原文:http://blog.csdn.net/singwhatiwanna/article/details/17515543 java
最近公司項目需用到微信滑動拉出按鈕的效果,發現一位牛人已經實現了相關效果,但控件仍與業務代碼存有耦合,因而花了點時間作了些去耦合,並於此進行記錄,以防遺忘。 android
我的認爲耦合主要在於兩點: 緩存
第一點是SlideListView中的onTouchEvent 微信
經過獲取item間接獲得SlideView,但這樣會引入外部數據類MessageItem。 app
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { int x = (int) event.getX(); int y = (int) event.getY(); //咱們想知道當前點擊了哪一行 int position = pointToPosition(x, y); Log.e(TAG, "postion=" + position); if (position != INVALID_POSITION) { //獲得當前點擊行的數據從而取出當前行的item。 //可能有人懷疑,爲何要這麼幹?爲何不用getChildAt(position)? //由於ListView會進行緩存,若是你不這麼幹,有些行的view你是得不到的。 MessageItem data = (MessageItem) getItemAtPosition(position); mFocusedItemView = data.slideView; Log.e(TAG, "FocusedItemView=" + mFocusedItemView); } } default: break; } ... }
本人認爲將如下代碼 ide
int position = pointToPosition(x, y); if (position != INVALID_POSITION) { MessageItem data = (MessageItem) getItemAtPosition(position); mFocusedItemView = data.slideView; }
修改成: post
int position = pointToPosition(x, y); if (position != INVALID_POSITION) { int firstPos = getFirstVisiblePosition(); mSlideView = (SlideView) getChildAt(position - firstPos); }
便可。因爲pointToPosition返回的是ListView全部item中被點擊的item的position,而listview只會緩存可見的item,所以getChildAt()的時候,須要經過減去getFirstVisiblePosition()來計算被點擊的item在可見items中的位置。如此則可以去掉外部數據類MessageItem給控件帶來的耦合,同時MessageItem再也不須要內部成員slideView。 字體
public class MessageItem { public int iconRes; public String title; public String msg; public String time; }
第二點是slide_view_merge.xml中holder的寬度被固定爲120dp this
<?xml version="1.0" encoding="utf-8"?> <merge ... <RelativeLayout android:id="@+id/holder" android:layout_width="120dp" android:layout_height="match_parent" android:clickable="true" android:background="@drawable/holder_bg"> ... </RelativeLayout> </merge>
SlideView初始化時再次計算其寬度 spa
SlideView.java:
private void initView() { mContext = getContext(); // 初始化彈性滑動對象 mScroller = new Scroller(mContext); // 設置其方向爲橫向 setOrientation(LinearLayout.HORIZONTAL); // 將slide_view_merge加載進來 View.inflate(mContext, R.layout.slide_view_merge, this); mViewContent = (LinearLayout) findViewById(R.id.view_content); mHolderWidth = Math.round(TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources() .getDisplayMetrics())); }
本人顧慮(固然該顧慮多是多餘的)到按鈕沒法根據字體進行長度擴展,在SlideView初始化時提早計算holder可能所需的空間,確保按鈕的可擴展性
修改以下:
<?xml version="1.0" encoding="utf-8"?> <merge ... <RelativeLayout android:id="@+id/holder" android:layout_width="wrap_content" android:layout_height="match_parent" android:clickable="true" android:background="@drawable/holder_bg"> ... </RelativeLayout> </merge>
SlideView.java:
private void initView() { mContext = getContext(); // 初始化彈性滑動對象 mScroller = new Scroller(mContext); // 設置其方向爲橫向 setOrientation(LinearLayout.HORIZONTAL); // 將slide_view_merge加載進來 View.inflate(mContext, R.layout.slide_view_merge, this); mViewContent = (LinearLayout) findViewById(R.id.view_content); mHolder = (RelativeLayout) findViewById(R.id.holder); mHolder.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); mHolderWidth = mHolder.getMeasuredWidth(); mHolder.setLayoutParams(new LinearLayout.LayoutParams(mHolderWidth, LayoutParams.FILL_PARENT)); }
整體來講,牛人的代碼很簡潔易用,很符合小弟的口味,十分感謝牛人的無私分享!