奇怪的列表视图项目选择器外观(手指离开屏幕时未移除按下状态)
Posted
技术标签:
【中文标题】奇怪的列表视图项目选择器外观(手指离开屏幕时未移除按下状态)【英文标题】:Wierd listview item selector appearance (pressed state was not removed when finger left the screen) 【发布时间】:2012-05-02 01:19:28 【问题描述】:我有如下列表视图项
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="horizontal"
android:descendantFocusability="blocksDescendants"
>
<TextView
android:id="@+id/textView1"
android:layout_
android:layout_
/>
<CheckBox
android:id="@+id/checkBox1"
android:layout_
android:layout_
android:background="@drawable/music_list_item_checkbox_bg"
/>
</LinearLayout>
music_list_item_checkbox_bg.xml
是一个选择器,它会根据不同的状态显示不同的drawable。
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:state_pressed="false"
android:state_selected="true"
android:drawable="@drawable/btn_checkbox_check_untapped" />
<item android:state_selected="true"
android:state_pressed="true"
android:drawable="@drawable/btn_checkbox_check_tapped" />
<item android:state_selected="false"
android:state_pressed="false"
android:drawable="@drawable/btn_checkbox_uncheck_untapped" />
<item android:state_selected="false"
android:state_pressed="true"
android:drawable="@drawable/btn_checkbox_uncheck_tapped" />
</selector>
当我按下列表视图中的项目并将触摸屏留在项目内时,取决于不同状态的可绘制对象是正确的。
问题: 但是如果我按下项目并将手指水平移出项目(触摸点的 X 位于项目的顶部和底部之间) ,然后离开屏幕,复选框的drawable将保持按下状态。 (如果触摸点的X不在项目的顶部和底部,则状态正确)。
我尝试在复选框中添加android:duplicateParentState="true"
以获得与父级相同的状态,但它不起作用。
我很困惑,有人有什么想法吗?
已编辑
我之前尝试在项目中实现 onTouch 和 onIntercept,但如果我返回 super.onTouch(MotionEvent 事件),则只能接收动作。只返回true,则接收到sequence event,但是listview的onItemClick不起作用。 我尝试阅读 AbsListview 中的 onTouch 代码 sn-p 以找出解决问题的方法,我发现有时 child(item) 的按下状态不会通过调用 child.setPressed(false) 来清除为 false,这取决于不同的触摸模式。
我真的很想要一个解决方案!!!
【问题讨论】:
这是一个纯粹的猜测,但也许是因为该动作在视图(按下)上注册了一个 Down 事件,但没有为 that 视图注册一个相应的 Up 事件? 【参考方案1】:<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/btn_checkbox_check_tapped" />
<item android:state_selected="true"
android:drawable="@drawable/btn_checkbox_check_tapped" />
<item android:drawable="@drawable/btn_checkbox_uncheck_untapped" />
</selector>
尝试使用这些选择器作为背景
【讨论】:
如果上述方法在实现 ontouch 并识别 action up 事件并使用 adapter.notifyDataSetChanged() 刷新列表视图后不起作用 我解决了这个问题,但可能不是一个好的解决方案或官方解决方案。【参考方案2】:尝试让其中的视图无法聚焦...
<TextView
android:id="@+id/textView1"
android:layout_
android:layout_
/>
<CheckBox
android:id="@+id/checkBox1"
android:layout_
android:layout_
android:background="@drawable/music_list_item_checkbox_bg"
android:focussableInTouchMode="false"
android:focussable="false"
/>
您不能在触摸模式下使列表项成为焦点...这里因为您的复选框是可聚焦的,它会产生问题...
【讨论】:
我试过了,还是不行。我使用 android:descendantFocusability="blocksDescendants" 来避免项目获得焦点。 @dreamtale .. 尝试删除我解决了问题,但可能不是一个好的解决方案或官方解决方案。
我使用自己的MyListView
类从ListView
扩展而不是SDK ListView
并在其onTouchEvent
中接收ACTION_UP
和ACTION_CANCEL
,然后手动将项目的按下状态设置为false .更多细节请看下面的代码。
@Override
public boolean onTouchEvent(MotionEvent event)
boolean handled = super.onTouchEvent(event);
Log.d("test", "event " + event.toString());
int action = event.getAction();
switch (action)
case MotionEvent.ACTION_DOWN:
m_downPosition = pointToPosition((int)event.getX(), (int)event.getY());
Log.d("test", "The down position " + m_downPosition);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
int position = m_downPosition - getFirstVisiblePosition();
View child = INVALID_POSITION != m_downPosition ? getChildAt(position) : null;
if (null != child)
child.setPressed(false);
break;
default:
break;
return handled;
【讨论】:
【参考方案4】:您应该尝试使用这样的默认选择器项
<item android:drawable="@drawable/btn_checkbox_uncheck_untapped" />
这将处理所有剩余的状态
或者您应该有一个选择器项来处理您的 xml 中缺少的 focussed
状态。
【讨论】:
我试过了,还是不行,Android lint 也有警告:No android:state_ attribute found on为您的项目扩展 LinearLayout
并覆盖其中的 onTouch
。处理 ACTION_CANCEL 事件(返回 true)并更新项目的按下和选择状态。
class ItemLayout extends LinearLayout
@override
boolean onTouch(MotionEvent ev)
switch(ev.getAction())
case ACTION_CANCEL:
// Update/reset pressed and selected states of item or checbkox
return true;
return super.onTouch(ev);
参考http://groups.google.com/group/android-developers/browse_thread/thread/df75c5b8e4605167#
希望对您有所帮助。
<ItemLayout
....>
<TextView
...
/>
<CheckBox
...
/>
</ItemLayout >
【讨论】:
我的listview项目前是extends LinearLayout,我之前试过实现onTouch和onIntercept,但是只能接收动作down,如果我返回super.onTouch(MotionEvent事件),只返回true,然后是sequence event会收到,但是listview的onItemClick不起作用。 如果返回super,item中只能收到action down。 是否以与我给出的代码相同的方式完成?查看谷歌群组链接,它说当手指离开视线时会发生 ACTION_CANCEL .. 我之前试过,记得Action_cancel没有收到,我稍后再试,如果收到了会通知你。 不,操作取消也无法接收。我差点放弃了,过段时间我会再尝试解决的。以上是关于奇怪的列表视图项目选择器外观(手指离开屏幕时未移除按下状态)的主要内容,如果未能解决你的问题,请参考以下文章