onInterceptTouchEvent和onTouchEvent调用时序

触摸事件传递机制
本文详细解析了Android中onInterceptTouchEvent和onTouchEvent方法的工作原理及调用时序,通过实例展示了不同返回值对事件传递的影响。

onInterceptTouchEvent和onTouchEvent调用时序

onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。 

onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。 

关于返回值的问题,基本规则很清楚,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。

SDK给出的说明如下:

· You will receive the down event here.

· The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.

· For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().

·  If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.

 

由于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:

1.       down事件首先会传递到onInterceptTouchEvent()方法

2.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。

3.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。

4.       如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。

5.       如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

 

下面用一个简单的实验说明上述复杂的规则。视图自底向上共3层,其中LayoutView1和LayoutView2就是LinearLayout, MyTextView就是TextView:

对应的xml布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <com.touchstudy.LayoutView2
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center">
       <com.touchstudy.MyTextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tv"
            android:text="AB"
            android:textSize="40sp"
            android:textStyle="bold"
            android:background="#FFFFFF"
            android:textColor="#0000FF"/>
   </com.touchstudy.LayoutView2>
</com.touchstudy.LayoutView1>


 

下面看具体情况:

1.       onInterceptTouchEvent()处理down事件均返回falseonTouchEvent()处理事件均返回true

------------------------------------------------------------------------------------------------------------------------------

04-11 03:58:42.620: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:58:42.620: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:58:42.620: DEBUG/MyTextView(614): onTouchEvent action:ACTION_DOWN

04-11 03:58:42.800: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_MOVE

04-11 03:58:42.800: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_MOVE

04-11 03:58:42.800: DEBUG/MyTextView(614): onTouchEvent action:ACTION_MOVE

…… //省略过多的ACTION_MOVE

04-11 03:58:43.130: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_UP

04-11 03:58:43.130: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_UP

04-11 03:58:43.150: DEBUG/MyTextView(614): onTouchEvent action:ACTION_UP

------------------------------------------------------------------------------------------------------------------------------

这是最常见的情况,onInterceptTouchEvent并没有做任何改变事件传递时序的操作,效果上和没有覆写该方法是一样的。可以看到,各种事件的传递本身是自底向上的,次序是:LayoutView1->LayoutView2->MyTextView。注意,在onInterceptTouchEvent均返回false时,LayoutView1和LayoutView2的onTouchEvent并不会收到事件,而是最终传递给了MyTextView。

 

2.     LayoutView1onInterceptTouchEvent()处理down事件返回true

MyTextViewonTouchEvent()处理事件返回true

------------------------------------------------------------------------------------------------------------------------------

04-11 03:09:27.589: DEBUG/LayoutView1(446): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:09:27.589: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_DOWN

04-11 03:09:27.629: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE

04-11 03:09:27.689: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE

…… //省略过多的ACTION_MOVE

04-11 03:09:27.959: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_UP

------------------------------------------------------------------------------------------------------------------------------

从Log可以看到,由于LayoutView1在拦截第一次down事件时return true,所以后续的事件(包括第一次的down)将由LayoutView1本身处理,事件不再传递下去。

 

3.       LayoutView1LayoutView2onInterceptTouchEvent()处理down事件返回false

MyTextViewonTouchEvent()处理事件返回false

LayoutView2onTouchEvent()处理事件返回true

----------------------------------------------------------------------------------------------------------------------------

04-11 09:50:21.147: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/LayoutView2(301): onInterceptTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/MyTextView(301): onTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_DOWN

04-11 09:50:21.176: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE

04-11 09:50:21.176: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE

04-11 09:50:21.206: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE

04-11 09:50:21.217: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE

…… //省略过多的ACTION_MOVE

04-11 09:50:21.486: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_UP

04-11 09:50:21.486: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_UP

----------------------------------------------------------------------------------------------------------------------------

可以看到,由于MyTextView在onTouchEvent()中return false,down事件被传递给其父view,即LayoutView2的onTouchEvent()方法处理,由于在LayoutView2的onTouchEvent()中return true,所以down事件传递并没有上传到LayoutView1。注意,后续的move和up事件均被传递给LayoutView2的onTouchEvent()处理,而没有传递给MyTextView。

 

----------------------------------------------------------------------------------------------------------------

应大家的要求,我把源代码贴上,其实很简单,就是基础文件,主要是用来观察事件的传递。

 

主Activity: InterceptTouchStudyActivity.java:
public class InterceptTouchStudyActivityextends Activity {
    static final String TAG = "ITSActivity";
    TextView tv;
    /** Calledwhen the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       setContentView(R.layout.layers_touch_pass_test);
     }
 }
      LayoutView1.java:
      public class LayoutView1 extends LinearLayout {
     private final String TAG = "LayoutView1";
       public LayoutView1(Context context, AttributeSet attrs) {
         super(context, attrs);
         Log.d(TAG,TAG);
     }
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         int action = ev.getAction();
         switch(action){
         case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onInterceptTouchEventaction:ACTION_DOWN");
//            return true;
              break;
         case MotionEvent.ACTION_MOVE:
              Log.d(TAG,"onInterceptTouchEventaction:ACTION_MOVE");
              break;
         case MotionEvent.ACTION_UP:
              Log.d(TAG,"onInterceptTouchEventaction:ACTION_UP");
              break;
         case MotionEvent.ACTION_CANCEL:
              Log.d(TAG,"onInterceptTouchEventaction:ACTION_CANCEL");
              break;
         }
         return false;
     }
     @Override

     public boolean onTouchEvent(MotionEvent ev) {
         int action = ev.getAction();
         switch(action){
         case MotionEvent.ACTION_DOWN:
              Log.d(TAG,"onTouchEventaction:ACTION_DOWN");
              break;
         case MotionEvent.ACTION_MOVE:
              Log.d(TAG,"onTouchEventaction:ACTION_MOVE");
              break;
         case MotionEvent.ACTION_UP:
              Log.d(TAG,"onTouchEventaction:ACTION_UP");
              break;
         case MotionEvent.ACTION_CANCEL:
              Log.d(TAG,"onTouchEventaction:ACTION_CANCEL");
              break;
         }

        

         return true;

     }

     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         // TODO Auto-generatedmethod stub
         super.onLayout(changed, l, t, r, b);
     }
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // TODO Auto-generatedmethod stub
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
}

LayoutView2.java:

 
public class LayoutView2 extends LinearLayout {

    private final String TAG = "LayoutView2";

    public LayoutView2(Context context, AttributeSet attrs) {
       super(context, attrs);
       Log.d(TAG,TAG);

    }

 

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
       int action = ev.getAction();
       switch(action){
       case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onInterceptTouchEventaction:ACTION_DOWN");
           break;
       case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onInterceptTouchEventaction:ACTION_MOVE");
           break;
       case MotionEvent.ACTION_UP:
Log.d(TAG,"onInterceptTouchEventaction:ACTION_UP");
           break;
       case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onInterceptTouchEventaction:ACTION_CANCEL");
           break;
       }
       return false;
    }
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
       int action = ev.getAction();
       switch(action){
       case MotionEvent.ACTION_DOWN:
      Log.d(TAG,"onTouchEventaction:ACTION_DOWN");
           break;
       case MotionEvent.ACTION_MOVE:
       Log.d(TAG,"onTouchEventaction:ACTION_MOVE");
           break;
       case MotionEvent.ACTION_UP:
           Log.d(TAG,"onTouchEventaction:ACTION_UP");
           break;
       case MotionEvent.ACTION_CANCEL:
           Log.d(TAG,"onTouchEventaction:ACTION_CANCEL");
           break;
       }
       return true;
    } 
}
MyTextView.java:

public class MyTextView extends TextView {
    private final String TAG = "MyTextView";
    public MyTextView(Context context, AttributeSet attrs) {
       super(context, attrs);
       Log.d(TAG,TAG);
    }
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
       int action = ev.getAction();
       switch(action){
       case MotionEvent.ACTION_DOWN:
      Log.d(TAG,"onTouchEventaction:ACTION_DOWN");
           break;
       case MotionEvent.ACTION_MOVE:
       Log.d(TAG,"onTouchEventaction:ACTION_MOVE");
           break;
       case MotionEvent.ACTION_UP:
           Log.d(TAG,"onTouchEventaction:ACTION_UP");
           break;
       case MotionEvent.ACTION_CANCEL:
    Log.d(TAG,"onTouchEventaction:ACTION_CANCEL");
           break;
       }
       return false;
    }

    public void onClick(View v) {
       Log.d(TAG, "onClick");
    }

    public boolean onLongClick(View v) {
       Log.d(TAG, "onLongClick");
       return false;
    }
}



内容概要:本文介绍了一个基于冠豪猪优化算法(CPO)的无人机三维路径规划项目,利用Python实现了在复杂三维环境中为无人机规划安全、高效、低能耗飞行路径的完整解决方案。项目涵盖空间环境建模、无人机动力学约束、路径编码、多目标代价函数设计以及CPO算法的核心实现。通过体素网格建模、动态障碍物处理、路径平滑技术多约束融合机制,系统能够在高维、密集障碍环境下快速搜索出满足飞行可行性、安全性与能效最优的路径,并支持在线重规划以适应动态环境变化。文中还提供了关键模块的代码示例,包括环境建模、路径评估CPO优化流程。; 适合人群:具备一定Python编程基础优化算法基础知识,从事无人机、智能机器人、路径规划或智能优化算法研究的相关科研人员与工程技术人员,尤其适合研究生及有一定工作经验的研发工程师。; 使用场景及目标:①应用于复杂三维环境下的无人机自主导航与避障;②研究智能优化算法(如CPO)在路径规划中的实际部署与性能优化;③实现多目标(路径最短、能耗最低、安全性最高)耦合条件下的工程化路径求解;④构建可扩展的智能无人系统决策框架。; 阅读建议:建议结合文中模型架构与代码示例进行实践运行,重点关注目标函数设计、CPO算法改进策略与约束处理机制,宜在仿真环境中测试不同场景以深入理解算法行为与系统鲁棒性。
在科技快速演进的时代背景下,移动终端性能持续提升,用户对移动应用的功能需求日益增长。增强现实、虚拟现实、机器人导航、自动驾驶辅助、手势识别、物体检测与距离测量等前沿技术正成为研究与应用的热点。作为支撑这些技术的核心,双目视觉系统通过模仿人类双眼的成像机制,同步获取两路图像数据,并借助图像处理与立体匹配算法提取场景深度信息,进而生成点云并实现三维重建。这一技术体系对提高移动终端的智能化程度及优化人机交互体验具有关键作用。 双目视觉系统需对同步采集的两路视频流进行严格的时间同步与空间校正,确保图像在时空维度上精确对齐,这是后续深度计算与立体匹配的基础。立体匹配旨在建立两幅图像中对应特征点的关联,通常依赖复杂且高效的计算算法以满足实时处理的要求。点云生成则是将匹配后的特征点转换为三维空间坐标集合,以表征物体的立体结构;其质量直接取决于图像处理效率与匹配算法的精度。三维重建基于点云数据,运用计算机图形学方法构建物体或场景的三维模型,该技术在增强现实与虚拟现实等领域尤为重要,能够为用户创造高度沉浸的交互环境。 双目视觉技术已广泛应用于多个领域:在增强现实与虚拟现实中,它可提升场景的真实感与沉浸感;在机器人导航与自动驾驶辅助系统中,能实时感知环境并完成距离测量,为路径规划与决策提供依据;在手势识别与物体检测方面,可精准捕捉用户动作与物体位置,推动人机交互设计与智能识别系统的发展。此外,结合深度计算与点云技术,双目系统在精确距离测量方面展现出显著潜力,能为多样化的应用场景提供可靠数据支持。 综上所述,双目视觉技术在图像处理、深度计算、立体匹配、点云生成及三维重建等环节均扮演着不可或缺的角色。其应用跨越多个科技前沿领域,不仅推动了移动设备智能化的发展,也为丰富交互体验提供了坚实的技术基础。随着相关算法的持续优化与硬件性能的不断提升,未来双目视觉技术有望在各类智能系统中实现更广泛、更深层次的应用。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
本软件提供多种基于张量理论的流动诱导纤维取向计算功能,涵盖Jeffrey模型、Folgar-Tucker模型及各向异性旋转扩散系列(如Phelps-Tucker五参数模型、iARD、pARD、MRD与Wang双参数模型)以及慢速动力学方法(包括SRF、RSC与RPR)。针对四阶方向张量,支持三维空间中的线性、二次、混合、正交各向异性、自然及IBOF闭合近似;在平面取向分析中,则提供Bingham分布、自然近似、椭圆半径法、正交各向异性D型与非正交F型等多种闭合方案。 软件可计算平面或三维条件下的完整方向分布函数,适用于瞬态或稳态过程,并整合了Jeffery、Folgar-Tucker与ARD等基础取向动力学模型。同时支持基于Phelps-Tucker理论的纤维长度分布演化模拟。 在线弹性刚度预测方面,集成了平均场模型体系,包括Halpin-Tsai公式、稀释Eshelby解、Mori-Tanaka方法及Lielens双夹杂模型,适用于单向或分布型纤维取向情况。所有刚度模型均可导出对应的热应力张量与热膨胀张量。 此外,软件具备经典层压板理论分析能力,可处理随厚度变化的纤维取向对复合材料板刚度的影响。在分布函数重构方面,提供Jeffery解析解、Bingham分布、椭圆半径法及四阶最大熵函数等多种方法用于平面取向分布的重建。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值