此问题在此处已有答案:
Android ImageView Zoom-in and Zoom-Out(23个答案)
8个月前关闭。
我正在使用Making Sense of Multitouch中的代码示例来缩放图像视图。在ScaleListener上,我添加了ScaleGestureDetector.getFocusX() and getFocusY()
来缩放手势焦点的内容。它工作正常。
问题是,在第一次多点触控时,整个图像绘制位置会更改为当前触摸点,并从那里进行缩放。您能帮助我解决此问题吗?
以下是TouchImageView的我的代码示例。
public class TouchImageViewSample extends ImageView {
private Paint borderPaint = null;
private Paint backgroundPaint = null;
private float mPosX = 0f;
private float mPosY = 0f;
private float mLastTouchX;
private float mLastTouchY;
private static final int INVALID_POINTER_ID = -1;
private static final String LOG_TAG = "TouchImageView";
// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;
public TouchImageViewSample(Context context) {
this(context, null, 0);
}
public TouchImageViewSample(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
// Existing code ...
public TouchImageViewSample(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Create our ScaleGestureDetector
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
borderPaint = new Paint();
borderPaint.setARGB(255, 255, 128, 0);
borderPaint.setStyle(Paint.Style.STROKE);
borderPaint.setStrokeWidth(4);
backgroundPaint = new Paint();
backgroundPaint.setARGB(32, 255, 255, 255);
backgroundPaint.setStyle(Paint.Style.FILL);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
/*
* (non-Javadoc)
*
* @see android.view.View#draw(android.graphics.Canvas)
*/
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawRect(0, 0, getWidth() - 1, getHeight() - 1, borderPaint);
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, getWidth() - 1, getHeight() - 1, backgroundPaint);
if (this.getDrawable() != null) {
canvas.save();
canvas.translate(mPosX, mPosY);
Matrix matrix = new Matrix();
matrix.postScale(mScaleFactor, mScaleFactor, pivotPointX,
pivotPointY);
// canvas.setMatrix(matrix);
canvas.drawBitmap(
((BitmapDrawable) this.getDrawable()).getBitmap(), matrix,
null);
// this.getDrawable().draw(canvas);
canvas.restore();
}
}
/*
* (non-Javadoc)
*
* @see
* android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable
* )
*/
@Override
public void setImageDrawable(Drawable drawable) {
// Constrain to given size but keep aspect ratio
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
mLastTouchX = mPosX = 0;
mLastTouchY = mPosY = 0;
int borderWidth = (int) borderPaint.getStrokeWidth();
mScaleFactor = Math.min(((float) getLayoutParams().width - borderWidth)
/ width, ((float) getLayoutParams().height - borderWidth)
/ height);
pivotPointX = (((float) getLayoutParams().width - borderWidth) - (int) (width * mScaleFactor)) / 2;
pivotPointY = (((float) getLayoutParams().height - borderWidth) - (int) (height * mScaleFactor)) / 2;
super.setImageDrawable(drawable);
}
float pivotPointX = 0f;
float pivotPointY = 0f;
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
pivotPointX = detector.getFocusX();
pivotPointY = detector.getFocusY();
Log.d(LOG_TAG, "mScaleFactor " + mScaleFactor);
Log.d(LOG_TAG, "pivotPointY " + pivotPointY + ", pivotPointX= "
+ pivotPointX);
mScaleFactor = Math.max(0.05f, mScaleFactor);
invalidate();
return true;
}
}
这是我如何在我的活动中使用它的。
ImageView imageView = (ImageView) findViewById(R.id.imgView);
int hMargin = (int) (displayMetrics.widthPixels * .10);
int vMargin = (int) (displayMetrics.heightPixels * .10);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(displayMetrics.widthPixels - (hMargin * 2), (int)(displayMetrics.heightPixels - btnCamera.getHeight()) - (vMargin * 2));
params.leftMargin = hMargin;
params.topMargin = vMargin;
imageView.setLayoutParams(params);
imageView.setImageDrawable(drawable);
7条答案
按热度按时间q1qsirdb1#
您可以使用这个类别:TouchImageView
5sxhfpxr2#
使用ScaleGestureDetector
当学习一个新概念时,我不喜欢使用库或代码转储。我在here和文档中找到了一个很好的描述,关于如何通过捏取来调整图像大小。这个答案是一个稍微修改过的总结。你可能会想在以后添加更多的功能,但它会帮助你开始。
布局
ImageView
只使用应用程序徽标,因为它已经可用。不过,你可以用任何你喜欢的图像替换它。活动
我们在activity上使用
ScaleGestureDetector
来监听触摸事件。当检测到缩放(即捏合)手势时,则使用缩放因子来调整ImageView
的大小。备注
继续
您可能还想做一些其他的事情,比如平移和缩放到某个焦点。您可以自己开发这些东西,但是如果您想使用一个预先制作的自定义视图,将
TouchImageView.java
复制到你的项目中,像普通的ImageView
一样使用它。它对我来说运行得很好,我只遇到了一个bug。我计划进一步编辑代码,删除警告和不需要的部分。您也可以这样做。u4dcyp6a3#
我做了我自己的自定义图像视图与捏缩放。没有限制/边界上Chirag Raval的代码,所以用户可以拖动图像离开屏幕。这将修复它。
下面是CustomImageView类:
以下是您在活动中使用它的方式:
和布局:
uujelgoq4#
在build.gradle中添加以下行:
或
在Java文件中:
cu6pst1q5#
在
TouchImageViewSample
类中,缩放发生在枢轴点周围。属于枢轴点的像素不会受到图像缩放的影响。当您更改枢轴点时,视图会被重新绘制,缩放会围绕新的旋转点发生。2这会改变先前旋转点的位置,你可以看到每次你点击图像时图像都会发生移动。您必须通过平移图像来补偿这个移位误差。请看我的ZoomGestureDetector.updatePivotPoint()
方法是如何做到的。缩放手势检测器
我创建了一个自定义的缩放手势检测器类。它可以同时进行缩放、平移和旋转。它还支持fling动画。
第一次
我在
FrameLayout
中使用了ZoomGestureDetector
,如下所示。更新:
我已经在github.com/UdaraWanasinghe/android-transform-layout上发布了一个库,它使用了一种基于变换矩阵连接属性的不同算法。
ef1yzkbh6#
Kotlin中的自定义缩放视图
pprl5pva7#
我做了代码imageview与捏缩放使用zoomageview。所以用户可以拖动图像离开屏幕和放大,缩小图像。
您可以遵循此
link
以获取Step By Step
代码和给定的输出屏幕截图。https://stackoverflow.com/a/58074642/11613683