zoukankan      html  css  js  c++  java
  • 可删除超炫&多种特效的Card视图(改造自cardsui-for-android开源项目),提供DEMO下载

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990)。谢谢支持!

          



    实例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;
                            }
                        });
            }
        }
    

    这里主要关注showUndoBarhideUndoBarUndoBarController这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点击下载





  • 相关阅读:
    String类可以被继承吗?我们来聊聊final关键字!
    微信小程序中使用阿里ICON图标
    兼容iphone x刘海的正确姿势
    解决ios下部分手机在input设置为readonly属性时,依然显示光标
    react jsx 中使用 switch case 示例
    react 中使用 JsBarcode 显示条形码
    解决IDEA输入法输入中文候选框不显示问题
    svn提交代码失败提示清理(清理失败并且报错信息乱码解决办法)
    css笔记
    修改Mysql数据库的字符集
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5118495.html
Copyright © 2011-2022 走看看