android 堆栈卡片,左滑添加右滑删除

来源:互联网 发布:linux安装jdk1.8 rpm 编辑:程序博客网 时间:2024/05/29 19:35

这个功能,网上相近的功能是有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)`