`
crazier9527
  • 浏览: 1013665 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

@Override
protected 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。

@Override
protected 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/

分享到:
评论

相关推荐

    listview item点击事件冲突问题

    解决这个问题的方法是在子View的XML布局中添加`android:clickable="false"`或`android:focusable="false"`,或者在代码中设置`setClickable(false)`和`setFocusable(false)`,使得点击事件能传递到ListView。...

    ListView和EditText

    在Android开发中,ListView是一个非常常见的组件,用于展示大量数据的列表形式。它允许用户滚动浏览,同时提供了可定制的视图复用机制,以优化性能。然而,当ListView内部包含EditText时,开发者可能会遇到一些挑战...

    listview-Edit.zip_ListView_edit listview_listview edit_listviewe

    当用户在EditText中输入完毕后按回车键,可以通过设置KeyListener或TextWatcher来处理键盘事件,焦点移到下一列的EditText,或者根据业务逻辑执行相应的操作。 4. **处理点击事件**:可能需要为ListView添加...

    防QQListView滑动置顶删除功能

    在Android开发中,QQListView是一种常见的可滑动并带有多种操作功能的列表控件,它扩展了Android原生的ListView,增加了诸如滑动删除、置顶等交互效果。本教程将详细讲解如何实现"防QQListView滑动置顶删除功能"。 ...

    Android应用源码之Gallery2_Android.zip

    首先,Gallery2应用的核心是Android的ListView组件,它是Android中用于展示可滚动列表的视图。在这个应用中,ListView被用来展示图片的缩略图,这涉及到自定义Adapter,用于将数据集(如图片路径)转换为ListView...

    动画移动后获取焦点

    5. **ListView集成**:如果控件是在ListView中,那么需要处理ListView的滚动和焦点问题。ListView有自己的焦点机制,通常情况下,焦点会跟随列表项的可见性变化。因此,需要确保在动画完成后,列表项的位置和焦点...

    Android2.2 API 中文文档系列(5) —— View

    在Android开发中,View是构建用户界面的基本元素,它代表屏幕上的一个可视组件,比如按钮、文本框等。本文将基于Android 2.2 API的中文文档,深入探讨View类的相关知识点。 首先,View类是所有UI元素的基类,它负责...

    android tv列表焦点记忆实现的方法

    在 Android TV 开发中,焦点记忆功能是一个常见的需求,特别是在列表控件中,例如 ListView 或 RecyclerView。当用户离开列表项时,焦点需要记忆当前位置,以便在返回时能够定位到原来的项目上。下面是实现焦点记忆...

    Android 源码Button 经典实例

    在Android开发中,Button控件是用户界面中最基础也是最重要的元素之一,它允许用户执行特定的操作或触发事件。本文将通过“Android 源码Button 经典实例”这一主题,深入探讨Button的使用方法、源码分析以及实战案例...

    TextView实现上线滚动

    在Android开发中,`TextView` 是一个非常基础且重要的组件,通常用于显示单行或多行文本。在某些场景下,我们可能希望让`TextView`中的文字实现上下滚动的效果,以展示更多的信息或者吸引用户的注意力。这篇博文中,...

    5种方法完美解决android软键盘挡住输入框方法详解

    在Android应用开发中,经常会遇到一个问题,即当用户在输入框中输入时,弹出的软键盘会遮挡部分屏幕内容,尤其是对于登录或注册等需要填写多项信息的界面,这种情况严重影响了用户体验。为了解决这个问题,Android...

    联想Android面试题

    - 通过子线程发送消息到主线程的消息队列中,主线程中的Looper不断从消息队列中取出消息,并通过Handler分发到对应的处理方法。 #### 5. Activity、Intent、Service的关系 - **Activity**是用户界面的基本组成部分...

    Android初级考试13126853.docx

    适配器(Adapter)在Android中主要用于将数据绑定到组件上,比如ListView,将数据集转化为列表项显示,而不仅仅是存储数据或者解析数据。 Matrix类是用来处理二维矩阵,用于图像变换,如缩放、旋转或平移,对内存中...

    Android技术面试整理附有详细答案

    - **singleTask**:如果Activity实例已经存在于任务栈中,就会复用该实例,并将其移至栈顶;否则,创建新实例。 - **singleInstance**:总是创建一个新的实例,且独立于其他Activity之外运行。 #### 8. Intent的...

    android 弹出窗口动画demo

    在Android开发中,`PopupWindow`是一个非常实用的组件,它允许我们在主界面之上显示一个浮动的窗口,常用于创建下拉菜单、悬浮提示框等。这个“android 弹出窗口动画demo”就是一个示例,展示了如何在Android应用中...

    android--gallery走廊效果图片查看器

    在Android开发中,"android--gallery走廊效果图片查看器"是一种常见的用户界面组件,用于展示图片,它提供了类似走廊或画廊的滚动效果,让用户能够优雅地浏览一系列图像。这个组件在早期版本的Android SDK中被称为`...

    Android常见知识点总结

    - **Single Task**:如果Intent对应的Activity实例存在,则将其移到栈顶并复用;否则新建一个实例。 #### 9. Activity的生命周期 Activity的生命周期包括以下几个关键阶段: - **onCreate()**:首次创建Activity...

    Google Android SDK开发范例大全.docx

    ### Google Android SDK 开发...以上是《Google Android SDK开发范例大全》中部分章节的主要知识点概述,这些知识点覆盖了Android应用开发的基础到高级技术,对于希望深入了解Android开发的人来说是非常宝贵的资源。

    2011Android技术面试

    ### 2011 Android技术面试知识点详解 #### 1. Android的四大组件及其作用 - **Activity**:这是...以上内容涵盖了2011年Android技术面试中常见的知识点,有助于准备相关面试或复习Android开发的基本概念和技术要点。

Global site tag (gtag.js) - Google Analytics