【5年Android从零复盘系列之十七】Android自定义View(12):手势绘制及GestureOverlayView事件浅析


1.基础

  1. 掌握View体系事件分发与处理,参考Android自定义View(9):事件分发&处理
  2. 掌握基础的手势监听及手势动作有关的回调时机,参考Android自定义View(10):手势监听&处理
  3. 了解GestureLibrary和GestureOverlayView的api使用,参考官方API文档

2.绘制

绘制简述:

(具体用法及要点见代码注释)

1.首先在布局文件中添加GestureOverlayView控件;
2.然后在代码中获取控件对象;
3.初始化绘制画笔;
4.设置监听;
5.若关联activity,则在onDestroy()解除。

2.1 xml代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><android.gesture.GestureOverlayViewandroid:id="@+id/gesture_overlay"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:orientation="vertical"android:gravity="center"android:layout_height="match_parent"><TextViewandroid:id="@+id/text"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout></android.gesture.GestureOverlayView>
</RelativeLayout>

2.2 activity代码

package com.cupster.android_x_frame;import android.gesture.Gesture;
import android.gesture.GestureOverlayView;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;public class DrawGestureActivity extends AppCompatActivity implements GestureOverlayView.OnGesturePerformedListener, GestureOverlayView.OnGesturingListener {GestureOverlayView mGestureOverlayView;TextView mTvHint;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_draw_gesture);mGestureOverlayView = findViewById(R.id.gesture_overlay);mTvHint = findViewById(R.id.text);mGestureOverlayView.setFadeOffset(800);//默认420ms,设置为800msmGestureOverlayView.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);//默认单指连续绘制,设置为多指绘制mGestureOverlayView.setGestureStrokeWidth(10);//绘制线宽mGestureOverlayView.setGestureColor(Color.parseColor("#3ca1f9"));//绘制颜色mGestureOverlayView.setUncertainGestureColor(Color.parseColor("#a7dbf7"));//渐成色//设置监听mGestureOverlayView.addOnGesturePerformedListener(this);mGestureOverlayView.addOnGesturingListener(this);}@Overrideprotected void onDestroy() {mGestureOverlayView.removeOnGesturePerformedListener(this);mGestureOverlayView.removeOnGesturingListener(this);super.onDestroy();}//==============================================//=========GesturePerformedListener=============//==============================================@Overridepublic void onGesturePerformed(GestureOverlayView gestureOverlayView, Gesture gesture) {mTvHint.append("\n");mTvHint.append("--> 所有绘制路径,识别完成");}//===============================================//=========GesturingListener=====================//===============================================@Overridepublic void onGesturingStarted(GestureOverlayView gestureOverlayView) {mTvHint.append("\n");mTvHint.append("--> 单笔手势绘制开始");}@Overridepublic void onGesturingEnded(GestureOverlayView gestureOverlayView) {mTvHint.append("\n");mTvHint.append("--> 单笔手势绘制结束");}
}

2.3 源码简析

2.3.1 结论

  1. GestureOverlayView继承FrameLayout,FrameLayout继承ViewGroup(继承View);
  2. GestureOverlayView重写View的dispatchTouchEvent方法
  3. GestureOverlayView.setEnabled()默认设置为true,即夺取事件分发;
  4. GestureOverlayView.setEnabled(false)时,可视为FrameLayout,即不响应手势绘制;

验证代码:

//测试禁用,mGestureOverlayView默认启用绘制==读取手势事件mGestureOverlayView.setEnabled(false);mTvHint.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {mTvHint.append("\n");mTvHint.append("绘制未启用,事件正常分发");return true;}});

2.3.2 源码

解析 见代码注释

public class GestureOverlayView extends FrameLayout {...@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {if (isEnabled()) {final boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null &&mCurrentGesture.getStrokesCount() > 0 && mPreviousWasGesturing)) &&mInterceptEvents;processEvent(event);//即夺取事件分发if (cancelDispatch) {event.setAction(MotionEvent.ACTION_CANCEL);}super.dispatchTouchEvent(event);return true;//回复上级已处理事件,不下发}//isEnabled== false ,可视为FrameLayout,正常分发事件return super.dispatchTouchEvent(event);}
...
}
...private boolean processEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:touchDown(event);//这里回调onGestureStartedinvalidate();return true;case MotionEvent.ACTION_MOVE:if (mIsListeningForGestures) {Rect rect = touchMove(event);//这里回调onGestureif (rect != null) {invalidate(rect);}return true;}break;case MotionEvent.ACTION_UP:if (mIsListeningForGestures) {touchUp(event, false);//回调onGestureEndedinvalidate();return true;}break;case MotionEvent.ACTION_CANCEL:if (mIsListeningForGestures) {touchUp(event, true);//标志位true,代表取消,清除绘制的手势invalidate();return true;}}return false;}
...
...
/**
* 每次执行完touchDown、touchMove方法后都会调用invalidate()、invalidate(rect)刷新手势
*/
@Overridepublic void draw(Canvas canvas) {super.draw(canvas);if (mCurrentGesture != null && mGestureVisible) {canvas.drawPath(mPath, mGesturePaint);}}
...

【5年Android从零复盘系列之十七】Android自定义View(12):手势绘制及GestureOverlayView事件详解(图文)相关推荐

  1. 【5年Android从零复盘系列之六】Android自定义View(1):基础详解(图文)

    1.基础一:坐标计算 1.1 Android窗口坐标系计算以屏幕左上角为原点, 向右为X轴正向,向下为Y轴正向 1.2 View坐标系 [注意获取的坐标是像素值,不是dp值] [注意获取的坐标是像素值 ...

  2. 【5年Android从零复盘系列之二十】Android自定义View(15):Matrix详解(图文)【转载】

    [转载]本文转载自麻花儿wt 的文章<android matrix 最全方法详解与进阶(完整篇)> [5年Android从零复盘系列之二十]Android自定义View(15):Matri ...

  3. 【Android从零单排系列十一】《Android视图控件——日历、日期、时间选择控件》

    目录 一.日历.日期.时间组件基本介绍 二.几种常见的控件类型 1.CalendarView –日历控件 2. DatePicker –日期选择控件 3.TimePicker –时间选择控件 4.Ch ...

  4. [Python从零到壹] 三十六.图像处理基础篇之图像算术与逻辑运算详解

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  5. android 拖动 点击事件,Android事件详解——拖放事件DragEvent

    1.Android拖放框架的作用? 利用Android的拖放框架,可以让用户用拖放手势把一个View中的数据移到当前layout内的另一个View中去. 2.拖放框架的内容? 1)拖放事件类 2)拖放 ...

  6. android仿知乎按钮动效,Android仿知乎客户端关注和取消关注的按钮点击特效实现思路详解...

    先说明一下,项目代码已上传至github,不想看长篇大论的也可以先去下代码,对照代码,哪里不懂点哪里. 代码在这https://github.com/zgzczzw/ZHFollowButton 前几 ...

  7. Java多线程系列(九):CountDownLatch、Semaphore等4大并发工具类详解

    之前谈过高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 ,以及高并发编程系列:ConcurrentHashMap的实现原理(JDK1.7和JDK1.8) 今天主要介绍concurre ...

  8. 精通Android自定义View(十四)绘制水平向右加载的进度条

    1引言 1 精通Android自定义View(一)View的绘制流程简述 2 精通Android自定义View(二)View绘制三部曲 3 精通Android自定义View(三)View绘制三部曲综合 ...

  9. 精通Android自定义View(十二)绘制圆形进度条

    1 绘图基础简析 1 精通Android自定义View(一)View的绘制流程简述 2 精通Android自定义View(二)View绘制三部曲 3 精通Android自定义View(三)View绘制 ...

最新文章

  1. [Deep-Learning-with-Python]神经网络入手学习[上]
  2. Jerry本地安装SAP Kyma的一些失败尝试
  3. Android eclipse导入项目后出现Unable to resolve target #39;android-17#39;解决方法
  4. css自动换行加前置_StudyNode -- CSS
  5. zookeeper3.4.5集群安装
  6. java怎么建立socket_Java Socket编程如何建立两者关系
  7. 中文分词:采用二元词图以及viterbi算法(三)
  8. 数独超难题目_世界最难数独游戏 世界上最难数独题目
  9. 微信小程序 之修改switch组件尺寸大小
  10. 序列试题---最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离 .
  11. typescript 高阶类型 Exclude 和 Extract
  12. 遗传算法(Genetic Algorithm)详解与实现
  13. What?Poly又双叒叕发新品了?
  14. Old fishman-老赵钓鱼
  15. Javascript实现博客全文搜索功能
  16. 路由器上USB插口的4大功能,估计你连一个都没用过!
  17. redis五种数据类型对应的底层数据结构
  18. android解析xml-豆瓣电影API的xml解析实例
  19. JavaScript判断设备类型的实现
  20. 微信小程序|基于小程序+云开发制作一个菜谱小程序

热门文章

  1. 抽象数据类型三元组Triplet基本操作与实现 严蔚敏版
  2. 计算机开机密码有几成,电脑密码设置有哪些类型 电脑开机密码忘了怎么解锁...
  3. 以太网详解(四)-网口硬件测试指南
  4. 机器学习 | 特征重要性判断
  5. IDEA环境下SpringBoot项目,@Resource或@Autowired报错could not autowire
  6. Tensorflow 模型文件结构、模型中Tensor查看
  7. 阿里云域名使用cloudflare的DNS解析隐藏真实IP
  8. 试题 算法训练 预测身高
  9. python中的matplotlib绘图
  10. WPS 广告关闭 如何取消WPS的广告? 关闭弹窗-热点-广告推送