Open liuyuttkx opened 5 years ago
设置标签可点击的View id, 如果该View在布局中是被多层嵌套的,它的点击事件不生效。 应用场景:粘性标签中不同子view拥有不同的点击事件。
示例:标签布局如下,并设置三个TextView可被点击 builder.setClickIds(R.id.stockName, R.id.ipo_time,R.id.fluctuate );
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#987" android:orientation="horizontal">
<TextView android:id="@+id/stockName" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="left" android:paddingBottom="12dp" android:paddingTop="12dp" android:text="股票名称" android:textSize="13dp" android:layout_width="0dp" /> <TextView android:id="@+id/ipo_time" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:gravity="center" android:text="上市日期" /> <LinearLayout android:id="@+id/ll_fluctuate" android:layout_width="0dp" android:layout_height="match_parent" android:layout_gravity="center" android:tag="test no" android:layout_weight="1.3" android:gravity="center"> <TextView android:id="@+id/fluctuate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:gravity="right|center_vertical" android:lines="1" android:background="#f00" android:text="首日最"
/>
异常现象: view Id 为 stockName 、ipo_time 、ll_fluctuate 的三个View,如果设置点击事件,则可以在OnHeaderClickAdapter.class中的onHeaderClick(View view, int id, int position)方法中收到回调,但如果设置viewId 为fluctuate 的TextView可被点击,则它的点击事件无法生效。
原因:查看源码在Decoration初始化时,给设置点击事件的子View确定对应的区域时(点击事件触发时,根据点击的坐标来确认是发生在哪个子View的区域),是 PinnedHeaderItemDecoration 类的 401 行,该行实际上是调用 OnItemTouchListener.class 的setClickBounds(int id, View view)方法。源码如下:
public void setClickBounds(int id, View view) { ClickBounds bounds; if (mBoundsArray.get(id) == null) { bounds = new ClickBounds(view, view.getLeft(), view.getTop(), view.getLeft() + view.getMeasuredWidth(), view.getTop() + view.getMeasuredHeight()); mBoundsArray.put(id, bounds); } else { bounds = mBoundsArray.get(id); bounds.setBounds(view.getLeft(), view.getTop(), view.getLeft() + view.getMeasuredWidth(), view.getTop() + view.getMeasuredHeight()); } }
可以看出是根据子view的getLeft() getTop()等来确定View在Decoration中的坐标。但是getLeft() getTop()是获取相对父控件的距离。综上所述,结合布局,可以发现TextView fluctuate 的点击区域在初始化设置时,是它相对于它的父控制LinearLayout(id为ll_fluctuate)的值,而并不是实际相对于Decoration 的区域,所以 TextView id 为ipo_time stockName 可以正常获取点击事件,而点击TextView fluctuate 所在区域没有回调。
修复该问题: 在OnItemTouchListener 类中增加如下两个方法,并作出如下修改
将PinnedHeaderItemDecoration.class中401行和 SmallPinnedHeaderItemDecoration.class 的 274行的 mItemTouchListener.setClickBounds(mClickId, view); 修改为 mItemTouchListener.setClickViewkBounds(mPinnedHeaderView, mClickId, view);
`/**
public int[] getLeftAndTopBounds(View itemView, int childId, View view) { int[] bounds = new int[2]; if (itemView.getId() == childId) { bounds[0] = itemView.getLeft(); bounds[1] = itemView.getTop(); return bounds; } else { if (itemView instanceof ViewGroup) { ViewGroup group = (ViewGroup) itemView; for (int i = 0; i < group.getChildCount(); i++) { View childAt = group.getChildAt(i); if (childAt.getId() == childId) { bounds[0] = childAt.getLeft(); bounds[1] = childAt.getTop(); return bounds; } else if (childAt instanceof ViewGroup) { int[] childViewBounds = getLeftAndTopBounds(childAt, childId, view); if (childViewBounds != null) { bounds[0] = childViewBounds[0] + childAt.getLeft(); bounds[1] = childViewBounds[1] + childAt.getTop(); return bounds; } } } } } return null; }`
这仅仅是个人拙见,还请楼主测试一下。
设置标签可点击的View id, 如果该View在布局中是被多层嵌套的,它的点击事件不生效。 应用场景:粘性标签中不同子view拥有不同的点击事件。
示例:标签布局如下,并设置三个TextView可被点击 builder.setClickIds(R.id.stockName, R.id.ipo_time,R.id.fluctuate );
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#987" android:orientation="horizontal">
/>
异常现象: view Id 为 stockName 、ipo_time 、ll_fluctuate 的三个View,如果设置点击事件,则可以在OnHeaderClickAdapter.class中的onHeaderClick(View view, int id, int position)方法中收到回调,但如果设置viewId 为fluctuate 的TextView可被点击,则它的点击事件无法生效。
原因:查看源码在Decoration初始化时,给设置点击事件的子View确定对应的区域时(点击事件触发时,根据点击的坐标来确认是发生在哪个子View的区域),是 PinnedHeaderItemDecoration 类的 401 行,该行实际上是调用 OnItemTouchListener.class 的setClickBounds(int id, View view)方法。源码如下:
public void setClickBounds(int id, View view) { ClickBounds bounds; if (mBoundsArray.get(id) == null) { bounds = new ClickBounds(view, view.getLeft(), view.getTop(), view.getLeft() + view.getMeasuredWidth(), view.getTop() + view.getMeasuredHeight()); mBoundsArray.put(id, bounds); } else { bounds = mBoundsArray.get(id); bounds.setBounds(view.getLeft(), view.getTop(), view.getLeft() + view.getMeasuredWidth(), view.getTop() + view.getMeasuredHeight()); } }
可以看出是根据子view的getLeft() getTop()等来确定View在Decoration中的坐标。但是getLeft() getTop()是获取相对父控件的距离。综上所述,结合布局,可以发现TextView fluctuate 的点击区域在初始化设置时,是它相对于它的父控制LinearLayout(id为ll_fluctuate)的值,而并不是实际相对于Decoration 的区域,所以 TextView id 为ipo_time stockName 可以正常获取点击事件,而点击TextView fluctuate 所在区域没有回调。
修复该问题: 在OnItemTouchListener 类中增加如下两个方法,并作出如下修改
将PinnedHeaderItemDecoration.class中401行和 SmallPinnedHeaderItemDecoration.class 的 274行的 mItemTouchListener.setClickBounds(mClickId, view); 修改为 mItemTouchListener.setClickViewkBounds(mPinnedHeaderView, mClickId, view);
`/**
public int[] getLeftAndTopBounds(View itemView, int childId, View view) { int[] bounds = new int[2]; if (itemView.getId() == childId) { bounds[0] = itemView.getLeft(); bounds[1] = itemView.getTop(); return bounds; } else { if (itemView instanceof ViewGroup) { ViewGroup group = (ViewGroup) itemView; for (int i = 0; i < group.getChildCount(); i++) { View childAt = group.getChildAt(i); if (childAt.getId() == childId) { bounds[0] = childAt.getLeft(); bounds[1] = childAt.getTop(); return bounds; } else if (childAt instanceof ViewGroup) { int[] childViewBounds = getLeftAndTopBounds(childAt, childId, view); if (childViewBounds != null) { bounds[0] = childViewBounds[0] + childAt.getLeft(); bounds[1] = childViewBounds[1] + childAt.getTop(); return bounds; } } } } } return null; }`
这仅仅是个人拙见,还请楼主测试一下。