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

原文:地址

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章