类似探探切换卡片,android 堆栈卡片,左滑添加右滑删除

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013597998/article/details/75282122

这个功能,网上相近的功能是有demo的,但是都不是我想要的。
所以,自己简单的写了一个。功能还很不完善,仅供参考。

效果如下:
这里写图片描述

这个控件,其实只用到ViewGroup的 child.layout()方法对子view进行排序跟动画。其他就是一些计算。数据设置通过adapter。

实现步骤分两步:
1.onLayout()通过缩放view,达到堆栈效果。这里用到 com.nineoldandroids:library:2.4.0 动画库,神器。

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // ①首先拿到所有的子view
        int count = getChildCount() > VisibleCardSize ? VisibleCardSize:getChildCount();
        for (int i = 0; i < count; i++) {
            View view = null;
            if (getChildCount() > count){
                view =  getChildAt(getChildCount() - count  + i);// 取得下标为i的子view
            }else {
                view =  getChildAt(i);
            }
            // ② 对子view进行排列,实际上就是需要调用子view的layout方法,四个参数分别对应 左、上、右、下
            if (isAddView && i == 0){
                view.layout(- getWidth(),150,0,650); //view添加进来的时候,由于是从外面慢慢滑进来,所以,刚开始放置在左边不可见
            }else {
                view.layout(0 ,150, getWidth(),getHeight() - 150);
            }
            ViewHelper.setScaleX(view, 0.8f + 0.03f*(i - count + 1));
            ViewHelper.setScaleY(view,0.8f + 0.03f*(i - count + 1));
            ViewHelper.setTranslationY(view,view.getMeasuredHeight() * 0.015f*(i - count + 1) -20*(count - 1 - i));
        }
    }

2.onTouchEvent()方法中进行手势处理。添加,跟删除操作。注释写的挺清楚的,这里就不多说。

private int firstX; //down时候的x轴坐标
    private boolean isAddView,isRemoveView; //区分是正在添加view还是删除
    private View addView; //正在被添加的view
    private View removeView; //正在被删除的view
    private View abandonView; //用于复用,被删除的view赋值给它,它不为空的时候,传给adapter的getView方法用于复用
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isScrolling){
           return true;
        }
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                firstX = (int) event.getRawX();
                break;
            case MotionEvent.ACTION_MOVE:
                int disX = (int) (event.getRawX() - firstX);
                if (Math.abs(disX) > mTouchSlop){
                    if (disX > 0){ //右滑,添加
                        isRemoveView = false;
                        if (!isAddView){ //防止多次add
                            if (mAdapter == null){
                                addView = getCardView();
                            }else {
                                if (currentPosition == 0){ //卡片滑到第0个的时候,在添加,取最后一个数据,这样就循环了
                                    addView = getInitLayoutView(mAdapter.getCount() - 1);
                                    currentPosition = TO_LAST_ONE;
                                }else {
                                    addView = getInitLayoutView(currentPosition - 1);
                                }
                            }
                            addView(addView);
                            addView.layout(- getWidth() + disX ,150,disX,getHeight() - 150);
                            isAddView = true;
                        }else {
                            addView.layout(- getWidth() + disX ,150,disX,getHeight() - 150); //移动
                        }
                    }else {
                        int i = getChildCount() -1;
                        isRemoveView = true;
                        removeView = getChildAt(i);
                        removeView.layout(disX,150, getWidth() + disX,getHeight() - 150);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (isRemoveView){ //删除操作
                    isRemoveView = false;
                    if (removeView.getRight() < getWidth()*2/3){ //滑动到2/3位置往左,算删除,否则,回弹不删
                        smoothRemoveView(removeView); //动画
                        if (currentPosition == mAdapter.getCount() - 1){ //删除最后一个后,回到第0个
                            currentPosition = 0;
                        }else {
                            currentPosition +=1;
                        }

                        //删除一个view后,如果总的childView比VisibleCardSize小,则在最后面补充
                        ThreadHandler.postUiThread(new Runnable() {
                            @Override
                            public void run() {  //延时的原因是,动画如果还没做完,就还没有执行removeView,getChildCount就不准确(多一),
                                // 这样以下if就不成立,无法添加
                                if (getChildCount() < VisibleCardSize){
                                    View view;
                                    if (currentPosition + VisibleCardSize > mAdapter.getCount()){ //刚好如果currentPosition是后面几个,则回到0,这样就循环了
                                        view = getInitLayoutView(VisibleCardSize - (mAdapter.getCount() - currentPosition) - 1);
                                    }else {
                                        view = getInitLayoutView(currentPosition + VisibleCardSize - 1);
                                    }
                                    ViewHelper.setScaleX(view, 0.68f);
                                    ViewHelper.setScaleY(view,0.68f);
                                    ViewHelper.setTranslationY(view,view.getMeasuredHeight() * 0.06f -80);
                                    addView(view,0);
                                }
                            }
                        },600);
                    }else {
                        anotherSmoothScroll(removeView.getLeft(),removeView.getRight(), - removeView.getLeft(),getWidth()  - removeView.getRight(),removeView,false);
                    }
                }else if (isAddView){
                    isAddView = false;
                    if (addView.getRight() > getWidth()/3){ //大于1/3才算添加,否则回弹
                        if (currentPosition == TO_LAST_ONE){ //如果当前是在位置0.添加卡片的时候,就赋值为TO_LAST_ONE
                            // ,添加成功后,则当前位置就是最后一个
                            currentPosition = mAdapter.getCount() -1;
                        }else {
                            currentPosition -=1;
                        }
                        anotherSmoothScroll(addView.getLeft(),addView.getRight(), - addView.getLeft(),getWidth() - addView.getRight(),addView,false);
                        ThreadHandler.postUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (getChildCount() > VisibleCardSize){  //ChildView总数大于VisibleCardSize时,最后面一个不可见的view,将被移除,同时用于复用
                                    abandonView = getChildAt(0);
                                    removeViewAt(0);
                                }
                            }
                        },600);
                    }else {
                        if (currentPosition == TO_LAST_ONE){ //位置为0时,没添加成功。
                            currentPosition = 0;
                        }
                        smoothRemoveView(addView);
                    }
                }
                break;

            default:
                break;
        }
        return true;
    }

这是源码,欢迎指教:(http://download.csdn.net/download/u013597998/9897895)`

猜你喜欢

转载自blog.csdn.net/u013597998/article/details/75282122