里面的ListView调焦的EditText里面、ListView、EditText

2023-09-11 10:25:43 作者:不美不萌不性感

我已经花了约6小时,在此,到目前为止,一直打到什么,但路障。一般premise是,有在的ListView一些行(不管它是由适配器产生的,或者添加作为头视图),其中包含一个的EditText 部件和按钮。所有我想要做的是能够使用jogball /箭头,浏览选择像正常的单件物品,但是当我得到一个特定的行 - 即使我有明确标识行 - 具有可聚焦孩子,我想要那个孩子取,而不是指示与选择的位置对焦。

I've spent about 6 hours on this so far, and been hitting nothing but roadblocks. The general premise is that there is some row in a ListView (whether it's generated by the adapter, or added as a header view) that contains an EditText widget and a Button. All I want to do is be able to use the jogball/arrows, to navigate the selector to individual items like normal, but when I get to a particular row -- even if I have to explicitly identify the row -- that has a focusable child, I want that child to take focus instead of indicating the position with the selector.

我试过很多可能性,迄今没有运气。

I've tried many possibilities, and have so far had no luck.

布局:

<ListView
    android:id="@android:id/list" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    />

标题视图:

EditText view = new EditText(this);
listView.addHeaderView(view, null, true);

假设有在适配器的其他项目,使用箭头键可以移动选择在列表中/下,符合市场预期;但得到的标题行的时候,它也显示了选择,也没有办法集中到的EditText 使用jogball。注:轻敲的EditText 的将会的不过是依赖于触摸屏,这不应该是一个要求,在这一点上重点吧,

Assuming there are other items in the adapter, using the arrow keys will move the selection up/down in the list, as expected; but when getting to the header row, it is also displayed with the selector, and no way to focus into the EditText using the jogball. Note: tapping on the EditText will focus it at that point, however that relies on a touchscreen, which should not be a requirement.

的ListView 显然在这方面有两种模式: 1. setItemsCanFocus(真):选择永远不会显示出来,但的EditText 可以使用箭头时获得焦点。聚焦搜索算法很难predict,无视觉反馈(在任何行:具有可调焦的子女或没有),在其项目被选中,这两者都可以给用户一个意想不到的体验。 2. setItemsCanFocus(假):选择总是画在非触摸模式,和的EditText 永远无法获得焦点 - 即使你点击它

ListView apparently has two modes in this regard: 1. setItemsCanFocus(true): selector is never displayed, but the EditText can get focus when using the arrows. Focus search algorithm is hard to predict, and no visual feedback (on any rows: having focusable children or not) on which item is selected, both of which can give the user an unexpected experience. 2. setItemsCanFocus(false): selector is always drawn in non-touch-mode, and EditText can never get focus -- even if you tap on it.

更糟糕的是,调用 editTextView.requestFocus()返回true,但实际上并没有给EditText上的焦点。

To make matters worse, calling editTextView.requestFocus() returns true, but in fact does not give the EditText focus.

什么我构想基本上是1和混合; 2,在那里而不是列表设置,如果的所有的项目是可聚焦与否,我想设置可聚焦性的的单的项目列表,从而使选择无缝过渡选择整个行不可聚焦项目,以及遍历的焦点树包含可聚焦儿童的项目。

What I'm envisioning is basically a hybrid of 1 & 2, where rather than the list setting if all items are focusable or not, I want to set focusability for a single item in the list, so that the selector seamlessly transitions from selecting the entire row for non-focusable items, and traversing the focus tree for items that contain focusable children.

任何考生?

推荐答案

对不起,回答我的问题。它可能不是最正确或最优雅的解决方案,但它为我工作,并给出了pretty的坚实的用户体验。我看着在$ C $下的ListView明白为什么两种行为​​是如此的不同,遇到这种情况的ListView.java:

Sorry, answered my own question. It may not be the most correct or most elegant solution, but it works for me, and gives a pretty solid user experience. I looked into the code for ListView to see why the two behaviors are so different, and came across this from ListView.java:

    public void setItemsCanFocus(boolean itemsCanFocus) {
        mItemsCanFocus = itemsCanFocus;
        if (!itemsCanFocus) {
            setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
        }
    }

所以,当调用 setItemsCanFocus(假),它也设置后代可聚焦性,使儿童不能获得焦点。这就解释了为什么我不能只需拨动 mItemsCanFocus 在ListView的OnItemSelectedListener - 因为ListView控件,然后堵重点向所有儿童

So, when calling setItemsCanFocus(false), it's also setting descendant focusability such that no child can get focus. This explains why I couldn't just toggle mItemsCanFocus in the ListView's OnItemSelectedListener -- because the ListView was then blocking focus to all children.

我现在有:

<ListView
    android:id="@android:id/list" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    android:descendantFocusability="beforeDescendants"
    />

我用 beforeDescendants 因为选择只绘制时,ListView控件本身(而不是一个孩子)有重点,所以默认行为,需要在那个ListView控件需要重点第一和绘制选择。

I use beforeDescendants because the selector will only be drawn when the ListView itself (not a child) has focus, so the default behavior needs to be that the ListView takes focus first and draws selectors.

然后在OnItemSelectedListener,因为我知道我要重写选择器(将采取更多的工作,以动态地确定是否有任何给定的位置包含一个可成为焦点的观点),我可以改变后代可聚焦性,并在EditText上设置焦点这头视图。当我浏览了这个头的,改变它再回来了。

Then in the OnItemSelectedListener, since I know which header view I want to override the selector (would take more work to dynamically determine if any given position contains a focusable view), I can change descendant focusability, and set focus on the EditText. And when I navigate out of that header, change it back it again.

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);
}

请注意注释掉的 setItemsCanFocus 通话。有了这些电话,我得到了正确的行为,但 setItemsCanFocus(假)引起的焦点从EditText上跳,另一个插件的ListView控件之外,又回到了ListView和显示选择的下一个选择的项目,那跳跃的重点是分心。卸下ItemsCanFocus变化,只是切换后代可聚焦性得到了我所期望的行为。所有项目绘制选择正常,但得到与EditText上行时,它着眼于文本字段代替。然后继续指出,EditText上时,它开始再次绘制选择。

Note the commented-out setItemsCanFocus calls. With those calls, I got the correct behavior, but setItemsCanFocus(false) caused focus to jump from the EditText, to another widget outside of the ListView, back to the ListView and displayed the selector on the next selected item, and that jumping focus was distracting. Removing the ItemsCanFocus change, and just toggling descendant focusability got me the desired behavior. All items draw the selector as normal, but when getting to the row with the EditText, it focused on the text field instead. Then when continuing out of that EditText, it started drawing the selector again.