Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果
轉(zhuǎn)載請(qǐng)注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877),請(qǐng)尊重他人的辛勤勞動(dòng)成果,謝謝!
今天還是給大家?guī)?lái)自定義控件的編寫(xiě),自定義一個(gè)ListView的左右滑動(dòng)刪除Item的效果,這個(gè)效果之前已經(jīng)實(shí)現(xiàn)過(guò)了,有興趣的可以看下Android 使用Scroller實(shí)現(xiàn)絢麗的ListView左右滑動(dòng)刪除Item效果, 之前使用的是滑動(dòng)類Scroller來(lái)實(shí)現(xiàn)的,但是看了下通知欄的左右滑動(dòng)刪除效果,確實(shí)很棒,當(dāng)我們滑動(dòng)Item超過(guò)一半的時(shí)候,item的透明度就變 成了0,我們就知道抬起手指的時(shí)候item就被刪除了,當(dāng)item的透明度不為0的時(shí)候,我們抬起手指Item會(huì)回到起始位置,這樣我們就知道拖動(dòng)到什么 位置item會(huì)刪除,什么位置Item不刪除,用戶體驗(yàn)更好了,還有一個(gè)效果,就是我們滑動(dòng)刪除了item的時(shí)候,ListView的其他item會(huì)出現(xiàn) 向上或者向下滾動(dòng)的效果,感覺(jué)效果很棒,所以在GitHub上面搜索了下,發(fā)現(xiàn)很多開(kāi)源庫(kù)都有這個(gè)效果,比如ListViewAnimations,?android-swipelistview等等,我看了下實(shí)現(xiàn)原理,使用的是Jake Wharton的動(dòng)畫(huà)開(kāi)源庫(kù)NineOldAndroids, 這個(gè)庫(kù)究竟是干嘛的呢?在API3.0(Honeycomb), SDK新增了一個(gè)android.animation包,里面的類是實(shí)現(xiàn)動(dòng)畫(huà)效果相關(guān)的類,通過(guò)Honeycomb API,能夠?qū)崿F(xiàn)非常復(fù)雜的動(dòng)畫(huà)效果,但是如果開(kāi)發(fā)者想在3.0以下使用這一套API, 則需要使用開(kāi)源框架Nine Old Androids,在這個(gè)庫(kù)中會(huì)根據(jù)我們運(yùn)行的機(jī)器判斷其SDK版本,如果是API3.0以上則使用Android自帶的動(dòng)畫(huà)類,否則就使用Nine Old Androids庫(kù)中,這是一個(gè)兼容庫(kù),接下來(lái)我們就來(lái)看看這個(gè)效果的具體實(shí)現(xiàn)吧
實(shí)現(xiàn)該效果的主要思路
?
?
大致的思路這是這四步,其中的一些細(xì)節(jié)接下來(lái)我會(huì)一一為大家解答的,接下來(lái)我們就用代碼來(lái)實(shí)現(xiàn)這種效果吧
首先我們新建一個(gè)工程,叫Swipedismisslistview,我們需要將Nine Old Androids這個(gè)庫(kù)引入到工程,大家可以去https://github.com/JakeWharton/NineOldAndroids下載,可以使用Jar包,也可以使用工程庫(kù)的形式引入到我們自己的工程,我們還需要自定義一個(gè)ListView,我們先看代碼然后給大家講解下具體的功能實(shí)現(xiàn)
1 package com.example.swipedismisslistview; 2 3 import static com.nineoldandroids.view.ViewHelper.setAlpha; 4 import static com.nineoldandroids.view.ViewHelper.setTranslationX; 5 import android.content.Context; 6 import android.util.AttributeSet; 7 import android.view.MotionEvent; 8 import android.view.VelocityTracker; 9 import android.view.View; 10 import android.view.ViewConfiguration; 11 import android.view.ViewGroup; 12 import android.widget.AdapterView; 13 import android.widget.ListView; 14 15 import com.nineoldandroids.animation.Animator; 16 import com.nineoldandroids.animation.AnimatorListenerAdapter; 17 import com.nineoldandroids.animation.ValueAnimator; 18 import com.nineoldandroids.view.ViewHelper; 19 import com.nineoldandroids.view.ViewPropertyAnimator; 20 /** 21 * @blog http://blog.csdn.net/xiaanming 22 * 23 * @author xiaanming 24 * 25 */ 26 public class SwipeDismissListView extends ListView { 27 /** 28 * 認(rèn)為是用戶滑動(dòng)的最小距離 29 */ 30 private int mSlop; 31 /** 32 * 滑動(dòng)的最小速度 33 */ 34 private int mMinFlingVelocity; 35 /** 36 * 滑動(dòng)的最大速度 37 */ 38 private int mMaxFlingVelocity; 39 /** 40 * 執(zhí)行動(dòng)畫(huà)的時(shí)間 41 */ 42 protected long mAnimationTime = 150; 43 /** 44 * 用來(lái)標(biāo)記用戶是否正在滑動(dòng)中 45 */ 46 private boolean mSwiping; 47 /** 48 * 滑動(dòng)速度檢測(cè)類 49 */ 50 private VelocityTracker mVelocityTracker; 51 /** 52 * 手指按下的position 53 */ 54 private int mDownPosition; 55 /** 56 * 按下的item對(duì)應(yīng)的View 57 */ 58 private View mDownView; 59 private float mDownX; 60 private float mDownY; 61 /** 62 * item的寬度 63 */ 64 private int mViewWidth; 65 /** 66 * 當(dāng)ListView的Item滑出界面回調(diào)的接口 67 */ 68 private OnDismissCallback onDismissCallback; 69 70 /** 71 * 設(shè)置動(dòng)畫(huà)時(shí)間 72 * 73 * @param mAnimationTime 74 */ 75 public void setmAnimationTime(long mAnimationTime) { 76 this.mAnimationTime = mAnimationTime; 77 } 78 79 /** 80 * 設(shè)置刪除回調(diào)接口 81 * 82 * @param onDismissCallback 83 */ 84 public void setOnDismissCallback(OnDismissCallback onDismissCallback) { 85 this.onDismissCallback = onDismissCallback; 86 } 87 88 public SwipeDismissListView(Context context) { 89 this(context, null); 90 } 91 92 public SwipeDismissListView(Context context, AttributeSet attrs) { 93 this(context, attrs, 0); 94 } 95 96 public SwipeDismissListView(Context context, AttributeSet attrs, 97 int defStyle) { 98 super(context, attrs, defStyle); 99 100 ViewConfiguration vc = ViewConfiguration.get(context); 101 mSlop = vc.getScaledTouchSlop(); 102 mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * 8; //獲取滑動(dòng)的最小速度 103 mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); //獲取滑動(dòng)的最大速度 104 } 105 106 107 @Override 108 public boolean onTouchEvent(MotionEvent ev) { 109 switch (ev.getAction()) { 110 case MotionEvent.ACTION_DOWN: 111 handleActionDown(ev); 112 break; 113 case MotionEvent.ACTION_MOVE: 114 return handleActionMove(ev); 115 case MotionEvent.ACTION_UP: 116 handleActionUp(ev); 117 break; 118 } 119 return super.onTouchEvent(ev); 120 } 121 122 /** 123 * 按下事件處理 124 * 125 * @param ev 126 * @return 127 */ 128 private void handleActionDown(MotionEvent ev) { 129 mDownX = ev.getX(); 130 mDownY = ev.getY(); 131 132 mDownPosition = pointToPosition((int) mDownX, (int) mDownY); 133 134 if (mDownPosition == AdapterView.INVALID_POSITION) { 135 return; 136 } 137 138 mDownView = getChildAt(mDownPosition - getFirstVisiblePosition()); 139 140 if (mDownView != null) { 141 mViewWidth = mDownView.getWidth(); 142 } 143 144 //加入速度檢測(cè) 145 mVelocityTracker = VelocityTracker.obtain(); 146 mVelocityTracker.addMovement(ev); 147 } 148 149 150 /** 151 * 處理手指滑動(dòng)的方法 152 * 153 * @param ev 154 * @return 155 */ 156 private boolean handleActionMove(MotionEvent ev) { 157 if (mVelocityTracker == null || mDownView == null) { 158 return super.onTouchEvent(ev); 159 } 160 161 // 獲取X方向滑動(dòng)的距離 162 float deltaX = ev.getX() - mDownX; 163 float deltaY = ev.getY() - mDownY; 164 165 // X方向滑動(dòng)的距離大于mSlop并且Y方向滑動(dòng)的距離小于mSlop,表示可以滑動(dòng) 166 if (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < mSlop) { 167 mSwiping = true; 168 169 //當(dāng)手指滑動(dòng)item,取消item的點(diǎn)擊事件,不然我們滑動(dòng)Item也伴隨著item點(diǎn)擊事件的發(fā)生 170 MotionEvent cancelEvent = MotionEvent.obtain(ev); 171 cancelEvent.setAction(MotionEvent.ACTION_CANCEL | 172 (ev.getActionIndex()<< MotionEvent.ACTION_POINTER_INDEX_SHIFT)); 173 onTouchEvent(cancelEvent); 174 } 175 176 if (mSwiping) { 177 // 跟誰(shuí)手指移動(dòng)item 178 ViewHelper.setTranslationX(mDownView, deltaX); 179 // 透明度漸變 180 ViewHelper.setAlpha(mDownView, Math.max(0f, Math.min(1f, 1f - 2f * Math.abs(deltaX)/ mViewWidth))); 181 182 // 手指滑動(dòng)的時(shí)候,返回true,表示SwipeDismissListView自己處理onTouchEvent,其他的就交給父類來(lái)處理 183 return true; 184 } 185 186 return super.onTouchEvent(ev); 187 188 } 189 190 /** 191 * 手指抬起的事件處理 192 * @param ev 193 */ 194 private void handleActionUp(MotionEvent ev) { 195 if (mVelocityTracker == null || mDownView == null|| !mSwiping) { 196 return; 197 } 198 199 float deltaX = ev.getX() - mDownX; 200 201 //通過(guò)滑動(dòng)的距離計(jì)算出X,Y方向的速度 202 mVelocityTracker.computeCurrentVelocity(1000); 203 float velocityX = Math.abs(mVelocityTracker.getXVelocity()); 204 float velocityY = Math.abs(mVelocityTracker.getYVelocity()); 205 206 boolean dismiss = false; //item是否要滑出屏幕 207 boolean dismissRight = false;//是否往右邊刪除 208 209 //當(dāng)拖動(dòng)item的距離大于item的一半,item滑出屏幕 210 if (Math.abs(deltaX) > mViewWidth / 2) { 211 dismiss = true; 212 dismissRight = deltaX > 0; 213 214 //手指在屏幕滑動(dòng)的速度在某個(gè)范圍內(nèi),也使得item滑出屏幕 215 } else if (mMinFlingVelocity <= velocityX 216 && velocityX <= mMaxFlingVelocity && velocityY < velocityX) { 217 dismiss = true; 218 dismissRight = mVelocityTracker.getXVelocity() > 0; 219 } 220 221 if (dismiss) { 222 ViewPropertyAnimator.animate(mDownView) 223 .translationX(dismissRight ? mViewWidth : -mViewWidth)//X軸方向的移動(dòng)距離 224 .alpha(0) 225 .setDuration(mAnimationTime) 226 .setListener(new AnimatorListenerAdapter() { 227 @Override 228 public void onAnimationEnd(Animator animation) { 229 //Item滑出界面之后執(zhí)行刪除 230 performDismiss(mDownView, mDownPosition); 231 } 232 }); 233 } else { 234 //將item滑動(dòng)至開(kāi)始位置 235 ViewPropertyAnimator.animate(mDownView) 236 .translationX(0) 237 .alpha(1) 238 .setDuration(mAnimationTime).setListener(null); 239 } 240 241 //移除速度檢測(cè) 242 if(mVelocityTracker != null){ 243 mVelocityTracker.recycle(); 244 mVelocityTracker = null; 245 } 246 247 mSwiping = false; 248 } 249 250 251 252 /** 253 * 在此方法中執(zhí)行item刪除之后,其他的item向上或者向下滾動(dòng)的動(dòng)畫(huà),并且將position回調(diào)到方法onDismiss()中 254 * @param dismissView 255 * @param dismissPosition 256 */ 257 private void performDismiss(final View dismissView, final int dismissPosition) { 258 final ViewGroup.LayoutParams lp = dismissView.getLayoutParams();//獲取item的布局參數(shù) 259 final int originalHeight = dismissView.getHeight();//item的高度 260 261 ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 0).setDuration(mAnimationTime); 262 animator.start(); 263 264 animator.addListener(new AnimatorListenerAdapter() { 265 @Override 266 public void onAnimationEnd(Animator animation) { 267 if (onDismissCallback != null) { 268 onDismissCallback.onDismiss(dismissPosition); 269 } 270 271 //這段代碼很重要,因?yàn)槲覀儾](méi)有將item從ListView中移除,而是將item的高度設(shè)置為0 272 //所以我們?cè)趧?dòng)畫(huà)執(zhí)行完畢之后將item設(shè)置回來(lái) 273 ViewHelper.setAlpha(dismissView, 1f); 274 ViewHelper.setTranslationX(dismissView, 0); 275 ViewGroup.LayoutParams lp = dismissView.getLayoutParams(); 276 lp.height = originalHeight; 277 dismissView.setLayoutParams(lp); 278 279 } 280 }); 281 282 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 283 @Override 284 public void onAnimationUpdate(ValueAnimator valueAnimator) { 285 //這段代碼的效果是ListView刪除某item之后,其他的item向上滑動(dòng)的效果 286 lp.height = (Integer) valueAnimator.getAnimatedValue(); 287 dismissView.setLayoutParams(lp); 288 } 289 }); 290 291 } 292 293 /** 294 * 刪除的回調(diào)接口 295 * 296 * @author xiaanming 297 * 298 */ 299 public interface OnDismissCallback { 300 public void onDismiss(int dismissPosition); 301 } 302 303 }看過(guò)Android 使用Scroller實(shí)現(xiàn)絢麗的ListView左右滑動(dòng)刪除Item效果你會(huì)發(fā)現(xiàn),這個(gè)自定義的SwipeDismissListView只重寫(xiě)了onTouchEvent()方法,其實(shí)我們重寫(xiě)這一個(gè)方法就能實(shí)現(xiàn)我們需要的效果
1. 我們先看手指按下屏幕的處理方法handleActionDown();該方法里面根據(jù)我們手指按下的點(diǎn)根據(jù)pointToPosition()方法來(lái)獲 取我們點(diǎn)擊的position,然后利用getChildAt()來(lái)獲取我們按下的item的View對(duì)象,并且加入手指在屏幕滑動(dòng)的速度檢查,這一步相 對(duì)來(lái)說(shuō)還是比較簡(jiǎn)單
2. 接下來(lái)就是手指在屏幕上面滑動(dòng)的處理方法handleActionMove(),這個(gè)方法就稍微的復(fù)雜些,我們需要根據(jù)手指在X軸的滑動(dòng)距離和Y軸的滑動(dòng) 距離來(lái)判斷是ListView?item的水平滑動(dòng)還是ListView的上下滑動(dòng),當(dāng)滿足Math.abs(deltaX) > mSlop && Math.abs(deltaY) < mSlop這個(gè)條件時(shí)候,我們用一個(gè)布爾值mSwiping來(lái)標(biāo)記Item現(xiàn)在處于水平滑動(dòng)的狀態(tài),這時(shí)候我們需要處理Item跟隨手指的滑動(dòng)而滑動(dòng)的邏 輯,我們使用ViewHelper來(lái)處理Item的滑動(dòng)邏輯,這個(gè)類會(huì)根據(jù)機(jī)器的SDK版本來(lái)判斷使用Android系統(tǒng)的API還是 NineOldandroids中自己實(shí)現(xiàn)的API使得View滑動(dòng)的效果,NineOldandroids中主要使用Camera(可以實(shí)現(xiàn)各種復(fù)雜動(dòng) 畫(huà)效果的類),我們直接使用ViewHelper的setTranslationX()和setAlpha()就實(shí)現(xiàn)了item滑動(dòng)和透明度漸變的效果, 為了使得我們?cè)诨瑒?dòng)item的時(shí)候,ListView不上下滾動(dòng),我們必須返回true來(lái)屏蔽ListView的上下滾動(dòng),這里需要我們要非常熟悉 Android的事件分發(fā)機(jī)制,這里我就不說(shuō)明了,大家不了解的去網(wǎng)上找找相關(guān)的文章看看
還有一個(gè)問(wèn)題,就是當(dāng)我們滑動(dòng)ListView的item的時(shí)候,會(huì)伴隨著item的點(diǎn)擊事件,這不是我們想要的效果,所以當(dāng)Item滑動(dòng)的時(shí)候我們需要取消ListView Item的點(diǎn)擊事件
?
3. 在看手指抬起的時(shí)候的處理方法handleActionUp(),這里面需要根據(jù)手指的滑動(dòng)速度或者Item移動(dòng)的距離來(lái)判斷Item是滑出屏幕還是滑動(dòng)至起始位置,并且要判斷item向左還是向右滑出屏幕等等邏輯,具體的邏輯可以看代碼,相信大家都看得懂.
我這里要說(shuō)說(shuō)ViewPropertyAnimator類,這個(gè)類能更好的實(shí)現(xiàn)一個(gè)View同時(shí)進(jìn)行多個(gè)動(dòng)畫(huà)的功能,當(dāng)然我們也可以使用ObjectAnimator利用AnimatorSet來(lái)實(shí)現(xiàn)一個(gè)View上的多個(gè)同時(shí)進(jìn)行的動(dòng)畫(huà)效果,例如我們可以將
1 ViewPropertyAnimator.animate(mDownView) 2 .translationX(dismissRight ? mViewWidth : -mViewWidth)//X軸方向的移動(dòng)距離 3 .alpha(0) 4 .setDuration(mAnimationTime) 5 .setListener(new AnimatorListenerAdapter() { 6 @Override 7 public void onAnimationEnd(Animator animation) { 8 //Item滑出界面之后執(zhí)行刪除 9 performDismiss(mDownView, mDownPosition); 10 } 11 });替換成
1 AnimatorSet set = new AnimatorSet(); 2 set.playTogether(ObjectAnimator.ofFloat(mDownView, "translationX", dismissRight ? mViewWidth : -mViewWidth), 3 ObjectAnimator.ofFloat(mDownView, "alpha", 0)); 4 set.setDuration(mAnimationTime).start(); 5 set.addListener(new AnimatorListenerAdapter() { 6 @Override 7 public void onAnimationEnd(Animator animation) { 8 //Item滑出界面之后執(zhí)行刪除 9 performDismiss(mDownView, mDownPosition); 10 } 11 });在效果上面是一樣的,但是ViewPropertyAnimator在性能上要比使用ObjectAnimator來(lái)實(shí)現(xiàn)多個(gè)同時(shí)進(jìn)行的動(dòng)畫(huà)要高的多,舉 個(gè)例子,假如要對(duì)View使用移動(dòng)和透明度的動(dòng)畫(huà),使用ViewPropertyAnimator的話,某個(gè)時(shí)間點(diǎn)上我們只需要調(diào)用一次 invalidate()方法刷新界面就行了,而使用ObjectAnimator的話,移動(dòng)的動(dòng)畫(huà)需要調(diào)用invalidate(),透明度的動(dòng)畫(huà)也需 要調(diào)用invalidate()方法,在性能上使用AnimationSet比ViewPropertyAnimator要低,但是有的時(shí)候我們還是需要 使用ObjectAnimator,比如,在某個(gè)時(shí)間內(nèi),我們需要將View先變大在變小在變大等復(fù)雜情況,這時(shí)候ObjectAnimator就派上用 場(chǎng)了,例如
1 ObjectAnimator.ofInt(mDownView, "scaleX", 0 ,100 ,0, 100).setDuration(100).start()通過(guò)上面的幾步我們就實(shí)現(xiàn)了ListView的左右滑動(dòng)刪除item的效果啦,但是還有一個(gè)效果,item刪除之后,ListView的其他 item向上或者向下緩緩滑動(dòng)的效果,實(shí)現(xiàn)這個(gè)也很容易,就是動(dòng)態(tài)設(shè)置item的高度,item高度逐漸變小,這樣其他的item就會(huì)出現(xiàn)向上或者向下擠 壓的效果啦!
?
4. 這里我們使用的是ValueAnimator這個(gè)類,這個(gè)類并不是針對(duì)View作用的動(dòng)畫(huà),而是對(duì)某個(gè)值作用的動(dòng)畫(huà),他默認(rèn)使用的 Interpolator(插補(bǔ)器)是AccelerateDecelerateInterpolator(開(kāi)始和結(jié)束的時(shí)候慢,中間快) ,?舉個(gè)很簡(jiǎn)單的例子,我們?cè)?0秒內(nèi)使用ValueAnimator將某個(gè)值從0變化到100,如果使用LinearInterpolator(線性插 補(bǔ)器,勻速變化)在第2秒的時(shí)候,這個(gè)值變成了20,而是用AccelerateDecelerateInterpolator,可能在第二秒的時(shí)候這個(gè) 值為15或者13,所以我們?cè)赩alueAnimator變化的時(shí)候設(shè)置值動(dòng)畫(huà)變化的監(jiān)聽(tīng)器AnimatorUpdateListener就知道某個(gè)時(shí)間 這個(gè)值變成了多少,從而對(duì)View的某個(gè)屬性進(jìn)行設(shè)置(例如大小),所以ValueAnimator是間接的對(duì)View設(shè)置動(dòng)畫(huà)的
了解了 ValueAnimator的使用原理,我們就可以現(xiàn)實(shí)上面的動(dòng)畫(huà)效果了,我們使用ValueAnimator將item的高度變成0,設(shè)置 ValueAnimator變化的監(jiān)聽(tīng),我們?cè)诨卣{(diào)函數(shù)onAnimationUpdate()中動(dòng)態(tài)的設(shè)置item的高度, 然后添加AnimatorListener監(jiān)聽(tīng)動(dòng)畫(huà)的狀態(tài)(例如動(dòng)畫(huà)開(kāi)始,結(jié)束,重復(fù)等)監(jiān)聽(tīng),在動(dòng)畫(huà)結(jié)束的回調(diào)函數(shù)onAnimationEnd()中 刪除該item的數(shù)據(jù),調(diào)用notifyDataSetChanged刷新ListView,看看下面這段代碼
1 ViewHelper.setAlpha(dismissView, 1f); 2 ViewHelper.setTranslationX(dismissView, 0); 3 ViewGroup.LayoutParams lp = dismissView.getLayoutParams(); 4 lp.height = originalHeight; 5 dismissView.setLayoutParams(lp);我們使用動(dòng)畫(huà)只是將item移動(dòng)出了屏幕,并且將item的高度設(shè)置為了0,并沒(méi)有將item的View從ListView中Remove掉,況且 ListView也不能直接Remove掉Item的,只能將數(shù)據(jù)源刪除,在調(diào)用notifyDataSetChanged()刷新,所以我們需要將剛剛 滑出屏幕高度設(shè)置為0的Item恢復(fù)回來(lái)
自定義控件的代碼我們已經(jīng)編寫(xiě)完了,接下來(lái)我們就要使用它了,先看界面的布局代碼
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <com.example.swipedismisslistview.SwipeDismissListView 7 android:id="@+id/swipeDismissListView" 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" 10 android:listSelector="@android:color/transparent" 11 android:cacheColorHint="@android:color/transparent"> 12 </com.example.swipedismisslistview.SwipeDismissListView> 13 14 </RelativeLayout>很簡(jiǎn)單,一個(gè)RelativeLayout包裹我們自定義的ListView控件,接下來(lái)就是主界面的代碼編寫(xiě),跟平常的ListView使用一樣,但是我們需要設(shè)置OnDismissCallback()監(jiān)聽(tīng),在
onDismiss()中刪除該位置對(duì)于的數(shù)據(jù),刷新ListView
1 package com.example.swipedismisslistview; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.app.Activity; 7 import android.os.Bundle; 8 import android.view.View; 9 import android.widget.AdapterView; 10 import android.widget.AdapterView.OnItemClickListener; 11 import android.widget.ArrayAdapter; 12 import android.widget.Toast; 13 14 import com.example.swipedismisslistview.SwipeDismissListView.OnDismissCallback; 15 16 public class SwipeActivity extends Activity { 17 private SwipeDismissListView swipeDismissListView; 18 private ArrayAdapter<String> adapter; 19 private List<String> dataSourceList = new ArrayList<String>(); 20 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_swipe); 25 init(); 26 } 27 28 private void init() { 29 swipeDismissListView = (SwipeDismissListView) findViewById(R.id.swipeDismissListView); 30 for (int i = 0; i < 20; i++) { 31 dataSourceList.add("滑動(dòng)刪除" + i); 32 } 33 34 adapter = new ArrayAdapter<String>(this, 35 android.R.layout.simple_list_item_1, 36 android.R.id.text1, dataSourceList); 37 38 swipeDismissListView.setAdapter(adapter); 39 40 swipeDismissListView.setOnDismissCallback(new OnDismissCallback() { 41 42 @Override 43 public void onDismiss(int dismissPosition) { 44 adapter.remove(adapter.getItem(dismissPosition)); 45 } 46 }); 47 48 49 swipeDismissListView.setOnItemClickListener(new OnItemClickListener() { 50 51 @Override 52 public void onItemClick(AdapterView<?> parent, View view, 53 int position, long id) { 54 Toast.makeText(SwipeActivity.this, adapter.getItem(position), Toast.LENGTH_SHORT).show(); 55 } 56 }); 57 58 } 59 60 }所有的代碼都已經(jīng)編寫(xiě)完畢了,接下來(lái)就是運(yùn)行工程,看看具體的效果是不是我們想要的
好 了,今天的講解到這里結(jié)束了,有了NineOldAndroids我們可以在2.x的手機(jī)上面實(shí)現(xiàn)許多復(fù)雜的動(dòng)畫(huà)效果,文章也介紹了關(guān)于開(kāi)源庫(kù) NineOldAndroids使用的一些知識(shí),文章有點(diǎn)長(zhǎng),希望讀者還是先將文章看下,然后自己看看能不能自己實(shí)現(xiàn)出來(lái),有什么不明白的地方請(qǐng)?jiān)谙旅媪?言,我會(huì)為大家解答的!
項(xiàng)目源碼,點(diǎn)擊下載
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/liangstudyhome/p/3920737.html
總結(jié)
以上是生活随笔為你收集整理的Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。