Android动画化recyclerview

4
我创建了一个带有“事件”列表的recyclerview。对于小于5个事件的事件列表,它可以正常工作。但是,一旦事件列表中的事件数量超过6个,最后一个事件在被点击后不会展开,而是消失。当事件列表中的事件超过6个时,关闭动画也停止工作。
应该的行为:
- 用户点击事件,视图展开到全屏状态 - 用户点击已展开的事件,视图回缩到原始大小 - 当另一个事件已经展开时,用户点击事件,展开的事件返回原始高度,并将点击的事件扩大到全屏状态
当前的行为:
- 用户点击事件,除了列表中的最后一项之外,所有视图都会正确展开 - 用户点击已展开的事件,视图会回缩但没有动画效果 - 当另一个事件已经展开时,用户点击事件,展开的事件回缩并且点击的事件正确扩大到全屏状态 - 用户点击列表中的最后一个事件,该事件会消失(可能已经缩小到小于0)
我知道这可能与recyclerview在屏幕上不可见时如何重用其视图的方式有关。为了解决此问题,我检查了eventId而不是列表中的位置来确定所点击的事件的位置,但这仍然存在上述问题。
public class EventRecyclerAdapter extends RecyclerView.Adapter<EventRecyclerAdapter.ViewHolder> {
    private Context c;
    private List<Event> items = new ArrayList<>();
    private RelativeLayout container;
    private int screenheight;
    private EventListFragment eventListFragment;
    private int expandedPosition = -1;
    private static final String TAG = "EventRecyclerAdapter";

    public interface ItemClickedListener {
        void itemClicked(int position);
    }

    private ItemClickedListener itemClickedListener;

    public EventRecyclerAdapter(List<Event> itemlist, Context c, EventListFragment eventListFragment, ItemClickedListener listener) {
        this.items = itemlist;
        this.c = c;
        this.eventListFragment = eventListFragment;
        this.itemClickedListener = listener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, null);

        WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        screenheight = size.y;

        // Get the screen height from the device
        Resources r = c.getResources();
        float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, r.getDisplayMetrics());
        screenheight -= px;

        ViewHolder viewHolder = new ViewHolder(itemLayoutView);
        return viewHolder;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int position) {
        Event event = items.get(position);
        // - get data from your itemsData at this position
        // - replace the contents of the view with that itemsData
        viewHolder.tvName.setText(event.getName());
        viewHolder.tvLocation.setText(event.getLocation().getName());
        viewHolder.tvDate.setText(Helper.dateDoubleToString(event.getStartDate()));
        viewHolder.tvTicketCount.setText(String.valueOf(event.getNumberOfTickets()));
        viewHolder.background.setBackgroundColor(Color.GRAY);
        viewHolder.eventId = event.getId();

        // Load the background image
        if (event.getEventImageId() != null) {
            Picasso.with(c).load(Helper.imageUrlString(event.getEventImageId())).into(viewHolder.background);
            ColorMatrix matrix = new ColorMatrix();
            matrix.setSaturation(0);

            ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
            viewHolder.background.setColorFilter(filter);
        }

        // Check if the view needs to be expanded, collapsed or just drawn normally.
        if (expandedPosition == event.getId()) {
            if (event.expanded) {
                collapseView(viewHolder, event);
            } else if (!event.expanded) {
                expandView(viewHolder, position, event);
            }
        } else {
            setContainerHeight(viewHolder, event);
        }
    }

    private void expandView(final EventRecyclerAdapter.ViewHolder viewHolder, final int pos, Event event) {
        ResizeAnimation resizeAnimation = new ResizeAnimation(
                viewHolder.container,
                viewHolder.container.getHeight(),
                screenheight
        );
        resizeAnimation.setDuration(Constants.ANIMATION_SPEED);
        resizeAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                viewHolder.infoContainer.setVisibility(View.VISIBLE);
                viewHolder.closeIcon.setVisibility(View.VISIBLE);
                itemClickedListener.itemClicked(pos);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        viewHolder.itemView.startAnimation(resizeAnimation);
        viewHolder.expanded = true;

        event.expanded = true;
    }

    private void collapseView(final EventRecyclerAdapter.ViewHolder viewHolder, Event event) {
        ResizeAnimation resizeAnimation = new ResizeAnimation(
                viewHolder.container,
                viewHolder.container.getHeight(),
                getContainerCollapsedHeight()
        );
        resizeAnimation.setDuration(Constants.ANIMATION_SPEED);

        viewHolder.infoContainer.setVisibility(View.INVISIBLE);
        viewHolder.closeIcon.setVisibility(View.INVISIBLE);
        viewHolder.itemView.startAnimation(resizeAnimation);
        viewHolder.expanded = false;
        event.expanded = false;
}

    private void setContainerHeight(EventRecyclerAdapter.ViewHolder viewHolder, Event event) {
        viewHolder.container.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getContainerCollapsedHeight()));
        viewHolder.infoContainer.setVisibility(View.INVISIBLE);
        viewHolder.closeIcon.setVisibility(View.INVISIBLE);
        event.expanded = false;
        viewHolder.expanded = false;
    }

    private int getContainerCollapsedHeight() {
        int containerHeight;
        // Define the item containers height
        if (items.size() <= 3) {
            containerHeight = screenheight / items.size();
        } else {
            containerHeight = screenheight / 3;
        }
        return containerHeight;
    }

    /**
     * Clear all current data and swap add the new data list.
     * The expanded position also gets reset
     * @param events
     */
    public void swap(List<Event> events) {
        this.items.clear();
        this.items.addAll(events);
        this.expandedPosition = -1;

        Log.v(TAG,"SWAP SIZE : " + items.size());
        notifyDataSetChanged();
    }

    // inner class to hold a reference to each item of RecyclerView
    class ViewHolder extends RecyclerView.ViewHolder {

        public TextView tvLocation, tvDate, tvTicketCount;
        public TextView tvName;
        public ImageView background;
        public View container;
        public View infoContainer;
        public TextView closeIcon;
        public int eventId;
        public boolean expanded = false;

        public ViewHolder(final View itemLayoutView) {
            super(itemLayoutView);

            tvName = (TextView) itemLayoutView.findViewById(R.id.tvName);
            tvLocation = (TextView) itemLayoutView.findViewById(R.id.tvLocation);
            tvDate = (TextView) itemLayoutView.findViewById(R.id.tvDate);
            background = (ImageView) itemLayoutView.findViewById(R.id.background);
            tvTicketCount = (TextView) itemLayoutView.findViewById(R.id.ticket_count);
            container = itemLayoutView.findViewById(R.id.list_item_container);
            infoContainer = itemLayoutView.findViewById(R.id.info_container);
            closeIcon = (TextView) itemLayoutView.findViewById(R.id.close_icon);

            infoContainer.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Activity mainActivity = (Activity) c;
                    FragmentManager fm = mainActivity.getFragmentManager();
                    //add
                    FragmentTransaction ft = fm.beginTransaction();
                    ft.setCustomAnimations(R.animator.slide_to_top, R.animator.slide_from_bottom);
                    ft.addToBackStack(ft.toString());
                    ft.add(R.id.content_frame, EventFragment.newInstance(items.get(getAdapterPosition())), Constants.EVENT_FRAGMENT_TAG);
                    //commit change
                    ft.commit();
                }
            });

            container.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    expandedPosition = eventId;
                    notifyDataSetChanged();
                }
            });
        }
    }

    // Return the size of your itemsData (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return items.size();
    }
}

我认为当我点击列表中的最后一项时,它会以某种方式运行collapseView方法,导致其高度低于0。但是我无法弄清楚这是为什么。

希望有人能够发现问题所在。

1个回答

0

你可以在RecycleView项的OnClilck中尝试这个。

@Override
public void onClick(View view)
{
LayoutParams params = view.getLayoutParams();
     if (!large)
        {
            params.height = 2 * view.getHeight();     
        } else {
            params.height = view.getHeight()/2;
        }
        large = !large;
        view.setLayoutParams(params);
} 

谢谢您的回复,但我不想在活动之间进行转换。它只应该将行的高度增加到全屏幕的高度,用户仍然可以滚动查看列表的其余部分。 - Dave Tolboom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接