实例Demo下载地址在本文最后
简介
这个Demo主要是使用了cardsui-for-android开源项目,而且做了一些优化和改进:
1.自己定义card视图
2.加入长按事件。避免误操作
3.长按后能够删除card,并播放选中动画
4.删除后浮现一个悬浮button
5.点击悬浮button能够恢复之前删除的card视图
看内容前强烈建议先阅读下面的两篇文章,由于这个demo是在这两个文章的基础上写的:
关于cardsui-for-android这个开源项目的介绍和实现请看这篇博文酷炫开源项目cardsui-for-android-超具体源代码分析,具体解释所用特效是怎样实现的
4,5功能是參照开源项目cardslib。对这个开源项目的导入和简介请看这篇博文开源项目cardslib简介和导入eclipse并执行的方法
接下来对于以上的5个改进简介:(本文仅仅是提供一个思路,详细代码细节建议还是看提供的demo)
1.自己定义card视图
这里仅仅是简单的对于不同的card设置了不同的背景颜色:
CardStack stack = new CardStack(this); stack.setTitle("请支持大苞米的博客"); for (int i = 0; i < 5; i++) { MyCard card = null ; switch (i) { case 0: card = new MyCard("#FFBB33"); break; case 1: card = new MyCard("#98CC00"); break; case 2: card = new MyCard("#A966CC"); break; case 3: card = new MyCard("#33B4E4"); break; case 4: card = new MyCard("#FF4343"); break; } stack.add(card); } mCardView.addStack(stack);
MyCard类就是我自己定义的一个继承自card类的一个实现类,详细实现请看demo中的代码,非常easy。能够非常轻松的改成自己想要的样子,这里只是多介绍。
2.加入长按事件,避免误操作
3.长按后能够删除card。并播放选中动画
在CardStack中getView()方法中能够设置对card的点击监听
//正常点击监听 cardView.setOnClickListener(getClickListener(this, container, i)); //长按点击监听 cardView.setOnLongClickListener(getOnLongClickListener(card)); //触摸监听 cardView.setOnTouchListener(new SwipeDismissTouchListener( cardView, card, i, new OnDismissCallback() { @Override public void onDismiss(View view, Object token, int index) { .... } } }
长按点击监听getOnLongClickListener()的实现:
//改监听传入被按的card作为引用 private OnLongClickListener getOnLongClickListener(final Card card) { return new OnLongClickListener() { @Override public boolean onLongClick(View v) { //给card设置一个flag,标识这个card被长按过了 card.setLongClickable(true); //播放动画 Animation shake = AnimationUtils.loadAnimation(mContext , R.anim.shake); v.startAnimation(shake); return false; } }; }
这个动画是一个左右来回摆动的动画,详细实现能够去代码里找,这里只是多介绍了。
这里注意长按监听里最后返回false。这里在之前的那篇文章详介绍了,作用就是将事件接着交给ontouch监听处理。
接下来看看给card设好标识位后来到onTouchListener中。由于正常点击和长按点击都会触发触摸事件
@Override public boolean onTouch(View view, MotionEvent motionEvent) { //按下 case MotionEvent.ACTION_DOWN: { ..... return false; } //抬起 case MotionEvent.ACTION_UP: { if (dismiss && c.isLongClickable()) { .... } //将长按标示置为初始false c.setLongClickable(false); break; } //滑动 case MotionEvent.ACTION_MOVE: { if (mSwiping & c.isLongClickable()) { .... return true; } break; } }
如上面的伪代码中。在滑动和抬起操作时先推断card中的长按标示。最后在抬起的时候将长按标示为重置为false,这样就实现了长按操作
4.删除后浮现一个悬浮button
如图:
首先要实现这个功能就要先知道删除事件在哪,这样才干加入对应功能。
if (dismiss && c.isLongClickable()) { // dismiss animate(mView) .translationX(dismissRight ? mViewWidth : -mViewWidth) .alpha(0).setDuration(mAnimationTime) .setListener(new AnimatorListener() { @Override public void onAnimationEnd(Animator arg0) { //运行删除操作 performDismiss(); } }); }
删除事件在上面介绍的触摸监听中滑动操作里面。假设能够删除,则先播放一段删除动画。在动画结束的回调方法中运行performDismiss()方法。
该方法运行删除的回调方法mCallback.onDismiss(mView, mToken, mIndex);,该回调方法的详细实如今最開始为card设置触摸监听的地方。
cardView.setOnTouchListener(new SwipeDismissTouchListener( cardView, card, i, new OnDismissCallback() { @Override public void onDismiss(View view, Object token, int index) { Card c = (Card) token; // call onCardSwiped() listener c.OnSwipeCard(); cards.remove(c); mAdapter.setItems(mStack, getPosition()); // refresh(); mAdapter.notifyDataSetChanged(); //Check for a undo message to confirm if (isEnableUndo() && mUndoBarController!=null){ //Show UndoBar UndoCard itemUndo=new UndoCard(c , index); if (mContext!=null){ Resources res = mContext.getResources(); if (res!=null){ int number = index+1; String messageUndoBar = "确认要删除第"+number+"个card视图吗?"; mUndoBarController.showUndoBar( false, messageUndoBar, itemUndo); } } } } }));
回调方法中先从cards集合中删除这个card。之后把这个删除的card和他的位置传递给UndoCard类。之后通过UndoBarController.showUndoBar方法来显示悬浮的点击button,这里传递的有显示的消息和携带了删除信息的UndoCard类。
之后来简单看下UndoBarController类:
public UndoBarController(View undoBarView, UndoListener undoListener,UndoBarUIElements undoBarUIElements) { mBarView = undoBarView; mBarAnimator = mBarView.animate(); mUndoListener = undoListener; if (undoBarUIElements==null) undoBarUIElements = new DefaultUndoBarUIElements(); mUndoBarUIElements = undoBarUIElements; mMessageView = (TextView) mBarView.findViewById(mUndoBarUIElements.getUndoBarMessageId()); mBarView.findViewById(mUndoBarUIElements.getUndoBarButtonId()) .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { hideUndoBar(false); mUndoListener.onUndo(mUndoToken); } }); hideUndoBar(true); } @SuppressLint("NewApi") public void showUndoBar(boolean immediate, CharSequence message, Parcelable undoToken) { mUndoToken = undoToken; mUndoMessage = message; mMessageView.setText(mUndoMessage); mHideHandler.removeCallbacks(mHideRunnable); mHideHandler.postDelayed(mHideRunnable, 5000); mBarView.setVisibility(View.VISIBLE); if (immediate) { mBarView.setAlpha(1); } else { mBarAnimator.cancel(); mBarAnimator .alpha(1) .setDuration( mBarView.getResources() .getInteger(android.R.integer.config_shortAnimTime)) .setListener(null); } } @SuppressLint("NewApi") public void hideUndoBar(boolean immediate) { mHideHandler.removeCallbacks(mHideRunnable); if (immediate) { mBarView.setVisibility(View.GONE); mBarView.setAlpha(0); mUndoMessage = null; mUndoToken = null; } else { mBarAnimator.cancel(); mBarAnimator .alpha(0) .setDuration(mBarView.getResources() .getInteger(android.R.integer.config_shortAnimTime)) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mBarView.setVisibility(View.GONE); mUndoMessage = null; mUndoToken = null; } }); } }
这里主要关注showUndoBar,hideUndoBar,UndoBarController这3个方法
showUndoBar和hideUndoBar主要就是控制显示这个悬浮button。这个button的布局在代码中事先已经加入好,这两个方法中设置它的Visibility属性就能够控制隐藏和显示。
5.点击悬浮button能够恢复之前删除的card视图
接上面。UndoBarController方法中有一个监听器,能够监听悬浮button的点击事件:
mBarView.findViewById(mUndoBarUIElements.getUndoBarButtonId()) .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { hideUndoBar(false); mUndoListener.onUndo(mUndoToken); } });
点击后隐藏这个button,之后运行onUndo方法来恢复被删除的card。
(mUndoToken中携带的就是被删除的Card还有他位置信息的UndoCard类)。
public interface UndoListener { /* * Called when you undo the action */ void onUndo(Parcelable undoToken); }
这个监听器是一个接口。以下要做的就是找到实现mUndoListener.onUndo(mUndoToken)这个监听回调方法的地方。
public class CardStack extends AbstractCard implements UndoBarController.UndoListener
实现这个接口的就是我们的CardStack这个类了。接下来在类中找到onUndo回调方法。
@Override public void onUndo(Parcelable undoToken) { //Restore items in lists (use reverseSortedOrder) if (undoToken != null) { UndoCard item = (UndoCard) undoToken; Card card = item.card; int position = item.position; if (card != null) { add(card, position); mAdapter.notifyDataSetChanged(); } } }
实现非常easy:取出存放在UndoCard中的card和位置。把他又一次加入到集合中,之后刷新适配器又一次显示。
大概的对于这个开源项目的改进介绍完成。本文仅仅是提供一个思路,详细代码细节建议还是看提供的demo。
删除恢复功能是仿照cardsui这个开源项目实现的。涉及的类上面已经介绍了就是UndoCard和UndoBarController这两个类。
最后我强烈建议好好的看看这两个类和相关的调用方法。代码不多并且设计的非常好,值得研究一下。。
。
Demo下载地址:
Github:https://github.com/a396901990/CardList/tree/master
csdn点击下载