關於高仿微信對話列表滑動刪除效果代碼優化

原文: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));
}


整體來講,牛人的代碼很簡潔易用,很符合小弟的口味,十分感謝牛人的無私分享!

相關文章
相關標籤/搜索