时间:2021-05-20
接着上一节 Android手势ImageView三部曲(二)的往下走,我们讲到了github上的GestureDetector框架,
先附上github链接:
https://github.com/Almeros/android-gesture-detectors
其实把这个框架的主体思想也是参考的Android自带的ScaleGestureDetector工具类,ScaleGestureDetector估计是参考的GestureDetector工具类,不管谁参考谁的,既然被我们遇到了,我们就要变成自己的东西,真不能全变成自己的东西的话,至少
我们要了解下它的思想。
我们先了解一下android自带的ScaleGestureDetector(缩放手势监测器):
ScaleGestureDetector跟GestureDetector构造都差不多,但是ScaleGestureDetector只能用于监测缩放的手势,而GestureDetector监测的手势就比较多了,我们上一节内容中有提到。
ScaleGestureDetector的一些用法跟api,小伙伴自行去查看官网文档:
https://developer.android.google.cn/reference/android/view/ScaleGestureDetector.html
我们怎么使用它呢(我以第一节中最后一个demo为例)?
首先创建一个ScaleGestureDetector对象:
private void initView() { .... mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); .... }然后传递一个叫ScaleListener的回调接口给它,ScaleListener里面有三个回调方法:
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); // scale change since previous event // Don't let the object get too small or too large. mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); changeMatrix(); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return super.onScaleBegin(detector); } @Override public void onScaleEnd(ScaleGestureDetector detector) { super.onScaleEnd(detector); } }小伙伴应该看得懂哈,就是onScale放缩时回调,onScaleBegin缩放开始时回调,onScaleEnd缩放完毕后回调。
最后在view的onTouchEvent方法中把事件给ScaleGestureDetector对象:
@Override public boolean onTouchEvent(MotionEvent event) { //把缩放事件给mScaleDetector mScaleDetector.onTouchEvent(event); return true; }好啦~!!上一节最后的时候,我写了一个小demo去实现了图片的位移,下面我们继续加上图片的缩放:
public class MatrixImageView extends ImageView { private Matrix currMatrix; private GestureDetector detector; private ScaleGestureDetector scaleDetector; private float currX;//当前图片的x坐标值 private float currY;//当前图片的y坐标值 private float scaleFactor=1f;//当前图片的缩放值 public MatrixImageView(Context context, AttributeSet attrs) { super(context, attrs); initView(); detector=new GestureDetector(context,onGestureListener); //创建一个缩放手势监测器 scaleDetector=new ScaleGestureDetector(context,onScaleGestureListener); } private void initView() { currMatrix = new Matrix(); DisplayMetrics dm = getResources().getDisplayMetrics(); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.test); bitmap = Bitmap.createScaledBitmap(bitmap, dm.widthPixels, dm.heightPixels, true); setImageBitmap(bitmap); } @Override public boolean onTouchEvent(MotionEvent event) { detector.onTouchEvent(event); //把事件给scaleDetector scaleDetector.onTouchEvent(event); return true; } private void setMatrix(){ currMatrix.reset(); currMatrix.postTranslate(currX,currY); currMatrix.postScale(scaleFactor,scaleFactor,getMeasuredWidth()/2,getMeasuredHeight()/2); setImageMatrix(currMatrix); } private GestureDetector.SimpleOnGestureListener onGestureListener=new GestureDetector.SimpleOnGestureListener(){ @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { currX-=distanceX; currY-=distanceY; setMatrix(); return super.onScroll(e1, e2, distanceX, distanceY); } }; private ScaleGestureDetector.SimpleOnScaleGestureListener onScaleGestureListener=new ScaleGestureDetector.SimpleOnScaleGestureListener(){ @Override public boolean onScale(ScaleGestureDetector detector) { scaleFactor*=detector.getScaleFactor(); setMatrix(); /** * 因为getScaleFactor=当前两个手指之间的距离(preEvent)/手指按下时候两个点的距离(currEvent) * 这里如果返回true的话,会在move操作的时候去更新之前的event, * 如果为false的话,不会去更新之前按下时候保存的event */ return true; } };}尴尬了,模拟器不太好用于两个手指缩放的录制,所以效果小伙伴自己拿到代码运行一下哈~!!!
下面一起撸一撸ScaleGestureDetector的源码:
我们知道,ScaleGestureDetector核心代码也就是onTouchEvent,于是我们点开onTouchEvent:
一堆代码,数学不太好的看起来还真比较艰难,大概就是根据多个触碰点的x坐标算出一个x轴平均值,然后y轴也一样,然后通过Math.hypot(spanX, spanY);算出斜边长,斜边长即为两点之间的距离,然后保存当前的span跟移动过后的span。
最后当我们调用getScaleFactor获取缩放比例的时候,即用现在的span/之前的span:
public float getScaleFactor() { if (inAnchoredScaleMode()) { // Drag is moving up; the further away from the gesture // start, the smaller the span should be, the closer, // the larger the span, and therefore the larger the scale final boolean scaleUp = (mEventBeforeOrAboveStartingGestureEvent && (mCurrSpan < mPrevSpan)) || (!mEventBeforeOrAboveStartingGestureEvent && (mCurrSpan > mPrevSpan)); final float spanDiff = (Math.abs(1 - (mCurrSpan / mPrevSpan)) * SCALE_FACTOR); return mPrevSpan <= 0 ? 1 : scaleUp ? (1 + spanDiff) : (1 - spanDiff); } return mPrevSpan > 0 ? mCurrSpan / mPrevSpan : 1; }这数学渣真的是硬伤啊~~~
有了android自带的ScaleGestureDetector作为参考,我们能自己实现ScaleGestureDetector吗?? 当然github上大神已经实现了,但是如果没有的话,你能写出来么?
先写到这,未完待续。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
URL的格式URL的格式由下列三部分组成:1、第一部分是协议(或称为服务方式); 2、第二部分是存有该资源的主机IP地址(有时也包括端口号); 3、第三部分
把数据填写进去之后,分析的方法很简答,还是三部曲,了解现状,分析原因,预测未来。作者:淘宝小2哥,微信公众号:taobaoxiaoerge,有问题随时交流微信/
跟大家简单介绍添加收藏店铺的三部曲。第一,准备图片。第二是准备链接。第三是具体操作。第一:要准备好做收藏按钮的图片,可以自己设计或是购买也可以的。宽度限制在22
JS运行三部曲js运行代码共分三步语法分析预编译解释执行JavaScript代码在运行时,首先会进行语法分析,通篇检查代码是否存在低级错误,然后进行预编译,整理
这段时间非常火热的电影要数《侏罗纪世界》了,作为一部背景设置在《侏罗纪公园》故事发生22年后的大作,小编认为,在欣赏大片之前很有必要重温一下《侏罗纪公园》三部曲