多点触控手势识别
什么是多点触控控制器?
该术语不通用。 我们所说的“多点触摸控制器”是一段代码,它使在屏幕上显示的实体(视图,位图等)上实现操纵操作的过程变得很方便。 这意味着多点触摸控制器将逻辑包装在通过触摸屏的用户输入后面。 因此,当用户放下一根手指并开始在触摸屏上移动手指时,控制器应“指向”部分代码,开发人员应将自己的逻辑放在他想发生的事情上。 控制器“知道”是单指触摸,捏手势或旋转手势,还是一次(只要有可能)全部手势。 更准确地说,通过将库或代码链接到您的应用,多点触摸控制器不会使您的图形神奇地在屏幕上移动。 可以将其视为需要实现的接口,以便使对象移动,但是您需要弄清楚如何实现。
我们已经选择的已经提到的多点触控控制器是Android Multitouch Controller 。 准备时首先需要做的是创建一个空的Android项目并下载MultiTouchController.java文件。 这里是本教程所需要的90%。
生活必需品
到目前为止,通过使用批处理资源(可绘制对象)给出了Android Multitouch Controller的示例,可以稍后在Canvas上对其进行修改。 我们的想法是简化此过程,并在画布上仅制作一个可移动对象。 因此,我们将使用简单的位图,该位图将绘制在画布上,随后可以从其初始位置进行移动/缩放/旋转。 因此,我们首先需要两件事:一个实现MultiTouchObjectCanvas接口的View,然后一个将包含其绘制逻辑的自定义对象/实体/小部件。 该对象是“操纵性”对象,它包含代表它的位图。
因此,当我们说C 语言时,我们想到了需要创建的自定义视图,该视图将实现MultiTouchObjectCanvas接口(其中T是要修改的Pinch对象)。 该界面告诉我们在用户触摸屏幕时是否有对象(可拖动对象)或小部件。 如果是这样,则实现将返回相关对象,否则返回null。 因此,要使用此接口,我们需要实现几种方法,否则我们将无法获得结果。 无论如何,IDE会告诉您必须实现的内容,这些是方法(在父级View类的构造函数等中):
@Override
public T getDraggableObjectAtPoint(PointInfo touchPoint) {
return null;
}
如您所见,此方法从用户进行触摸输入的位置返回感兴趣的对象。 这意味着,如果用户触摸了x:120; y:100点,则此方法应检查该点是否在窗口小部件占用的区域中。 当您看到完整的实现时,您将知道它是如何完成的。
@Override
public void getPositionAndScale(T obj,
PositionAndScale objPosAndScaleOut) {
}
此方法对被触摸的小部件的PositionAndScale对象进行操作。 小部件作为第一个参数传递,而PositionAndScale作为第二个参数传递,这几乎是自描述性的:当触摸“ obj”对象时,将“ objPosAndScaleOut”属性应用于位置,比例和角度。 但这仅适用于屏幕的初始位置,实际上使运动成为第二种强制性方法。
@Override
public boolean setPositionAndScale(T obj,
PositionAndScale newObjPosAndScale, PointInfo touchPoint) {
return false;
}
同样,我们将小部件作为第一个参数,将新对象的位置/比例/角度属性以及PointInfo的帮助对象告知其是多点触摸还是单(拖动)手势。
@Override
public void selectObject(T obj, PointInfo touchPoint) {
}
此方法负责通知控制器正在选择哪个对象。 'obj'对象具有选定的对象。 因此,当我们实现此方法并设置多点触控控制器对象时,我们可以实现小部件逻辑,该逻辑将数据保存在画布上绘制的项目后面。 是的,在这种情况下,我们需要一个MultiTouchController对象,需要这样定义:
private MultiTouchController
mMultiTouchController = new MultiTouchController
(this);
那该怎么办? 好吧,当触摸事件发生时,我们需要将“一切”传递给该控制器。 这是通过覆盖自定义View / Canvas的onTouchEvent来完成的:
@Override
public boolean onTouchEvent(MotionEvent ev) {
return mMultiTouchController.onTouchEvent(ev);
}
有了这些人员和其他几个工作人员,我们有了基本的Canvas,可以处理它绘制的对象。 因此,我们还需要一件事,即Pinch小部件的逻辑及其位图,坐标等。因此,我们创建了一个PinchWidget对象,该对象是Multitouch Controller附带的一些示例的修改。 该对象的本质是以下两种方法:
public boolean setPos(PositionAndScale newImgPosAndScale, int uiMode, int uiModeAnisotropic, boolean isMultitouch) {
boolean ret = false;
float x = newImgPosAndScale.getXOff();
float y = newImgPosAndScale.getYOff();
if(isMultitouch) {
x = mCenterX;
y = mCenterY;
}
ret = setPos(x, y,
(uiMode & uiModeAnisotropic) != 0 ? newImgPosAndScale.getScaleX() : newImgPosAndScale.getScale(),
(uiMode & uiModeAnisotropic) != 0 ? newImgPosAndScale.getScaleY() : newImgPosAndScale.getScale(),
newImgPosAndScale.getAngle());
return ret;
}
和
private boolean setPos(float centerX, float centerY, float scaleX, float scaleY, float angle) {
float ws = (mImage.getWidth() / 2) * scaleX, hs = (mImage.getHeight() / 2) * scaleY;
float newMinX = centerX - ws, newMinY = centerY - hs, newMaxX = centerX + ws, newMaxY = centerY + hs;
mCenterX = centerX;
mCenterY = centerY;
mScaleFactor = scaleX;
mAngle = angle;
mMinX = newMinX;
mMinY = newMinY;
mMaxX = newMaxX;
mMaxY = newMaxY;
return true;
}
这两种方法使移动成为可能,因为它们提供了有关PinchWidget的坐标,比例因子和角度的信息。 它们以某种方式耦合在一起,这意味着第一种方法对其从第二种方法获得的数据进行计算。 现在我们有了对象的坐标,比例和角度。 我们只需要使用其draw(Canvas)方法来绘制它:
public void draw(Canvas canvas) {
Paint itemPaint = new Paint();
itemPaint.setAntiAlias(true);
itemPaint.setFilterBitmap(true);
float dx = (mMaxX + mMinX) / 2;
float dy = (mMaxY + mMinY) / 2;
canvas.save();
canvas.translate(dx, dy);
canvas.rotate(mAngle * 180.0f / (float) Math.PI);
canvas.translate(-dx, -dy);
Rect srcRect = new Rect(0, 0, mImage.getWidth(), mImage.getHeight());
Rect dstRect = new Rect((int) mMinX, (int) mMinY, (int) mMaxX, (int) mMaxY);
canvas.drawBitmap(mImage, srcRect, dstRect, null);
canvas.restore();
}
mImage是我们绘制的项目/小部件的位图。 必须画出看到的东西。 为了绘制它,我们需要它的源代码和目标代码(在这种实现中)。 源是图像的大小(在我们的示例中为Rect [0,0,300,300]),而目的地(将在何处绘制)是根据PinchWidget的init和setPos方法计算得出的。 然后,使用drawBitmap(…)方法以与绘制任何其他Bitmap相同的方式绘制图像。 现在回到MultiTouchView实现。 如前所述,请记住我们已经以XML声明了此View,我们将使用:
public MultiTouchView(Context context, AttributeSet attrs)
构造函数。 在那里,我们初始化上下文。 我们也有这种方法:
public void setPinchWidget(Bitmap bitmap) {
mPinchWidget = new PinchWidget(bitmap);
mPinchWidget.init(mContext.getResources());
}
该方法告诉MultiTouchView什么是我们的PinchWidget。 它是在此创建的,并通过调用init()(此处的资源仅用于计算显示器的宽度和高度),我们将调用绘制小部件的整个机制。 在此视图中,其onDraw()方法中发生了以下情况:
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
mPinchWidget.draw(canvas);
}
很简单,不是吗? 因此,如果一切按说明进行,并且您了解了这种实现的背后思想,那么您将在屏幕上看到类似以下内容的内容:
结论
Android中的MultiTouch操作与其他平台上的数学运算基本相同。 但是,当您需要时间进行此类项目时,Android Multitouch Contoroller是省时的工具,并且在下载该工具时,请务必阅读记录在案的方法,并查看优美而优美的代码,并且不要忘记感谢开发人员做了。
也许值得一提的是,我们的研究花了将近1年(准确地说是9个月)来确定我们现在和将来的应用中需要使用哪种Multitouch Controller。
示例应用程序的源可在我们的GitHub存储库中找到 。 接下来,我们将尝试介绍在Canvas视图上显示许多位图所需要做的事情。 或者,如果您自己解决问题,请不要犹豫编写教程,我们很乐意在此处发布。
祝您编程愉快,别忘了分享!
参考: Android:我们的JCG合作伙伴 Aleksandar Balalovski在2dwarfs博客上提供了多点触摸手势控制器 。
翻译自: https://www.javacodegeeks.com/2012/10/android-multi-touch-gestures-controller.html
多点触控手势识别