设置wrap_content属性后,按键延迟响应?
2014-09-24 20:06
169 查看
工作中遇到一个问题
android4.4原生Dialer
1、打开拨号盘(无常用联系人前提情况下)
2、点击拨号盘菜单,弹出拨号盘
3、随便输入数字搜索
4、返回键返回到起始界面
5、(多次)点击“所有联系人”无效
6、再点任意键(Button、menu、back、home。。。),之前点击“所有联系人”的按键事件都响应了,即弹出多次所有联系人界面。
分析
步骤5时,就没有执行注册的onClick函数,而是步骤6后执行了N次(对应步骤5的点击次数)。
View.java 中会调用post(mPerformClick)
mPerformClick 会调用到 mOnClickListener.onClick(this) 从而调用用户注册的listener处理按键。
正常情况下,mAttachInfo不为空,走上面的return,会直接处理消息。
加log发现,上述步骤5时,走的是下面的return,即mAttachInfo为空,将消息添加到一个队列里,后面触发后依次执行(即上述步骤6)。
mAttachInfo的值是在下面两个函数中设置的。
dispatchAttachedToWindow()
mAttachInfo = info;
dispatchDetachedFromWindow()
mAttachInfo = null;
回到拨号盘界面
PhoneFavoriteFragment onResume()后会重新加载数据,加载完后调用setEmptyViewVisibility()来设置R.id.phone_no_favorites_view是否可见以及调整R.id.contact_tile_frame的高度。
/* package */ void setEmptyViewVisibility(final boolean visible) {
final int previousVisibility = mEmptyView.getVisibility();
final int newVisibility = visible ? View.VISIBLE : View.GONE;
if (previousVisibility != newVisibility) {
final RelativeLayout.LayoutParams params = (LayoutParams) mContactTileFrame.getLayoutParams();
params.height = visible ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT;
mContactTileFrame.setLayoutParams(params);
mEmptyView.setVisibility(newVisibility);
}
}
布局文件R.layout.phone_favorites_fragment
<?xml version="1.0" encoding="utf-8"?>
<!-- Use LinearLayout + FrameLayout, just to rely on android:divider and android:showDividers -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="end"
android:clipChildren="false"
android:background="@color/background_dialer_list_items">
<FrameLayout
android:id="@+id/contact_tile_frame"
android:layout_width="match_parent"
android:layout_height="<span style="color:#ff0000;">match_parent</span>"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
>
<com.android.dialer.list.PhoneFavoriteListView
android:id="@+id/contact_tile_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/contact_tile_list_padding_top"
android:clipToPadding="false"
android:fadingEdge="none"
android:divider="@null" />
<ImageView
android:id="@+id/contact_tile_drag_shadow_overlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
</FrameLayout>
<include
android:id="@+id/phone_no_favorites_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/contact_tile_frame"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
layout="@layout/phone_no_favorites"
android:visibility="gone"/>
</RelativeLayout>
R.id.contact_tile_frame的属性设置为
android:layout_height="wrap_content"
或在代码里设置
params.height = LayoutParams.WRAP_CONTENT
就会调用几次dispatchAttachedToWindow和dispatchDetachedFromWindow,最终mAttachInfo = null;从而出现上述问题。
但是不知道为什么??
固定值或MATCH_PARENT就没问题。。。
解决办法
不设置WRAP_CONTENT,设置一个固定的值
问题虽然临时解决,但是不知道why。。。
TestSourceCodes
android4.4原生Dialer
1、打开拨号盘(无常用联系人前提情况下)
2、点击拨号盘菜单,弹出拨号盘
3、随便输入数字搜索
4、返回键返回到起始界面
5、(多次)点击“所有联系人”无效
6、再点任意键(Button、menu、back、home。。。),之前点击“所有联系人”的按键事件都响应了,即弹出多次所有联系人界面。
分析
步骤5时,就没有执行注册的onClick函数,而是步骤6后执行了N次(对应步骤5的点击次数)。
View.java 中会调用post(mPerformClick)
mPerformClick 会调用到 mOnClickListener.onClick(this) 从而调用用户注册的listener处理按键。
public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } // Assume that post will succeed later ViewRootImpl.getRunQueue().post(action); return true; }
正常情况下,mAttachInfo不为空,走上面的return,会直接处理消息。
加log发现,上述步骤5时,走的是下面的return,即mAttachInfo为空,将消息添加到一个队列里,后面触发后依次执行(即上述步骤6)。
mAttachInfo的值是在下面两个函数中设置的。
dispatchAttachedToWindow()
mAttachInfo = info;
dispatchDetachedFromWindow()
mAttachInfo = null;
回到拨号盘界面
PhoneFavoriteFragment onResume()后会重新加载数据,加载完后调用setEmptyViewVisibility()来设置R.id.phone_no_favorites_view是否可见以及调整R.id.contact_tile_frame的高度。
/* package */ void setEmptyViewVisibility(final boolean visible) {
final int previousVisibility = mEmptyView.getVisibility();
final int newVisibility = visible ? View.VISIBLE : View.GONE;
if (previousVisibility != newVisibility) {
final RelativeLayout.LayoutParams params = (LayoutParams) mContactTileFrame.getLayoutParams();
params.height = visible ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT;
mContactTileFrame.setLayoutParams(params);
mEmptyView.setVisibility(newVisibility);
}
}
布局文件R.layout.phone_favorites_fragment
<?xml version="1.0" encoding="utf-8"?>
<!-- Use LinearLayout + FrameLayout, just to rely on android:divider and android:showDividers -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="end"
android:clipChildren="false"
android:background="@color/background_dialer_list_items">
<FrameLayout
android:id="@+id/contact_tile_frame"
android:layout_width="match_parent"
android:layout_height="<span style="color:#ff0000;">match_parent</span>"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
>
<com.android.dialer.list.PhoneFavoriteListView
android:id="@+id/contact_tile_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/contact_tile_list_padding_top"
android:clipToPadding="false"
android:fadingEdge="none"
android:divider="@null" />
<ImageView
android:id="@+id/contact_tile_drag_shadow_overlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
</FrameLayout>
<include
android:id="@+id/phone_no_favorites_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/contact_tile_frame"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
layout="@layout/phone_no_favorites"
android:visibility="gone"/>
</RelativeLayout>
R.id.contact_tile_frame的属性设置为
android:layout_height="wrap_content"
或在代码里设置
params.height = LayoutParams.WRAP_CONTENT
就会调用几次dispatchAttachedToWindow和dispatchDetachedFromWindow,最终mAttachInfo = null;从而出现上述问题。
但是不知道为什么??
固定值或MATCH_PARENT就没问题。。。
解决办法
不设置WRAP_CONTENT,设置一个固定的值
问题虽然临时解决,但是不知道why。。。
TestSourceCodes
相关文章推荐
- Android 中CheckBox设置background为一张图片并且宽高属性为wrap_content时图片被拉伸
- 安卓 View 设置宽高 wrap_content 属性无效的原因
- 设置响应头的Content-Disposition属性,实现文件下载示例
- 将RecyclerView的宽高属性设置为“wrap_content”
- 个人经验 - Android的RelativeLayout布局的layout_height属性设置为wrap_content时的坑
- GridView 设置其高度属性为 wrap_content
- Android ViewPager无法使用wrap_content属性自适应高度
- 解决 viewpager 不能使用wrap_content 属性
- 给初学者:用VB写外挂 ———— 实战三:泰坦之旅V1.08 十项属性修改器——另一种无输入焦点时响应按键的方法
- Delphi中Menu设置Images属性后快捷按键下划线被隐藏解决方法
- Android ImageView设置长度高度为wrap_content时高度根据图片比例自适应
- c#创建窗体,向窗体添加控件,设置控件大小位置等属性,写控件的响应
- [疯狂Java]网络:GET/POST请求、设置请求属性、获取响应属性
- 设置属性“System.Windows.ResourceDictionary.DeferrableContent”时引发了异常
- 【android】解决Viewpager设置高度为wrap_content无效的方法
- 设置了背景图片的TextView,其尺寸设置为wrap_content时,并不是适应文字内容大小
- Response.setContentType 可设置属性
- MOSS 2007 爬网规则 Contentclass常用属性设置
- django 设置响应头Content-Length: 使用中间件
- Android ImageView设置长度高度为wrap_content时高度根据图片比例自适应