Android 扩大 View 的点击区域,ffmpeg音视频开发实战百度云

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);

setOnTou

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

chListener(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,会有怎样的输出呢?结果如下图。

image

那如果点击外层呢?

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 {

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值