首页 文章

Android - 滑动以在背景上关闭带有动画的RecyclerView

提问于
浏览
3

根据我的理解,实现使用刷卡项目下方背景的RecyclerView的滑动到解除的一种可能性(如在许多谷歌应用程序中)是实现ItemTouchHelper的简单回调并在方法onChildDraw中绘制背景 .

这是我的实施:

ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
    // create objects once and avoid allocating them in the onChildDraw method
    Drawable background;
    Drawable icon;
    int iconMargin;
    boolean initialized;

    private void init() {
        background = new ColorDrawable(Color.RED);
        icon = ContextCompat.getDrawable(mAppContext, R.drawable.ic_delete_white_24dp);
        iconMargin = (int) mAppContext.getResources().getDimension(R.dimen.fab_margin);
        initialized = true;
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        return false;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
        // remove swiped item from the list and notify the adapter
        int position = viewHolder.getAdapterPosition();
        mItemList.remove(position);
        mRecyclerViewAdapter.notifyDataSetChanged();
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            if (dX > 0) {
                View itemView = viewHolder.itemView;
                // if viewHolder has been swiped away, don't do anything
                if (viewHolder.getAdapterPosition() == -1) {
                    return;
                }
                if (!initialized) {
                    init();
                }
                // draw background
                int dXSwipe = (int) (dX * 1.05); // increase slightly dX to avoid view flickering, compensating loss of precision due to int conversion 
                background.setBounds(itemView.getLeft(), itemView.getTop(),
                itemView.getLeft() + dXSwipe, itemView.getBottom());
                background.draw(c);
                // draw icon
                int top = (itemView.getTop() + itemView.getBottom() - icon.getIntrinsicHeight()) / 2;
                int left = itemView.getLeft() + iconMargin;
                icon.setBounds(left, top, left + icon.getIntrinsicWidth(), top + icon.getIntrinsicHeight());
                icon.draw(c);
            }
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        }
    };
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
    itemTouchHelper.attachToRecyclerView(mRecyclerView);

现在,问题是如何在下面的背景中为视图设置动画 . 可以从Google日历中获取此动画的示例:当滑动事件或提醒时,左侧的图标将根据水平位移量进行放大 .

有谁知道如何实现这一目标?是否有必要采用不同的方法,可能在ViewHolder中有两个视图,如此处所提出的那样RecyclerView Swipe with a view below it

1 回答

  • 2

    我发现了怎么做 .

    对于那些感兴趣的人,解决方案是使用两个视图(前景和背景)并在滑动过程中为背景设置动画 .

    布局:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/item_delete_background">
    
        <ImageView
            android:id="@+id/item_delete_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="@dimen/fab_margin"
            android:layout_marginStart="@dimen/fab_margin"
            app:srcCompat="@drawable/ic_delete_white_24dp" />
    
        <android.support.constraint.ConstraintLayout
            android:id="@+id/item_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/gray_bg">
    
            <!--recyclerview item layout-->
    
        </android.support.constraint.ConstraintLayout>
    
    </FrameLayout>
    

    观点持有人:

    class MyViewHolder extends RecyclerView.ViewHolder {
        private ConstraintLayout mItemLayout;
        private ImageView mItemDeleteIcon;
    
        MyViewHolder(View v) {
            super(v);
            mItemLayout = (ConstraintLayout) v.findViewById(R.id.item_layout);
            mEventDeleteIcon = (ImageView) v.findViewById(R.id.item_delete_icon);
        }
    
        View getViewToSwipe() {
            return mItemLayout;
        }
    
        View getViewToAnimate() {
            return mItemDeleteIcon;
        }
    }
    

    和ItemTouchHelper回调:

    ItemTouchHelper.SimpleCallback mItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
    
        // override methods
    
        public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
                                    float dX, float dY,
                                    int actionState, boolean isCurrentlyActive) {
            // get the view which is currently swiped
            ConstraintLayout itemLayout = (ConstraintLayout) ((MyViewHolder) viewHolder).getViewToSwipe();
            // calculate relative horizontal displacement
            // with proportion dXRelative : 1 = dX : (layoutWidth / 3)
            float dXRelative = dX / itemLayout.getWidth() * 3;
            // check size boundaries
            if (dXRelative > 1) {
                dXRelative = 1;
            }
            if (dXRelative < 0) {
                dXRelative = 0;
            }
            // animate the icon with scaling on both dimensions
            ((MyViewHolder) viewHolder).getViewToAnimate().animate().scaleX(dXRelative).scaleY(dXRelative).setDuration(0).start();
            // call draw over
            getDefaultUIUtil().onDrawOver(c, recyclerView, ((MyViewHolder) viewHolder).getViewToSwipe(), dX, dY, actionState, isCurrentlyActive);
        }
    };
    

    在此帖子之后完成了基本行为(视图持有者中的前景/背景)的实现:Use ItemTouchHelper for Swipe-To-Dismiss with another View displayed behind the swiped out .

    希望这可能对某人有用 .

相关问题