当前位置: 首页 > news >正文

网站上的专题 怎么设计谷歌ads

网站上的专题 怎么设计,谷歌ads,wordpress 代码 格式,用ps做的网站怎么发布概述 本文主要讲述App View中inputEvent事件分发的流程,我们这里不讲述关于Android View窗口管理系统。Android系统中View的事件分发的方向就是: Activity -> PhoneWindow -> DecorView -> ViewGroup -> View 当事件被处理完成后,根据事件…

概述

        本文主要讲述App View中inputEvent事件分发的流程,我们这里不讲述关于Android View窗口管理系统。Android系统中View的事件分发的方向就是:

Activity -> PhoneWindow -> DecorView -> ViewGroup -> View

当事件被处理完成后,根据事件处理的结果然,反向调用路径返回:

从View-> ViewGroup->DecorView->PhoneWindow->Activity

本文涉及的源码路径

        frameworks/base/core/java/android/view/ViewRootImpl.java

        frameworks/base/core/java/android/view/View.java

事件分发

        上篇我们讲了,事件分发过程中,会找到目标View开始分发,如下代码所示:

 private int processPointerEvent(QueuedInputEvent q) {final MotionEvent event = (MotionEvent)q.mEvent;mAttachInfo.mUnbufferedDispatchRequested = false;final View eventTarget =(event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?mCapturingView : mView;mAttachInfo.mHandlingPointerEvent = true;boolean handled = eventTarget.dispatchPointerEvent(event);maybeUpdatePointerIcon(event);mAttachInfo.mHandlingPointerEvent = false;if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {mUnbufferedInputDispatch = true;if (mConsumeBatchedInputScheduled) {scheduleConsumeBatchedInputImmediately();}}return handled ? FINISH_HANDLED : FORWARD;}

继续调用View中的dispatchPointerEvent方法,如下所示:

 public final boolean dispatchPointerEvent(MotionEvent event) {if (event.isTouchEvent()) {return dispatchTouchEvent(event);} else {return dispatchGenericMotionEvent(event);}}

然后调用dispacthTouchEvent方法,开始从顶层的Activity一层一层,向能接受输入事件的view进行处理,为什么时Activity中的dispacthTouchEvent方法,这里不再追踪原因,感兴趣的同学可以学习一下Android系统中的窗口管理相关的知识。

1、Activity中的事件分发

Activity中事件分发,如下所示:

  public boolean dispatchTouchEvent(MotionEvent ev) {Log.i(TAG, "dispatchTouchEvent");if (ev.getAction() == MotionEvent.ACTION_DOWN) {onUserInteraction();}// 调用子类实现PhoneWindow中的superDispatchTouchEvent()if (getWindow().superDispatchTouchEvent(ev)) {return true;}return onTouchEvent(ev);}

该方法的核心逻辑如下:

a. 调用PhoneWindow中的superDispatchTouchEvent进行分发;

b. 如果事件在PhoneWindow中没有被处理,则调用Activty自己的onTouchEvent方法,默认返回false, 表示事件没有被处理;

2、PhoneWindow中的事件分发

PhoneWindow中调用比较简单,直接交给DecorView处理,如下所示:

 @Overridepublic boolean superDispatchTouchEvent(MotionEvent event) {Log.i(TAG, "superDispatchTouchEvent");return mDecor.superDispatchTouchEvent(event);}

3、DecorView中的事件分发

DecorView中也不直接处理,而是调用父类的dispatchTouchEvent处理,如下所示:

public boolean superDispatchTouchEvent(MotionEvent event) {Log.i(TAG, "superDispatchTouchEvent");return super.dispatchTouchEvent(event);}

4、ViewGroup中的事件分发

第3步中,事件由DecorView中父类处理,DecorView的父类为FrameLayout,FrageLayout继承ViewGroup,我们从FrameLayout中没有找到dispatchTouchEvent, 再次向上找父类,从ViewGroup中找到了dispatchTouchEvent方法,饶了一圈,最终调用到了ViewGroup中的dispatchTouchEvent如下所示:

public boolean dispatchTouchEvent(MotionEvent ev) {......boolean handled = false;if (onFilterTouchEventForSecurity(ev)) {......// Check for interception.// 检查事件是否可以被拦截final boolean intercepted;if (actionMasked == MotionEvent.ACTION_DOWN|| mFirstTouchTarget != null) {final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;if (!disallowIntercept) {intercepted = onInterceptTouchEvent(ev);ev.setAction(action); // restore action in case it was changed} else {intercepted = false;}} else {// There are no touch targets and this action is not an initial down// so this view group continues to intercept touches.// 如果当前事件没有处理它的子view,也不是ACTION_DOWN事件,则父类拦截intercepted = true;}......//如果没取消和拦截if (!canceled && !intercepted) {......if (newTouchTarget == null && childrenCount != 0) {final float x = ev.getX(actionIndex);final float y = ev.getY(actionIndex);// Find a child that can receive the event.// Scan children from front to back.// 找到一个能接受事件的子view// 按照显示在最上层到最下层的顺序去遍历final View[] children = mChildren;for (int i = childrenCount - 1; i >= 0; i--) {final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);// canViewReceivePointerEvents方法判断子view是否visible或者子view是否在播动画或者即将播动画// isTransformedTouchPointInView方法判断点击区域是否处于子view内if (!canViewReceivePointerEvents(child)|| !isTransformedTouchPointInView(x, y, child, null)) {ev.setTargetAccessibilityFocus(false);continue;}//dispatchTransformedTouchEvent方法是真正把事件分发给子view处理的// 返回值为true则代表该子view处理了事件if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {......}}......TouchTarget target = mFirstTouchTarget;while (target != null) {final TouchTarget next = target.next;if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {handled = true;} else {final boolean cancelChild = resetCancelNextUpFlag(target.child)|| intercepted;if (dispatchTransformedTouchEvent(ev, cancelChild, target.child, target.pointerIdBits)) {handled = true;}if (cancelChild) {if (predecessor == null) {mFirstTouchTarget = next;} else {predecessor.next = next;}target.recycle();target = next;continue;}}predecessor = target;target = next;}}.......return handled;}

该方法事件比较复杂,我为了简化事件分发流程,我在这个只保留了最核心的实现,该方法的实现逻辑如下:

1、遍历ViewGroup中的view,找到能接受input事件的View;

2、调用dispatchTransformedTouchEvent()进行事件处理;

3、返回事件处理的结果handled;

5、View中的事件分发

当找到能接受输入事件的子View后,调用dispatchTransformedTouchEvent进入事件的进一步分发,如下所示:

 private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,View child, int desiredPointerIdBits) {......final int oldAction = event.getAction();if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {event.setAction(MotionEvent.ACTION_CANCEL);if (child == null) {//如果子view为空,直接调了ViewGroup的父类View的dispatchTouchEvent方法handled = super.dispatchTouchEvent(event);} else {//如果子view不等于空,调用子view的dispatchTouchEvent方法//如果子view是一个ViewGroup,则递归ViewGroup的dispatchTouchEvent方法,重复上面分析的逻辑//如果子view是普通的view,则事件分发到View的dispatchTouchEvent方法handled = child.dispatchTouchEvent(event);}event.setAction(oldAction);return handled;}......}

该方法中直接执行view中的dispatchTouchEvent方法,这里有一种ViewGroup嵌套的情况下,则继续重复之前的流程,为了简化描述流程,我们这里假设找到最后的孩子view(比如Button)。 然后调用dispatchTouchEvent如下所示:

public boolean dispatchTouchEvent(MotionEvent event) {// If the event should be handled by accessibility focus first.if (event.isTargetAccessibilityFocus()) {......if (onFilterTouchEventForSecurity(event)) {if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {result = true;}//noinspection SimplifiableIfStatement// 已经注册了onToucherListenero监听,不再调用onTouchEvent处理ListenerInfo li = mListenerInfo;if (li != null && li.mOnTouchListener != null&& (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) {result = true;}//只有result为false事件才分发到onTouchEventif (!result && onTouchEvent(event)) {result = true;}}......return result;}

我们这里假设没有注册touch监听,则调用view中的onTouchEvent方法,如下所示:

public boolean onTouchEvent(MotionEvent event) {final float x = event.getX();final float y = event.getY();final int viewFlags = mViewFlags;final int action = event.getAction();if (((viewFlags & CLICKABLE) == CLICKABLE ||(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||(viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {switch (action) {case MotionEvent.ACTION_UP:......if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {// This is a tap, so remove the longpress checkremoveLongPressCallback();// Only perform take click actions if we were in the pressed stateif (!focusTaken) {// Use a Runnable and post this rather than calling// performClick directly. This lets other visual state// of the view update before click actions start.//调用OnClickListener的onClick方法if (mPerformClick == null) {mPerformClick = new PerformClick();}if (!post(mPerformClick)) {performClick();}}}......case MotionEvent.ACTION_DOWN:......if (isInScrollingContainer) {mPrivateFlags |= PFLAG_PREPRESSED;if (mPendingCheckForTap == null) {mPendingCheckForTap = new CheckForTap();}mPendingCheckForTap.x = event.getX();mPendingCheckForTap.y = event.getY();postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());} else {// Not inside a scrolling container, so show the feedback right awaysetPressed(true, x, y);checkForLongClick(0, x, y);}break;}return true;}return false;}

该方法的最终调用performClick让控件去处理事件,如下所示:

 public boolean performClick() {final boolean result;final ListenerInfo li = mListenerInfo;if (li != null && li.mOnClickListener != null) {playSoundEffect(SoundEffectConstants.CLICK);li.mOnClickListener.onClick(this);result = true;} else {result = false;}sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);return result;}

        最后,调用到了onClick方法,回调App对输入事件的处理接口,事件在这里就到了它最终的到达的地方。我们不再展开讲述如果在这条路径上,如果事件没有被处理的情况。

总结

        本文主要描述了,Android View事件分发被处理的流程,在讲述过程中,为了简化,我们删除了很多细节的东西。因为讲述Android View Input事件不能单独拿出来讲述,因为涉及的内容比较多,希望以后自己能力达到了,再补充上我删除的部分,Android 7 Input 子系统的框架梳理到此为止,下一个专题Android  HAL层开发;

http://www.dinnco.com/news/9113.html

相关文章:

  • 做网站开发使用百分比的好处谷歌排名算法
  • 株洲做网站客服电话杭州seo排名
  • 大连淘宝网站建设站长工具查询入口
  • 自己电脑做网站如何做推广最有效果
  • 商场设计任务书windows优化工具
  • 市场营销培训机构排名开鲁seo网站
  • 莱芜吧莱芜贴吧杭州网站seo外包
  • wordpress有中文版吗长沙网站优化对策
  • 百度关键词搜索推广广州seo网站优化培训
  • 遂宁网站开发怎样自己开发一款软件
  • apico云开发平台百度推广seo效果怎么样
  • wordpress手机版app导航湛江百度seo公司
  • 如何用模板搭建网站亚马逊排名seo
  • 怎么在阿里巴巴网站做公司济南优化网站关键词
  • ppt制作网站推荐手机营销软件
  • 专做批发的网站有哪些百度问答平台入口
  • 免费企业网站系统源码百度收录快的发帖平台
  • 门户网站域名是什么意思百度联盟怎么加入
  • 北京网站建设开发公司哪家好安卓系统优化软件
  • 妹妹强迫我和她做网站腾讯营销平台
  • wordpress 会员支付宝站长之家seo一点询
  • 企业网站设计制作收费济南seo全网营销
  • 杭州市城乡建设委员会的网站百度广告收费
  • 手机免费建设网站制作北京网站制作400办理多少钱
  • 河北网站设计推荐柚米科技seo优化要做什么
  • 苏州做网站的seo公司赚钱吗
  • 除了做视频网站还能做什么网站网络推广优化工具
  • 禹城做网站的公司最好的网络推广方式
  • 传媒网站设计公司不要手贱搜这15个关键词
  • 苏州高端网站建设开发新东方托福班价目表