標籤:android 開源項目 執行個體 動畫 源碼
轉載請註明本文出自大苞米的部落格(http://blog.csdn.net/a396901990),謝謝支援!
這裡貼幾個,我做了一個gif的動態圖,但是不知道為什麼上傳後圖片不動,所以只能放在相簿裡。
如果大家想看動態圖片示範請點擊後面的連結gif動態示範圖片
執行個體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中的代碼,很簡單。可以很輕鬆的改成自己想要的樣子,這裡不過多介紹。
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() {@Overridepublic 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中,因為正常點擊和長按點擊都會觸發觸摸事件
@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {//按下case MotionEvent.ACTION_DOWN: {.....return false;}//抬起case MotionEvent.ACTION_UP: {if (dismiss && c.isLongClickable()) {....}//將長按標示置為初始falsec.setLongClickable(false);break;}//滑動case MotionEvent.ACTION_MOVE: {if (mSwiping & c.isLongClickable()) {....return true;}break;}}如上面的虛擬碼中,在滑動和抬起操作時先判斷card中的長按標示。最後在抬起的時候將長按標示為重設為false,這樣就實現了長按操作
4.刪除後浮現一個懸浮button
首先要實現這個功能就要Crowdsourced Security Testing道刪除事件在哪,這樣才能添加相應功能。
if (dismiss && c.isLongClickable()) {// dismissanimate(mView).translationX(dismissRight ? mViewWidth : -mViewWidth).alpha(0).setDuration(mAnimationTime).setListener(new AnimatorListener() {@Overridepublic 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方法來顯示懸浮的點擊按鈕,這裡傳遞的有顯示的訊息和攜帶了刪除資訊的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回調方法。
@Overridepublic 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(); } }}實現很簡單:取出存放在UndoCard中的card和位置。把他重新添加到集合中,之後重新整理適配器重新顯示。
大概的對於這個開源項目的改進介紹完畢,本文只是提供一個思路,具體代碼細節建議還是看提供的demo。
刪除恢複功能是仿照cardsui這個開源項目實現的。涉及的類上面已經介紹了就是UndoCard和UndoBarController這兩個類,
最後我強烈建議好好的看看這兩個類和相關的調用方法,代碼不多而且設計的很好,值得研究一下。。。
Demo:點擊下載