首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10000篇文章
优秀的个人博客,低调大师

Spark(八) -- 使用Intellij Idea搭建Spark开发环境

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq1010885678/article/details/45954731 Intellij Idea下载地址: 官方下载 选择右下角的Community Edition版本下载安装即可 本文中使用的是windows系统 环境为: jdk1.6.0_45 scala2.10.5 在网上下载jdk和scala的安装包双击运行安装即可 注意:如果之后要将scala文件打包成jar包并在spark集群上运行的话,请确保spark集群和打包操作所在机器 环境保持一致!不然运行jar包会出现很多异常 要使用idea开发spark程序首先要安装scala插件 进入idea主界面 在线安装: 选择Plugins 输入scala 选择安装即可 离线安装: scala离线插件包 下载完scala插件包之后,在idea主界面的Plugins中选择从本地安装 选择下载好的scala插件安装即可 本文使用的是Idea14.1.3 对应的scala插件版本为1.5 不同版本的Idea对应的scala插件版本可能不同,无法识别 现在可以用idea来新建一个scala项目 New Project->Scala 再此页面中选择jdk和scala安装的目录,Idea会自动识别 Finish完成Project的创建 在File中选择Project Structure对项目进行配置 选中左侧的Mudules,点击+号添加一下新的Module。Idea中的Project相当于Eclipse中的一个WorkSpace,里面的Module相当于Project 新建一个First的Module 在src目下新新建main和scala目录,并设置为Sources类型 点击左侧的Liberaries,点击+进行添加spark的jar包 只要引入图中的那个jar包即可,spark版本为1.3.1,一般下载spark之后可以在其目录下找到 在scala文件夹下右键新建一个scala class,类型选择为Object 编写简单的代码 File->Project Structure->在右侧选择Artifacts->JAR->From modules with dependencies 选择新建的Test 将默认的SparkApp:jar重新名一下,并将依赖包删除,只剩First这个module本身(因为集群上已经安装了jdk,scala和spark,所以那些包可以去掉节省编译时间) 在菜单栏上选择Build->Build Artifacts 如图所示的操作 编译成功后可以在对应的输出文件夹下找到jar包 需要注意: 编译选择Main Class时如果是手动选择Object的话,Idea会弹出错误提示xx is not acceptable,而让其自动过滤选择的时候就不会。。。 scala代码中,如果注释中有中文默认可能会编译错误 在下图设置中加入 -ENCODING UTF-8 即可

优秀的个人博客,低调大师

spark 之 Scala 环境搭建,开发工具使用

1,首先介绍官网网站 http://scala-lang.org/ 下载windows 的exe直接进行安装就行。 安装后有个本地文档可以使用: 2,工具使用 继续使用eclipse。如果是IDEA直接使用插件就行了。 http://scala-ide.org/download/current.html 安装url: http://download.scala-ide.org/sdk/helium/e38/scala210/stable/site 3,创建工程 scala 学习非常简单 http://zh.scala-tour.com/#/welcome 4,Hello world 在eclipse创建一个工程 package demo_001 object HelloWorld { def hello(name: String): String = { return "hello world, " + name } def main(args: Array[String]) { println(hello("scala")); } }

优秀的个人博客,低调大师

Python基础知识细节点总结,零基础一分钟也能掌握

既然要开始学习Python,那么就首先就得不官网下载个Python,小编使用的是3.6的 安装教程百度经验里面还是很详细的。 那么正题开始吧! 两种格式化输出的方式 第一种是用%操作格式化输出字符串 代码如下: 运行上面的代码输出的结果: 第二种使用format()方法去格式化输出字符串 代码直接一行语句搞定 你运行后发现结果还是一样的! Python中类型的转换 很多初学者在刚开始学习Python的对于数据类型有点弄不清楚,比如: a = 666 这是一个定义a为666,默认是整型 B = '666' 这是也直接定义,然后默认是字符串 在Python中有三个内建的函数可以让我们进行类型转换,他们分别是int(),float()和str()函数 int()函数接收一个浮点型或者合适的字符串 比如:int(3.1415)、int('1314')、int('3.1415') 那么他们的运行结果是不是一样呢? 结果很明显了,int()函数接收一个浮点型或者合适的字符串! float() 函数接收一个整数和一个合适的字符串 比如:float(23),float('3.1415') str( ) 函数是把一个整型或者浮点型的数变为字符串 比如:str(1231)、str(3.1415) 那么对于类型的转换了解了么,可以自己动手亲自去试一试呀 关于列表的一些操作 例如 age = [1,2,3,4,5,6] #其实这里面也可以放不同类型的数据 列表是可以更改的,如进行单个元素的添加及删除。 我们后面将会介绍元组,它是不能修改的。 下面列举一些列表的操作 age[2] =13 age[-1]=23 someage = age[2:4] someage = age[0:5:2] del age[1] age.append('没粉丝的程序狗')

优秀的个人博客,低调大师

HarmonyOS NEXT应用接续开发指南(基础

踏入鸿蒙世界的敲门砖,标志着您在技术征途上的全新起点,提升就业竞争力,获得行业认可,点亮职业成长先机,快人一步抢占未来应用开发赛道!https://developer.huawei.com/consumer/cn/training/dev-cert-detail/101666948302721398?ha_source=hmosclass-kaiyuanzhongguo&ha_sourceId=89000441 大家好!作为在华为鸿蒙开发领域深耕多年的开发者,今天我想和大家分享一下HarmonyOS NEXT中应用接续开发的相关知识。应用接续功能为用户带来了无缝切换设备使用应用的体验,大大提升了用户在多设备间的操作便利性。接下来,我们就深入探讨一下应用接续的具体内容。 应用接续的基本概念与应用场景 应用接续,简单来说,就是当用户在一个设备上操作某个应用时,能够在另一个设备上快速切换并继续该应用的任务,实现无缝衔接的使用体验。这一功能背后涉及到分布式状态同步技术,它确保了应用在不同设备间迁移时,用户的数据和操作状态能够得到准确的保存和恢复。 在实际使用场景中,应用接续发挥着重要作用。比如,当你在手机上浏览一篇长篇文章时,突然需要使用平板进行更舒适的阅读,这时应用接续功能就能让你在平板上继续从手机上中断的位置开始阅读,浏览器页面的滚动位置、阅读进度等都能完美同步。再比如,在PC上处理文档编辑任务时,如果需要外出,在手机上可以接着PC上的进度继续编辑,编辑器中的内容、格式设置等都不会丢失。这种从手机切换到平板,或者从PC继续手机上任务的场景,极大地提高了用户的工作和生活效率,让多设备协同使用更加流畅自然。 应用接续API解析 onContinue() onContinue() 是应用接续中源端UIAbility的关键接口。当应用触发迁移时,这个接口会在源端被调用。开发者可以在这个接口中完成多项重要操作,比如保存迁移所需要的数据。你可以把当前应用的关键信息,像编辑器中的文本内容、浏览器的当前页面URL等,通过键值对的方式保存在 wantParam 中。同时,还能进行应用兼容性检测,从 onContinue() 的入参 wantParam.version 获取迁移对端应用的版本号,与源端应用版本号进行比对,判断是否支持此次迁移。如果版本不兼容,可以返回相应的错误信息提示用户。示例代码如下: onCreate() 在目的端设备上,onCreate() 接口用于恢复迁移数据。通过 launchReason 判断该次启动是否为迁移启动,如果是,就可以从 want 中获取保存的迁移数据。例如: onNewWant() 对于单实例应用,还需要额外实现 onNewWant() 接口。它的实现方式与 onCreate() 类似,也是在判断为迁移场景时,恢复数据并触发页面恢复。示例代码如下: (转载自51CTO,作者:SameX)

优秀的个人博客,低调大师

Android事件分发-基础原理和场景分析

作者:京东零售郭旭锋 1 为什么需要事件分发 和其他平台类似,Android 中 View 的布局是一个树形结构,各个 ViewGroup 和 View 是按树形结构嵌套布局的,从而会出现用户触摸的位置坐标可能会落在多个 View 的范围内,这样就不知道哪个 View 来响应这个事件,为了解决这一问题,就出现了事件分发机制。 2 事件分发的关键方法 Android 中事件分发是从 Activity 开始的,可以看看各组件中事件分发的关键方法 组件 dispatchTouchEvent onInterceptTouchEvent onTouchEvent Activity √ × √ ViewGroup √ √ √ View √ × √ Activity:没有 onInterceptTouchEvent 方法,因为如果 Activity 拦截事件,将导致整个页面都没有响应,而 Activity 是系统应用和用户交互的媒介,不能响应事件显然不是系统想要的结果。所以 Activity 不需要拦截事件。 ViewGroup:三个方法都有,Android 中 ViewGroup 是一个布局容器,可以嵌套多个 ViewGroup 和 View,事件传递和拦截都由 ViewGroup 完成。 View:事件传递的最末端,要么消费事件,要么不消费把事件传递给父容器,所以也不需要拦截事件。 3 事件分发流程分析 3.1 事件分发流程概览 Activity 并不是一个 View,那么 Activity 是如何将事件分发到页面的 ViewGroup 和 View 的呢。我们先看看源码 # Activity public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } // 调用 Window 对象的方法,开始事件分发 if (getWindow().superDispatchTouchEvent(ev)) { return true; } // 如果事件分发返回 false,也即事件没被消费,则调用自己的 onTouchEvent 方法 return onTouchEvent(ev); } public boolean onTouchEvent(MotionEvent event) { if (mWindow.shouldCloseOnTouch(this, event)) { finish(); return true; } return false; } 可以看到,Activity 中的事件分发方法 dispatchTouchEvent 调用了 getWindow().superDispatchTouchEvent(ev) 方法,而这里的 WIndow 实际上是 PhoneWindow。 简单来说,Window 是一个抽象类,是所有视图的最顶层容器,视图的外观和行为都归他管,无论是背景显示、标题栏还是事件处理都是他管理的范畴,而 PhoneWindow 作为 Window的唯一亲儿子(唯一实现类),自然就是 View 界的皇帝了。 下来看看 PhoneWindow 的代码 # PhoneWindow @Override public boolean superDispatchTouchEvent(MotionEvent event) { return mDecor.superDispatchTouchEvent(event); } PhoneWindow 中又调用了 mDecor.superDispatchTouchEvent(event) 方法。mDecor 是 DecorView 对象,再看看 DecorView 的代码 # DecorView public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks { public boolean superDispatchTouchEvent(MotionEvent event) { return super.dispatchTouchEvent(event); } } # FrameLayout public class FrameLayout extends ViewGroup { } # ViewGroup public abstract class ViewGroup extends View implements ViewParent, ViewManager { public boolean dispatchTouchEvent(MotionEvent ev) { ...... } } # View public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { public boolean dispatchTouchEvent(MotionEvent ev) { ...... } } 可以看到,DecorView 实际上就是 ViewGroup,事件分发方法最终调用到了 ViewGroup 的 dispatchTouchEvent(MotionEvent ev) 方法。 DecorView 是 PhoneWindow 的一个对象,其职位就是跟在 PhoneWindow 身边专业为 PhoneWindow 服务的,除了自己要干活之外,也负责消息的传递,PhoneWindow 的指示通过 DecorView 传递给下面的 View,而下面 View 的信息也通过 DecorView 回传给 PhoneWindow。 Android 中的事件分发是责任链模式的一种变形。事件由上往下传递,如果事件没有被消费则继续传递到下一层,如果事件被消费则停止传递,如果到最下层事件则没有被消费,则事件会层层传递给上一层处理。我们都知道事件分发的源头在 Activity 中的 dispatchTouchEvent 方法中,事件从这里开始,分发到布局中的各个 View 中,不断递归调用 ViewGroup/View 的 dispatchTouchEvent 方法。通过上面分析可以看到,Activity 在接受到上层派发来的事件后,会把事件传递到自己的 dispatchTouchEvent 方法中,然后Activity 会把触摸、点击事件传递给自己的 mWindow 对象,最终传递给 DecorView 的 dispatchTouchEvent 方法,实际调用的是 ViewGroup 的 dispatchTouchEvent 方法。 3.2 事件分发源码分析 经过分析,可以知道 Android 中事件分发的关键方法就是 ViewGroup 和 View 中的相关方法,如下 # View public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { public boolean dispatchTouchEvent(MotionEvent event) { // ... 省略部分代码 boolean result = false; // ... 省略部分代码 if (onFilterTouchEventForSecurity(event)) { // ... 省略部分代码 // 1. 主要调用 onTouchEvent 方法,返回 true 说明事件被消费,否则没被消费 if (!result && onTouchEvent(event)) { result = true; } } // ... 省略部分代码 return result; } public boolean onTouchEvent(MotionEvent event) { // ... 省略部分代码 // 2. 默认可点击则返回 true,也就是消费事件。Button 或设置过 OnClickListener,则 View 可点击 if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) { switch (action) { case MotionEvent.ACTION_UP: // ... 省略部分代码 break; case MotionEvent.ACTION_DOWN: // ... 省略部分代码 break; case MotionEvent.ACTION_CANCEL: // ... 省略部分代码 break; case MotionEvent.ACTION_MOVE: // ... 省略部分代码 break; } return true; } return false; } } View 中的方法逻辑比较简单,如备注 1 所示,dispatchTouchEvent 主要就是做一些安全检查,检查通过后会调用 onTouchEvent 方法。而 onTouchEvent 方法中逻辑如备注 2 所示,如果 View 是可点击的,则默认会认为消费事件,否则不消费,一般 Button 控件,或设置过 OnClickListener 的控件,View 会被默认设置为可点击。 下面看看 ViewGroup 代码 # ViewGroup public abstract class ViewGroup extends View implements ViewParent, ViewManager { public boolean dispatchTouchEvent(MotionEvent ev) { // ... 省略部分代码 boolean handled = false; if (onFilterTouchEventForSecurity(ev)) { final int action = ev.getAction(); final int actionMasked = action & MotionEvent.ACTION_MASK; // 1. 如果是 DOWN 事件,则重置事件状态 if (actionMasked == MotionEvent.ACTION_DOWN) { // Throw away all previous state when starting a new touch gesture. // The framework may have dropped the up or cancel event for the previous gesture // due to an app switch, ANR, or some other state change. cancelAndClearTouchTargets(ev); resetTouchState(); } final boolean intercepted; // 2. 如果是 DOWN 事件,会判断当前 ViewGroup 是否要拦截事件。这里受两个因素影响: // 一是 FLAG_DISALLOW_INTERCEPT,如果设置不拦截,则不会调用 onInterceptTouchEvent,直接设置为不拦截 // 二是没设置 FLAG_DISALLOW_INTERCEPT 标志,默认允许拦截,会调用 onInterceptTouchEvent 方法 // 3. 如果不是 DOWN 事件,可能是 MOVE 或 UP 事件,mFirstTouchTarget 是记录需要继续进行事件分发的下一级子 View,包括ViewGroup 或 View,这里也分为两种情况 // 如果 mFirstTouchTarget 不为空,说明需要继续向下一级子 View/ViewGroup 分发事件,这时说明上次 DOWN 事件找到了下级有消费事件的子 View,且无拦截事件 // 如果 mFirstTouchTarget 为空,说明没找到要消费事件的子 View,或事件被拦截了 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. intercepted = true; } // ... 省略部分代码 TouchTarget newTouchTarget = null; boolean alreadyDispatchedToNewTouchTarget = false; // 4. 下面逻辑主要就是遍历寻找能消费事件的 View,如果事件被拦截,则不需要再寻找 if (!canceled && !intercepted) { // ... 省略部分代码 // 5. 只有 DOWN 事件才需要寻找,其他事件时已经确定是否找到,都不需要再找消费事件的 View 了 if (actionMasked == MotionEvent.ACTION_DOWN || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN) || actionMasked == MotionEvent.ACTION_HOVER_MOVE) { // ... 省略部分代码 final int childrenCount = mChildrenCount; if (newTouchTarget == null && childrenCount != 0) { // ... 省略部分代码 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); // 6. 这个方法是关键 // 如果 child 不为空,则会再调用 child.dispatchTouchEvent 方法,达到层层递归的效果 // 如果 child 为空,则会调用 super.dispatchTouchEvent 方法,super 是 View,实际上调用了 onTouchEvent 方法,自己判断是否消费事件 if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) { // ... 省略部分代码 // 7. 返回 true,说明找到了消费事件的 View,下面方法会给 mFirstTouchTarget 赋值,下面 mFirstTouchTarget 将不为空 // 注:mFirstTouchTarget 并不是最终消费事件的 View,而是下一级包含消费事件 View 的链表对象,或是直接消费事件的 View 的链表对象 // 每一个 ViewGourp 都会记录一个 mFirstTouchTarget,mFirstTouchTarget.child 记录了下一层消费事件的 ViewGroup 或 View // 同时,alreadyDispatchedToNewTouchTarget 变量会设置为 true newTouchTarget = addTouchTarget(child, idBitsToAssign); alreadyDispatchedToNewTouchTarget = true; break; } // ... 省略部分代码 } // ... 省略部分代码 } // ... 省略部分代码 } } // Dispatch to touch targets. if (mFirstTouchTarget == null) { // 8. 当没有找到消费事件的 View,或事件被拦截,mFirstTouchTarget 都不会被赋值,这里 child 为空,会调用自己的 onTouchEvent 方法 handled = dispatchTransformedTouchEvent(ev, canceled, null, TouchTarget.ALL_POINTER_IDS); } else { // Dispatch to touch targets, excluding the new touch target if we already // dispatched to it. Cancel touch targets if necessary. TouchTarget predecessor = null; TouchTarget target = mFirstTouchTarget; while (target != null) { final TouchTarget next = target.next; // 9. 说明找到了消费事件的 View,并且已经分发,直接设置为已处理 if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) { handled = true; } else { final boolean cancelChild = resetCancelNextUpFlag(target.child) || intercepted; // 10. 此方法和备注 6 和 8 都一样,这里多了 cancel 的处理逻辑。如果事件被拦截,需要给原来消费事件的 View 发一个 CANCEL 事件 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; } public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.isFromSource(InputDevice.SOURCE_MOUSE) && ev.getAction() == MotionEvent.ACTION_DOWN && ev.isButtonPressed(MotionEvent.BUTTON_PRIMARY) && isOnScrollbarThumb(ev.getX(), ev.getY())) { return true; } // 默认不拦截 return false; } // 没有覆写这个方法,实际调用的是 View 的 onTouchEvent 方法 public boolean onTouchEvent(MotionEvent event) { } } 可以看到,ViewGroup 中的事件分发逻辑还是比较复杂,但抓住关键点后则很容易能看清它的本来面貌 (1)分发的事件包括 DOWN、MOVE、UP、CANCEL 几种,用户一个完整的动作就是由这几个事件组合而成的 (2)只有 DOWN 事件中会寻找消费事件的目标 View,其他事件不会再寻找 (3)DOWN 事件寻找到目标 View 后,后续其他事件都会直接分发至目标 View (4)事件可以被拦截,拦截后原目标 View 会收到 CANCEL 事件,后续将不会再收到任何事件(这也是这套机制不支持丰富的嵌套滑动的原因) 3.3 事件分发情景分析 3.3.1 分发过程没有任何 View 拦截和消费  (1)事件返回时,为了简化理解,dispatchTouchEvent 直接指向了父 View 的 onTouchEvent ,实际上它仅仅是返回给父 View 的 dispatchTouchEvent 一个 false 值(影响了 mFirstTouchTarget 的值),父 View 根据返回值来调用自身的onTouchEvent 方法 (2)ViewGroup 是根据 onInterceptTouchEvent 的返回值(影响了 mFirstTouchTarget 的值)确定是调用子 View 的 dispatchTouchEvent 还是自身的 onTouchEvent 方法 (3)如果所有 View 都没有消费 DOWN 事件,后续 MOVE 和 UP 不会再往下传递,会直接传递给 Activity 的 onTouchEvent 方法 3.3.2 最底层View消费事件,且上层View没有拦截事件  (1)若没有 ViewGroup 对事件进行拦截,而最底层 View 消费了此事件,也就是接收到 DOWN 事件时 View 的 onTouchEvent 返回 true,事件将不会再向上传递给各个 ViewGroup 的 onTouchEvent 方法,而是直接返回,后续的 MOVE 和 UP 事件也将会直接交给 View 进行处理 3.3.3 最底层View没有消费事件,ViewGroup2消费了事件,且上层View没有拦截事件 (1)如果 View 没有消费事件,在层层调用父布局的 onTouchEvent 方法时,有 View 消费此事件,如 ViewGroup2 消费此事件,后续 MOVE 和 UP 事件将会传递给 ViewGroup2 的 onTouchEvent 方法,而且不会再调用 ViewGroup2 的 onInterceptTouchEvent 方法 (2)源码 if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {} 这个代码中主要调用 onInterceptTouchEvent() 方法和处理是否拦截 第一次是 DOWN 事件会进行判断,所以会调用 onInterceptTouchEvent 拦截方法 第二次非 DOWN 事件,不会再调用 onInterceptTouchEvent 方法。原因如下: ◦ 如果 DOWN 事件的时候进行过拦截,也就是 onInterceptTouchEvent() 方法返回 true,则 mFirstTouchTarget 必定为 null,不会调用 onInterceptTouchEvent 方法。因为后面不会对这个值赋值,会往下走逻辑,直接调用到此 View 或 ViewGroup 的 onTouchEvent() 方法 ◦ 如果 DOWN 事件没有拦截,但子 View 的 onTouchEvent 都返回 false,只有当前 ViewGroup 的 onTouchEvent 返回 true,mFirstTouchTarget 也同样为 null,也不会调用 onInterceptTouchEvent 方法。因为 mFirstTouchTarget 本质是找能接收事件的子 View,所有子 View 都不接收事件,mFirstTouchTarget 就必然为 null 3.3.4 ViewGroup2拦截了并消费了DOWN事件,其他View没有拦截事件  (1)ViewGroup2 拦截 DOWN 事件后,View 不会接收到任何事件。ViewGroup2 消费事件后,后续 MOVE 和 UP 事件会交给 ViewGroup2 的 onTouchEvent 方法进行处理,且不会再调用 ViewGroup2 的onInterceptTouchEvent 方法 3.3.5 View消费了DOWN事件,ViewGroup2拦截且消费了MOVE事件,其他View没有拦截事件  (1)View 中 DOWN 事件正常传递 (2)当 ViewGroup2 拦截 MOVE 事件后,当前 mFirstTouchTarget 不为空,首先 View 会收到转换后的 CANCEL 事件,mFirstTouchTarget 会置为空,下次 MOVE 事件由于 mFirstTouchTarget 为空,会调用到自己的 onTouchEvent 方法 3.3.6 View消费 DOWN 事件,ViewGroup2拦截且消费了MOVE事件,一定条件后,ViewGroup1再次拦截和消费MOVE事件,其他View没有拦截事件  3.4 事件分发总结 (1)整个分发过程中没有任何拦截和消费,DOWN 事件会层层往下分发,并层层往上返回 false,MOVE 和 UP 事件则会交给 Activity 的 onTouchEvent 方法进行处理,不再往下分发 (2)分发过程中没有任何拦截但有消费,DOWN 事件会层层往下分发,并层层往上返回false,直到有消费返回 true,MOVE 和 UP 事件则会层层往下分发,最后直接交给消费事件的 View 进行处理,然后层层返回 true (3)分发过程中有拦截且拦截后消费,DOWN 事件会层层往下分发,直到有拦截后直接交给消费的 View 进行处理,MOVE 和 UP 事件则会层层往下分发,最后直接交给消费事件的 View 进行处理,然后层层返回true (4)分发过程中不拦截 DOWN 事件,但拦截 MOVE 事件且拦截后消费,第一次拦截,之前收到 DOWN 事件的子 View 会收到 CANCEL 事件,并层层返回;后续 MOVE 和 UP 会层层往下分发,最后直接交给消费事件的 View 进行处理 (5)分发过程中不拦截 DOWN 事件,但拦截 MOVE 事件且拦截后不消费,第一次拦截,之前收到 DOWN 事件的子 View 会收到 CANCEL 事件,并层层返回;后续 MOVE 和 UP 会层层往下分发,最后交给拦截的 View 进行处理,此时由于拦截的 View 没有消费,会层层往上返回 false,最后会交给 Activity 的 onTouchEvent 方法进行处理 以上,是个人的一些分析和经验,欢迎有兴趣的小伙伴一起学习和探讨!

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册