• Android之淘宝商品列表长按遮罩效果


    先来看看淘宝、唯品会长按商品的效果,以及简单Demo的效果:

             

     

    首先分析一下场景:

    1. 长按条目时,弹出遮罩的效果遮挡在原来的条目布局上;
    2. 页面滑动或点击其他的条目,上一个正在遮罩的条目遮罩消失。
    3. 长按其他条目时,上一个遮罩的条目撤销遮罩,当前长按的显示遮罩;
    4. 条目添加遮罩的时添加动画;

    1. 遮罩的效果,我们会很容易的想到Android布局控件FrameLayout布局,是基于叠加在上方的布局。所以在列表条目布局的时候,可以使用FrameLayout布局,在长按列表条目时,用条目的根布局添加一个遮罩的布局,就达到我们想要的效果了。

    2. 记录当前长按的根布局,如果点击或长按其他的列表条目,亦或滑动页面(添加活动监听)时,就取消之前长按的条目遮罩,从条目根布局中删除遮罩布局就OK了;

    3. 可以利用View动画或属性动画,在添加遮罩布局时显示动画;

     接下来, 来撸一下代码吧:

     1. 首先,先定义一下遮罩的布局,根据需求自定义View

    /***
     * 长按条目遮罩界面
     */
    public class ItemMaskLayout extends LinearLayout {
    
        public ItemMaskLayout(Context context) {
            this(context, null);
        }
    
        public ItemMaskLayout(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public ItemMaskLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            LayoutInflater.from(context).inflate(R.layout.layout_product_list_item_mask, this, true);
    
            findViewById(R.id.tv_find_same).setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mItemMaskClickListener != null) {
                        mItemMaskClickListener.findTheSame();
                    }
                }
            });
    
            findViewById(R.id.tv_collection).setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mItemMaskClickListener != null) {
                        mItemMaskClickListener.collection();
                    }
                }
            });
        }
    
        public ItemMaskClickListener mItemMaskClickListener;
    
        public void setMaskItemClickListener(ItemMaskClickListener listener) {
            this.mItemMaskClickListener = listener;
        }
    
        //提供遮罩中按钮点击操作接口  自定义
        public interface ItemMaskClickListener {
            void findTheSame();
            void collection();
        }
    }

    2. 封装一个帮助类,主要是根据该类的成员变量根据长按的条目指向列表Item的布局,然后为条目添加遮罩的效果;

    /**
     * 长按条目添加遮罩操作帮助类
     */
    public class ItemLongClickMaskHelper {
    
        private FrameLayout mRootFrameLayout;
        private ItemMaskLayout mMaskItemLayout;
        private Context mContext;
        private ScaleAnimation anim;
        private String productId;
    
        public ItemLongClickMaskHelper(Context context){
            this.mContext = context;
            mMaskItemLayout = new ItemMaskLayout(mContext);
            anim = new ScaleAnimation(
                    0f, 1.0f, 1.0f, 1.0f,
                    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f
            );
            anim.setDuration(300);
            mMaskItemLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dismissItemMaskLayout();
                }
            });
    
            mMaskItemLayout.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    dismissItemMaskLayout();
                    return true;
                }
            });
    
            mMaskItemLayout.setMaskItemClickListener(new ItemMaskLayout.ItemMaskClickListener() {
                @Override
                public void findTheSame() {
                    ToastUtil.showCustomToast("找相似 " + productId);
                }
    
                @Override
                public void collection() {
                    ToastUtil.showCustomToast("收藏 " + productId);
                }
            });
        }
    
        public ItemLongClickMaskHelper setRootFrameLayout(FrameLayout frameLayout, String fundId){
            if (mRootFrameLayout != null){
                mRootFrameLayout.removeView(mMaskItemLayout);
            }
            mRootFrameLayout = frameLayout;
            this.productId = fundId;
            mRootFrameLayout.addView(mMaskItemLayout);
            mMaskItemLayout.startAnimation(anim);
            return this;
        }
    
        public ItemLongClickMaskHelper setMaskItemListener(ItemMaskLayout.ItemMaskClickListener listener){
            this.mMaskItemLayout.setMaskItemClickListener(listener);
            return this;
        }
    
        /**
         * 遮罩消失
         */
        public void dismissItemMaskLayout(){
            if (mRootFrameLayout != null){
                mRootFrameLayout.removeView(mMaskItemLayout);
            }
        }
    }

    3.注意在滑动RecyclerView列表的时候,监听滑动,撤销遮罩,直接定义RecyclerView的子类,添加滑动监听回调;

    public class TouchCallbackRecyclerView extends RecyclerView {
        
        public TouchCallbackRecyclerView(Context context) {
            super(context);
        }
    
        public TouchCallbackRecyclerView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public TouchCallbackRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public interface ScrollCallback {
            /**
             * 滑动手指抬起事件
             *
             * @param diffY 抬起时相对于按下时的偏移量<br/>大于0:列表往下拉, 小于0: 列表往上拉
             */
            void onTouchUp(float diffY);
        }
    
        private ScrollCallback mScrollCallback;
    
        public void setScrollCallback(ScrollCallback callback) {
            this.mScrollCallback = callback;
        }
    
        private float mDownY, mMovingY, mUpY;
        private boolean isUp = false;
    
        @SuppressWarnings("deprecation")
        private static final float SLOP = ViewConfiguration.getTouchSlop();
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mDownY = ev.getY();
                    isUp = false;
    
                    break;
                case MotionEvent.ACTION_MOVE:
                    mMovingY = ev.getY();
                    isUp = false;
                    break;
                case MotionEvent.ACTION_UP:
                    mUpY = ev.getY();
                    isUp = true;
                    break;
            }
            if (isUp && mScrollCallback != null && Math.abs(mUpY - mDownY) > SLOP) {
                mScrollCallback.onTouchUp(mMovingY - mDownY);
            }
            return super.dispatchTouchEvent(ev);
        }
    }

    以上就是主要的代码实现部分,灵活地扩展应用ItemLongClickMaskHelper基本就能实现类似淘宝长按遮罩效果了。

    源码地址:https://github.com/denluoyia/ItemLongClickMaskDemo

  • 相关阅读:
    APP与智能手表是如何通信的【本文摘抄自深圳尚锐科技】
    flash添加超链接的办法
    NPOI使用手册
    如何在 SQL Server 实例之间传输登录和密码
    CentOS 7 上部署Mono 4 和Jexus 5.6
    django models 中choices之用法举例
    django中的objects.get和objects.filter方法的区别
    Django中的Model.objects.create() 和 Model() 的区别?
    python爬虫练手项目快递单号查询
    根据现有的数据库自动生成Django model
  • 原文地址:https://www.cnblogs.com/denluoyia/p/9006223.html
Copyright © 2020-2023  润新知