原文: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)); }
整体来讲,牛人的代码很简洁易用,很符合小弟的口味,十分感谢牛人的无私分享!