有时候,按照视觉图做出来效果后,发现点击区域过小,不好点击,用户体验肯定不好。扩大视图,就会导致整个视觉图变得不好看。那么有没有什么办法在不改变视图大小的前提下扩大点击区域呢?

答案是有!

能够解决这个问题的前提你要对 View 的事件分发机制有一定的了解。

下面我将简单介绍一下View 的事件分发机制,方便大家理解后面的解决办法。

为了更清楚的说明整个机制,采用如下的视图来说明点击的事件分发机制。下图是一个 FrameLayout (ViewGroup) 里面包含着一个 ImageView (View)。

先自定义一个 MyFrameLayout,继承FrameLayout,并实现两个点击相关的接口;具体代码如下:

public class MyFrameLayout extends FrameLayout implements OnClickListener, OnTouchListener {

private static final String TAG = "Event";

public MyFrameLayout(Context context, AttributeSet attrs) {

super(context, attrs);

Log.d(TAG, "MyFrameLayout init");

setOnClickListener(this);

setOnTouchListener(this);

}

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

Log.d(TAG, "MyFrameLayout dispatchTouchEvent " + event.getAction());

return super.dispatchTouchEvent(event);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

Log.d(TAG, "MyFrameLayout onTouchEvent " + event.getAction() );

return super.onTouchEvent(event);

}

@Override

public void onClick(View view) {

Log.d(TAG, "MyFrameLayout onClick");

}

@Override

public boolean onTouch(View view, MotionEvent event) {

Log.d(TAG, "MyFrameLayout onTouch " + event.getAction());

return true;

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

Log.d(TAG, "MyFrameLayout onInterceptTouchEvent " + ev.getAction());

return super.onInterceptTouchEvent(ev);

}

}

接着,对于 ImageView 也做类似的操作,具体代码如下:

public class MyImageView extends ImageView implements OnClickListener, OnTouchListener {

private static final String TAG = "Event";

public MyImageView(Context context, AttributeSet attrs) {

super(context, attrs);

Log.d(TAG, "MyImageView init");

setOnClickListener(this);

setOnTouchListener(this);

}

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

Log.d(TAG, "MyImageView dispatchTouchEvent "+ event.getAction());

return super.dispatchTouchEvent(event);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

Log.d(TAG, "MyImageView onTouchEvent "+ event.getAction());

return super.onTouchEvent(event);

}

@Override

public boolean onTouch(View arg0, MotionEvent arg1) {

Log.d(TAG, "MyImageView onTouch " + arg1.getAction());

return false;

}

@Override

public void onClick(View arg0) {

Log.d(TAG, "MyImageView onClick");

}

}

这里要说明的是,只有ViewGroup才有 onInterceptTouchEvent 方法的,普通的 View 是没有的,它是不能对事件进行拦截的。

那这时候,如果我们点击里面的 ImageView,会有怎样的输出呢?结果如下图。

那如果点击外层呢?

0,1,2分别是代表 ACTION_DOWN,ACTION_UP,ACTION_MOVE;从中也可以看出一个点击动作包含一个Down,一个Up,还有多个Move操作。

再来看一段源码:

public boolean dispatchTouchEvent(MotionEvent ev){

boolean consume = false;

if(onInterceptTouchEvent(ev)){

consume = onTouchEvent(ev);

} else{

consume = child.dispatchTouchEvent(ev);

}

return consume;

}

上述的代码把三者的关系说得很清楚了,对于一个对于一个 ViewGroup 来说,点击事件产生后,首先会传递给它,这时候会调用 dispatchTouchEvent,如果这个 ViewGroup 的 onInterceptTouchEvent 返回 true ,则表示它要拦截该事件,也就会交给它的 onTouchEvent 来进行处理。如果这个 ViewGroup 的 onInterceptTouchEvent 返回 false 则会传给子元素,子元素的 dispatchTouchEvent 就会被调用,如此反复循环。这与上面一张图打出的结果是一致的。

这里还有说明的是,如果代码设置了 OnTouchListener,那么就会先调用 onTouch 方法,然后在调用 onTouchEvent。OnClickListener 是优先级最低的,所以最后才会调用 onClick。

因此,从第二张结果图也可以看出,当存在 onTouch 之后,onTouchEvent 和 onClick 两个方法都不会在调用了。

相信到这里,大家对于View的事件分发机制有一定的了解了。

这里回到开头提的那个问题,那么有什么办法可以扩大 View 的点击区域呢?

答案:在父 View 设置 OnTouchListener 对点击事件进行拦截,通过判断点击的位置,来决定是相应子 View 的事件,还是父 View 的事件。

具体实现代码如下:

public class TouchFactory {

/** 扩展垂直方向点击区域尺寸 */

private static final int EXT_V_SIZE = 200;

public static View.OnTouchListener creatTouchListener(){

return new View.OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

if (expendTouchSize(v, event)) {

return true;

}

return false;

}

};

}

public static boolean expendTouchSize(View root, MotionEvent event) {

if (root instanceof MyFrameLayout) {

ImageView view = ((MyFrameLayout) root).getMyImageView();

if (view != null && view.getVisibility() == View.VISIBLE) {

Rect touchRect = new Rect();

view.getGlobalVisibleRect(touchRect);

int action = event.getAction();

float x = event.getRawX();

float y = event.getRawY();

if ((y >= touchRect.top - EXT_V_SIZE) && (y <= touchRect.bottom + EXT_V_SIZE)) {

if (x >= touchRect.left) {

if (action == MotionEvent.ACTION_UP) {

Toast.makeText(view.getContext(), "touch", Toast.LENGTH_SHORT).show();

}

return true;

}

}

}

}

return false;

}

}

TouchFactory 对点击事件进行了封装,并通过对点击区域的判断,来决定要不要拦截点击事件。

下面是  MyFrameLayout 的具体实现。由于是一个自定义 view, 因此,变量 myImageView 是一定为空的,所以要对其进行赋值。

public class MyFrameLayout extends FrameLayout {

private static final String TAG = "Event";

private MyImageView myImageView;

public MyFrameLayout(Context context) {

this(context, null);

}

public MyFrameLayout(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public MyFrameLayout(Context context, AttributeSet attrs, int def) {

super(context, attrs, def);

init();

}

public void init() {

this.setOnTouchListener(TouchFactory.creatTouchListener());

}

public MyImageView getMyImageView() {

if (myImageView == null) {

myImageView = findViewById(R.id.mImage);

}

return myImageView;

}

}

注意事项: 当对子 View 设置 OnClickListener,点击区域刚好是子 View 内部的时候,就会消耗此事见,父 View 的拦截处理就无效了,因此,一旦选择拦截来扩大点击区域,就不要再去子 View 设置点击回调来消耗点击事件了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

opencv 扩大区域_Android 扩大 View 的点击区域的方法相关推荐

  1. html点击区域,求助HTML+CSS可以点击区域外关闭实现。

    [CSS] 纯文本查看 复制代码.caidan { position:fixed; bottom:80px; width:100%; } .nav { overflow:hidden; positio ...

  2. Android扩大控件的点击区域

    在做Android应用开发时,会碰到imageView尺寸小,用户难点击的情况,所以在不改变imageView大小情况,对其点击区域进行扩大.这里有两种方法可实现. 方法一:在imageView的xm ...

  3. android 图片圆角 遮罩_Android 自定义View练手Demo(一)实现圆角遮罩效果

    Android 自定义View系列文章 Android自定义View实现圆角遮罩效果 一图胜千言,有一个遮罩就会凸显出重点区域 1-1.jpg 本文通过两种方式来实现这种效果,来达到自定义View练手 ...

  4. opencv 从原始的图像中找出ROI区域

    http://blog.csdn.net/chentravelling/article/details/45331225 opencv 从原始的图像中找出ROI区域 #include <iost ...

  5. 判断自定义异形view的点击事件是否在绘制区域内

    本文是摘抄自 这篇文章,此处作为记录,以备后期查阅使用.在此感谢原文作者的贡献. 使用recyclerview显示如下所示的列表,其中item是一个自定义六边形view,点击事件会有重叠情况,所以需要 ...

  6. 使用android.view.TouchDelegate扩大View的触摸点击区域

    Android4.0设计规定的有效可触摸的UI元素标准是48dp,转化为一个物理尺寸约为9毫米.7~10毫米,这是一个用户手指能准确并且舒适触摸的区域. 如下图所示,你的UI元素可能小于48dp,图标 ...

  7. OPENCV C++图像提取,图像处理,roi,阈值分割,连通区域筛选,边缘检测(以箱子边缘框选为例)

    本周有机会接触了一点opnev, 在此做一下记录, 最终以框选出下图箱子为目的(图片箱子为相机实拍结果,曝光有点低,会有亿点点暗 ), 本文会拆解步骤并附上图片, 完整的源码在最后.PS:本文参考了好 ...

  8. OpenCV学习笔记(二十一)——绘图函数core OpenCV学习笔记(二十二)——粒子滤波跟踪方法 OpenCV学习笔记(二十三)——OpenCV的GUI之凤凰涅槃Qt OpenCV学习笔记(二十

    OpenCV学习笔记(二十一)--绘图函数core 在图像中,我们经常想要在图像中做一些标识记号,这就需要绘图函数.OpenCV虽然没有太优秀的GUI,但在绘图方面还是做得很完整的.这里就介绍一下相关 ...

  9. 【自己给自己题目做】之一:椭圆可点击区域

    [题一] 请实现以下需求,要做一个活动页面,页面上有一张图片(假设是800x600),图片正中心有一个椭圆形的可点击区域,假设椭圆长轴为200px(横向),短轴160px(纵向),请实现点击这个椭圆区 ...

最新文章

  1. Base64编码和解码
  2. 双目标帕累托优化_结构力学中的优化分析(3) —— 结构优化分析
  3. opencv-contrib配置过程
  4. 【React.js 06】Redux基础知识
  5. 简释iptables防火墙
  6. 【数道云大数据】大数据平台哪一个好用?武汉2019年大数据平台排行版?...
  7. c++string替换指定位置字符_Lua 字符串
  8. 复盘所有NLP比赛的TOP方案,专注NLP
  9. servlet中文数据存入数据库为乱码的解决办法
  10. g2o图优化简介与基本使用方法
  11. 开源Docker管理工具kubernetes的简易安装和使用
  12. libjvm ThreadState Transition transition_from_native
  13. bzoj3550: [ONTAK2010]Vacation(单纯形法+线性规划)
  14. iOS 播放视频的基本步骤
  15. 全球与中国服装测试、检验及认证市场深度研究分析报告
  16. 计算机的好处和坏处的英语作文,电脑利与弊英语作文
  17. GLTF格式学习:glTF介绍( 基于WebGL
  18. 一套Python入门视频
  19. 啥是单点登陆?淘宝和天猫是如何实现同时登陆的?
  20. 多项目同时进行如何做好进度管理

热门文章

  1. 力扣 792. 匹配子序列的单词数
  2. 大数据专栏一-全自动化在线式当当销售情况分析预测系统
  3. 利用python SMTP 发送电子邮件
  4. #include 中 和 的区别
  5. 中柏平板u盘启动_中柏平板电脑重装系统教程盘点
  6. TRENDnet固件获取文件系统
  7. 移动大数据助力南京智慧旅游升级
  8. 【精彩回顾】迪拜BSV全球区块链大会Day1
  9. Spring Boot实现各种参数校验,值得一看
  10. python中if verbose是啥意思呀讲解