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

时间:2022-03-31 23:43:02

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

效果如下:
android 堆栈卡片,左滑添加右滑删除

这个控件,其实只用到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)`