首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

Android中焦点移到ListView的有关问题(转)

2012-06-26 
Android中焦点移到ListView的问题(转)发现Android编程中的一个问题:如果在一个ListView上面放置一个可以接

Android中焦点移到ListView的问题(转)

发现Android编程中的一个问题:如果在一个ListView上面放置一个可以接收焦点的东西,比如Button,当使用向上方向键滚动ListView到第一条后,焦点会移到上面的Button上,这个没问题。但然后使用向下的方向键时,焦点会跳到ListView中当前窗口的最下面一条,而不是焦点离开时的第一条。在ListView下方有Button的时候,向上移动焦点,也会出现类似的情况。

这个问题在Android的示例里面也有,ApiDemos->Views->Tabs->Content By Intent。这个示例里当使用方向键从list这个Tab向下移动焦点的时候,会跳过一屏的条目。

在网上搜了一下,仅仅有一个人提到了这个问题,但没有看到解答。

我查了一下源代码,实现设置焦点的代码是:

git://android.git.kernel.org/platform/frameworks/base.git?core?java?android?widget?ListView.java

@Overrideprotected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {    super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);    int closetChildIndex = -1;    if (gainFocus && previouslyFocusedRect != null) {        previouslyFocusedRect.offset(mScrollX, mScrollY);        // figure out which item should be selected based on previously        // focused rect        Rect otherRect = mTempRect;        int minDistance = Integer.MAX_VALUE;        final int childCount = getChildCount();        final int firstPosition = mFirstPosition;        final ListAdapter adapter = mAdapter;        for (int i = 0; i < childCount; i++) {            // only consider selectable views            if (!adapter.isEnabled(firstPosition + i)) {                continue;            }            View other = getChildAt(i);            other.getDrawingRect(otherRect);            offsetDescendantRectToMyCoords(other, otherRect);            int distance = getDistance(previouslyFocusedRect, otherRect, direction);            if (distance < minDistance) {                minDistance = distance;                closetChildIndex = i;            }        }    }    if (closetChildIndex >= 0) {        setSelection(closetChildIndex + mFirstPosition);    } else {        requestLayout();    }}

通过debug发现,previouslyFocusedRect在这里是ListView的,而不是之前焦点View的。在按向下键时,getDistance比较ListView的bottom和各个child的top,当然会选中离ListView下沿最近的。具体为什么会previouslyFocusedRect是ListView,我还没有深入分析。

一个解决办法

这不是一个根本解决的方法:写一个新的class,继承ListView,覆盖onFocusChanged。

@Overrideprotected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);if (gainFocus && previouslyFocusedRect != null) {final ListAdapter adapter = getAdapter();final int count = adapter.getCount();switch (direction) {case FOCUS_DOWN:for (int i = 0; i < count; i++) {if (!adapter.isEnabled(i)) {continue;}setSelection(i);break;}break;case FOCUS_UP:for (int i = count-1; i>=0; i--) {if (!adapter.isEnabled(i)) {continue;}setSelection(i);break;}break;default:break;}}}

在这里,我只处理了FOCUS_DOWN和FOCUS_UP。由于不能访问mFirstPosition,处理也做了简化:焦点从上方移下来时选择第一个能选择的,从下方移上来时选择最后一个能选择的。

?

感谢:http://sunote.info/2010/02/25/android-move-focus-to-listview/

热点排行