Joe*_*Joe 120 android android-layout android-listview android-edittext
到目前为止,我已经花了大约6个小时的时间,除了路障之外什么都没打.一般的前提是a中有一些行ListView(无论是由适配器生成,还是作为标题视图添加)包含一个EditText小部件和一个Button.我想要做的就是能够使用jogball /箭头,将选择器导航到正常的单个项目,但是当我到达特定行时 - 即使我必须明确地识别行 - 它具有可聚焦孩子,我希望那个孩子采取焦点而不是用选择器指示位置.
我已经尝试了很多可能性,到目前为止还没有运气.
布局:
<ListView
android:id="@android:id/list"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
/>
Run Code Online (Sandbox Code Playgroud)
标题视图:
EditText view = new EditText(this);
listView.addHeaderView(view, null, true);
Run Code Online (Sandbox Code Playgroud)
假设适配器中还有其他项目,使用箭头键将按预期在列表中上/下移动选择; 但是当到达标题行时,它也会与选择器一起显示,并且无法专注于EditText使用jogball.注意:点击它EditText 会将焦点集中在那一点,但是它依赖于触摸屏,这不是必需的.
ListView在这方面显然有两种模式:
1 setItemsCanFocus(true).:从不显示选择器,但EditText使用箭头时可以获得焦点.焦点搜索算法难以预测,并且没有选择哪个项目的视觉反馈(在任何行上:具有可聚焦儿童或不具有可聚焦儿童),这两者都可以给用户带来意想不到的体验.
2 setItemsCanFocus(false).:选择器始终以非触摸模式绘制,并且EditText永远无法获得焦点 - 即使您点击它也是如此.
更糟糕的是,调用editTextView.requestFocus()返回true,但事实上并没有给EditText带来焦点.
我想象的基本上是1和2的混合,而不是列表设置,如果所有项目都是可聚焦的,我想为列表中的单个项目设置可聚焦性,以便选择器从选择无缝转换不可聚焦项目的整行,以及遍历包含可聚焦子项的项目的焦点树.
任何接受者?
Joe*_*Joe 102
对不起,回答了我自己的问题.它可能不是最正确或最优雅的解决方案,但它适用于我,并提供非常可靠的用户体验.我查看了ListView的代码,看看为什么这两个行为如此不同,并从ListView.java中看到了这个:
public void setItemsCanFocus(boolean itemsCanFocus) {
mItemsCanFocus = itemsCanFocus;
if (!itemsCanFocus) {
setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,在呼叫时setItemsCanFocus(false),它还设置后代可聚焦性,使得没有孩子可以获得焦点.这解释了为什么我不能只mItemsCanFocus在ListView的OnItemSelectedListener中切换- 因为ListView然后阻止了对所有孩子的焦点.
我现在拥有的:
<ListView
android:id="@android:id/list"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:descendantFocusability="beforeDescendants"
/>
Run Code Online (Sandbox Code Playgroud)
我使用beforeDescendants因为只有在ListView本身(不是子)具有焦点时才会绘制选择器,因此默认行为需要是ListView首先获得焦点并绘制选择器.
然后在OnItemSelectedListener中,因为我知道哪个标题视图要覆盖选择器(将需要更多工作来动态确定任何给定位置是否包含可聚焦视图),我可以更改后代可聚焦性,并将焦点设置在EditText上.当我离开那个标题时,再将其更改回来.
public void onItemSelected(AdapterView<?> listView, View view, int position, long id)
{
if (position == 1)
{
// listView.setItemsCanFocus(true);
// Use afterDescendants, because I don't want the ListView to steal focus
listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
myEditText.requestFocus();
}
else
{
if (!listView.isFocused())
{
// listView.setItemsCanFocus(false);
// Use beforeDescendants so that the EditText doesn't re-take focus
listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
listView.requestFocus();
}
}
}
public void onNothingSelected(AdapterView<?> listView)
{
// This happens when you start scrolling, so we need to prevent it from staying
// in the afterDescendants mode if the EditText was focused
listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}
Run Code Online (Sandbox Code Playgroud)
请注意已注释掉的setItemsCanFocus电话.通过这些调用,我获得了正确的行为,但setItemsCanFocus(false)导致焦点从EditText跳转到ListView外的另一个小部件,返回到ListView并在下一个选定项目上显示选择器,并且跳跃焦点分散了注意力.删除ItemsCanFocus更改,只是切换后代可聚焦性让我得到了所需的行为.所有项目都正常绘制选择器,但是当使用EditText到达行时,它会聚焦于文本字段.然后当继续使用EditText时,它再次开始绘制选择器.
小智 99
这对我有帮助.
在你的清单中:
<activity android:name= ".yourActivity" android:windowSoftInputMode="adjustPan"/>
Run Code Online (Sandbox Code Playgroud)
And*_*cko 17
我的任务是实现ListView在点击时展开的内容.附加空间显示EditText您可以输入文本的位置.应用程序应该在2.2+上运行(在编写本文时最多4.2.2)
我试过这个帖子和我能找到的其他人的许多解决方案; 在2.2到4.2.2设备上测试它们.所有设备2.2+都没有令人满意的解决方案,每个解决方案都存在不同的问题.
我想分享我的最终解决方案:
android:descendantFocusability="afterDescendants"setItemsCanFocus(true);android:windowSoftInputMode="adjustResize"
很多人建议,adjustPan但adjustResize给你更好的ux imho,只需在你的情况下测试.例如,adjustPan您将获得隐藏的底部列表项目.Docs建议("这通常不如调整大小").同样在4.0.4用户开始在软键盘上键入后,屏幕平移到顶部.adjustResize,EditText焦点存在一些问题.解决方案是从该线程应用rjrjr解决方案.它看起来很麻烦,但事实并非如此.它有效.就试一试吧.附加5.由于适配器被刷新(因为视图调整大小)当EditText增益集中在预装HoneyComb版本时,我发现了反向视图的问题:
在2.2上获取ListView项目/逆序的视图; 适用于4.0.3
如果您正在做一些动画,您可能希望将行为更改adjustPan为预蜂窝版本,以便调整大小不会触发,并且适配器不会刷新视图.你只需要添加这样的东西
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
Run Code Online (Sandbox Code Playgroud)
所有这些都为2.2 - 4.2.2设备提供了可接受的ux.希望它能节省一些时间,因为我花了至少几个小时来得出这个结论.
小智 10
这拯救了我的生命--->
设置这一行
ListView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
然后在您的活动标签清单中输入 - >
<activity android:windowSoftInputMode="adjustPan">
你通常的意图
我们在一个没有任何视图回收的简短列表上尝试这个.到现在为止还挺好.
XML:
<RitalinLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/cart_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="outsideOverlay"
/>
</RitalinLayout>
Run Code Online (Sandbox Code Playgroud)
Java的:
/**
* It helps you keep focused.
*
* For use as a parent of {@link android.widget.ListView}s that need to use EditText
* children for inline editing.
*/
public class RitalinLayout extends FrameLayout {
View sticky;
public RitalinLayout(Context context, AttributeSet attrs) {
super(context, attrs);
ViewTreeObserver vto = getViewTreeObserver();
vto.addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
@Override public void onGlobalFocusChanged(View oldFocus, View newFocus) {
if (newFocus == null) return;
View baby = getChildAt(0);
if (newFocus != baby) {
ViewParent parent = newFocus.getParent();
while (parent != null && parent != parent.getParent()) {
if (parent == baby) {
sticky = newFocus;
break;
}
parent = parent.getParent();
}
}
}
});
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override public void onGlobalLayout() {
if (sticky != null) {
sticky.requestFocus();
}
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
106936 次 |
| 最近记录: |