• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android焦点事件分发与传递机制

Android焦点事件分发与传递机制

作者:永远不要停下学习的脚步。 字体:[增加 减小] 来源:互联网 时间:2017-07-23

永远不要停下学习的脚步。通过本文主要向大家介绍了android,源码,Android-焦点等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

如果您对TouchEvent事件分发机制不太了解的,可以参考我的这篇文章——安卓TounchEvent事件分发机制。

问题:TV端焦点满天飞,如何解决和处理?

记得初入TV开发,以为很简单。TV的这些界面与布局太简单了,分分钟就可以把页面搭建出来,处理好,然后就没有然后了。。。。

下面我们就从源码来带大家进行安卓TV焦点事件的传递

这里先给出Android系统View的绘制流程:

依次执行View类里面的如下三个方法:

  • measure(int ,int) :测量View的大小
  • layout(int ,int ,int ,int) :设置子View的位置
  • draw(Canvas) :绘制View内容到Canvas画布上

ViewRootImpl的主要作用如下(此处不多讲,如有意图,看源码):

  • A:链接WindowManager和DecorView的纽带,更广一点可以说是Window和View之间的纽带。

  • B:完成View的绘制过程,包括measure、layout、draw过程。

  • C:向DecorView分发收到的用户发起的event事件,如按键,触屏等事件。

ViewRootImpl不再多余叙述,进入正题:

Android焦点分发的主要方法以及拦截方法的讲解。

在RootViewImpl中的函数通道是各种策略(InputStage)的组合,各策略负责的任务不同,如SyntheticInputStage、ViewPostImeInputStage、NativePostImeInputStage等等,这些策略以链表结构结构起来,当一个策略者没有消费事件时,就传递个下一个策略者。其中触摸和按键事件由ViewPostImeInputStage处理。

 @Override
        protected int onProcess(QueuedInputEvent q) {
            if (q.mEvent instanceof KeyEvent) {
                return processKeyEvent(q);//如果是按键事件走此处,处理按键和焦点问题了
            } else {
                final int source = q.mEvent.getSource();
                if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                    return processPointerEvent(q);//如果是触摸事件走此处
                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                    return processTrackballEvent(q);
                } else {
                    return processGenericMotionEvent(q);
                }
            }
        }

processKeyEvent(QueuedInputEvent q)源码如下:

   @Override
        protected void onDeliverToNext(QueuedInputEvent q) {
            if (mUnbufferedInputDispatch
                    && q.mEvent instanceof MotionEvent
                    && ((MotionEvent)q.mEvent).isTouchEvent()
                    && isTerminalInputEvent(q.mEvent)) {
                mUnbufferedInputDispatch = false;
                scheduleConsumeBatchedInput();
            }
            super.onDeliverToNext(q);
        }

        private int processKeyEvent(QueuedInputEvent q) {
            final KeyEvent event = (KeyEvent)q.mEvent;

            // Deliver the key to the view hierarchy.
            if (mView.dispatchKeyEvent(event)) {
                return FINISH_HANDLED;
            }

            if (shouldDropInputEvent(q)) {
                return FINISH_NOT_HANDLED;
            }

            // If the Control modifier is held, try to interpret the key as a shortcut.
            if (event.getAction() == KeyEvent.ACTION_DOWN
                    && event.isCtrlPressed()
                    && event.getRepeatCount() == 0
                    && !KeyEvent.isModifierKey(event.getKeyCode())) {
                if (mView.dispatchKeyShortcutEvent(event)) {
                    return FINISH_HANDLED;
                }
                if (shouldDropInputEvent(q)) {
                    return FINISH_NOT_HANDLED;
                }
            }

            // Apply the fallback event policy.
            if (mFallbackEventHandler.dispatchKeyEvent(event)) {
                return FINISH_HANDLED;
            }
            if (shouldDropInputEvent(q)) {
                return FINISH_NOT_HANDLED;
            }

            // Handle automatic focus changes.
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                int direction = 0;
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_DPAD_LEFT:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_LEFT;
                        }
                        break;
                    case KeyEvent.KEYCODE_DPAD_RIGHT:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_RIGHT;
                        }
                        break;
                    case KeyEvent.KEYCODE_DPAD_UP:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_UP;
                        }
                        break;
                    case KeyEvent.KEYCODE_DPAD_DOWN:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_DOWN;
                        }
                        break;
                    case KeyEvent.KEYCODE_TAB:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_FORWARD;
                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
                            direction = View.FOCUS_BACKWARD;
                        }
                        break;
                }
                if (direction != 0) {
                    View focused = mView.findFocus();
                    if (focused != null) {
                        View v = focused.focusSearch(direction);
                        if (v != null && v != focused) {
                            // do the math the get the interesting rect
                            // of previous focused into the coord system of
                            // newly focused view
                            focused.getFocusedRect(mTempRect);
                            if (mView instanceof ViewGroup) {
                                ((ViewGroup) mView).offsetDescendantRectToMyCoords(
                                        focused, mTempRect);
                                ((ViewGroup) mView).offsetRectIntoDescendantCoords(
                                        v, mTempRect);
                            }
                            if (v.requestFocus(direction, mTempRect)) {
                                playSoundEffect(SoundEffectConstants
                                        .getContantForFocusDirection(direction));
                                return FINISH_HANDLED;
                            }
                        }

                        // Give the focused view a last chance to handle the dpad key.
                        if (mView.dispatchUnhandledMove(focused, direction)) {
                            return FINISH_HANDLED;
                        }
                    } else {
                        // find the best view to give focus to in this non-touch-mode with no-focus
                        View v = focusSearch(null, direction);
                        if (v != null && v.requestFocus(direction)) {
                            return FINISH_HANDLED;
                        }
                    }
                }
            }
            return FORWARD;
        }

进入源码讲解:

(1) 首先由dispatchKeyEvent进行焦点的分发

如果dispatchKeyEvent方法返回true,那么下面的焦点查找步骤就不会继续了。

dispatchKeyEvent方法返回true代表事件(包括焦点和按键)被消费了。

dispatchKeyEvent(event)如果不了解,看我

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android:手把手教你 实现Activity 与 Fragment 相互通信(含Demo)
  • android自定义圆角背景实现富文本标题展示
  • 自定义收集用户行为统计库 (非常方便 可以自己拓展)
  • Android 6.0 Phone"通话显示"查询流程
  • Android缓存处理
  • 自定义进度条PictureProgressBar——从开发到开源发布全过程
  • 详解Android中的SQLite数据库存储
  • Android设备上获取照片、裁剪图片、压缩图片
  • Android触摸事件分发机制完全解析《一》
  • Android-SQLite和SQLiteOpenHelper

相关文章

  • 2017-05-26android:descendantFocusability用法,
  • 2017-05-26Android 如何本地加载pdf文件,android加载pdf
  • 2017-05-26理解android中ListFragment和Loader,androidlistfragment
  • 2017-05-26Android中通信协议,Android通信协议
  • 2017-05-26Android Studio创建/打开项目时一直处于Building“project name”Gradle project info的解决办法,androidgradle
  • 2017-05-26Linux内核系列—操作系统开发之HelloWorld,linuxhelloworld
  • 2017-05-26Android中常见的图片加载框架,
  • 2017-05-26AsyncTask.cancel()的结束问题,asynctaskcancel
  • 2017-05-26android:QQ多种侧滑菜单的实现
  • 2017-05-26zabbix 应用系列之nginx tcp stream监控

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android 指纹认证,android指纹认证
    • Android中使用ExpandableListView实现微信通讯录界面(完善仿微信APP),expandablelistview
    • android使用AIDL实现跨进程通讯(IPC)
    • 关于安卓APP的启动界面,安卓APP启动界面
    • Android热更新开源项目Tinker集成实践总结,androidtinker
    • Android开发学习之路--Content Provider之初体验
    • Java入门(二)——果然断更的都是要受惩罚的。。。,java受惩罚
    • andriod 动态显示当前时间,andriod当前时间
    • Android.mk模板(持续更新中),android.mk更新中
    • 我的Android进阶之旅之Android自定义View来实现解析lrc歌词同步滚动、上下拖动、缩放歌词等功能

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有