【5年Android从零复盘系列之十七】Android自定义View(12):手势绘制及GestureOverlayView事件详解(图文)
【5年Android从零复盘系列之十七】Android自定义View(12):手势绘制及GestureOverlayView事件浅析
1.基础
- 掌握View体系事件分发与处理,参考Android自定义View(9):事件分发&处理
- 掌握基础的手势监听及手势动作有关的回调时机,参考Android自定义View(10):手势监听&处理
- 了解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 结论
- GestureOverlayView继承FrameLayout,FrameLayout继承ViewGroup(继承View);
- GestureOverlayView重写View的dispatchTouchEvent方法
- GestureOverlayView.setEnabled()默认设置为true,即夺取事件分发;
- 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事件详解(图文)相关推荐
- 【5年Android从零复盘系列之六】Android自定义View(1):基础详解(图文)
1.基础一:坐标计算 1.1 Android窗口坐标系计算以屏幕左上角为原点, 向右为X轴正向,向下为Y轴正向 1.2 View坐标系 [注意获取的坐标是像素值,不是dp值] [注意获取的坐标是像素值 ...
- 【5年Android从零复盘系列之二十】Android自定义View(15):Matrix详解(图文)【转载】
[转载]本文转载自麻花儿wt 的文章<android matrix 最全方法详解与进阶(完整篇)> [5年Android从零复盘系列之二十]Android自定义View(15):Matri ...
- 【Android从零单排系列十一】《Android视图控件——日历、日期、时间选择控件》
目录 一.日历.日期.时间组件基本介绍 二.几种常见的控件类型 1.CalendarView –日历控件 2. DatePicker –日期选择控件 3.TimePicker –时间选择控件 4.Ch ...
- [Python从零到壹] 三十六.图像处理基础篇之图像算术与逻辑运算详解
欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...
- android 拖动 点击事件,Android事件详解——拖放事件DragEvent
1.Android拖放框架的作用? 利用Android的拖放框架,可以让用户用拖放手势把一个View中的数据移到当前layout内的另一个View中去. 2.拖放框架的内容? 1)拖放事件类 2)拖放 ...
- android仿知乎按钮动效,Android仿知乎客户端关注和取消关注的按钮点击特效实现思路详解...
先说明一下,项目代码已上传至github,不想看长篇大论的也可以先去下代码,对照代码,哪里不懂点哪里. 代码在这https://github.com/zgzczzw/ZHFollowButton 前几 ...
- Java多线程系列(九):CountDownLatch、Semaphore等4大并发工具类详解
之前谈过高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 ,以及高并发编程系列:ConcurrentHashMap的实现原理(JDK1.7和JDK1.8) 今天主要介绍concurre ...
- 精通Android自定义View(十四)绘制水平向右加载的进度条
1引言 1 精通Android自定义View(一)View的绘制流程简述 2 精通Android自定义View(二)View绘制三部曲 3 精通Android自定义View(三)View绘制三部曲综合 ...
- 精通Android自定义View(十二)绘制圆形进度条
1 绘图基础简析 1 精通Android自定义View(一)View的绘制流程简述 2 精通Android自定义View(二)View绘制三部曲 3 精通Android自定义View(三)View绘制 ...
最新文章
- [Deep-Learning-with-Python]神经网络入手学习[上]
- Jerry本地安装SAP Kyma的一些失败尝试
- Android eclipse导入项目后出现Unable to resolve target #39;android-17#39;解决方法
- css自动换行加前置_StudyNode -- CSS
- zookeeper3.4.5集群安装
- java怎么建立socket_Java Socket编程如何建立两者关系
- 中文分词:采用二元词图以及viterbi算法(三)
- 数独超难题目_世界最难数独游戏 世界上最难数独题目
- 微信小程序 之修改switch组件尺寸大小
- 序列试题---最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离 .
- typescript 高阶类型 Exclude 和 Extract
- 遗传算法(Genetic Algorithm)详解与实现
- What?Poly又双叒叕发新品了?
- Old fishman-老赵钓鱼
- Javascript实现博客全文搜索功能
- 路由器上USB插口的4大功能,估计你连一个都没用过!
- redis五种数据类型对应的底层数据结构
- android解析xml-豆瓣电影API的xml解析实例
- JavaScript判断设备类型的实现
- 微信小程序|基于小程序+云开发制作一个菜谱小程序
热门文章
- 抽象数据类型三元组Triplet基本操作与实现 严蔚敏版
- 计算机开机密码有几成,电脑密码设置有哪些类型 电脑开机密码忘了怎么解锁...
- 以太网详解(四)-网口硬件测试指南
- 机器学习 | 特征重要性判断
- IDEA环境下SpringBoot项目,@Resource或@Autowired报错could not autowire
- Tensorflow 模型文件结构、模型中Tensor查看
- 阿里云域名使用cloudflare的DNS解析隐藏真实IP
- 试题 算法训练 预测身高
- python中的matplotlib绘图
- WPS 广告关闭 如何取消WPS的广告? 关闭弹窗-热点-广告推送