草庐IT

Android ImageView 捏缩放

coder 2023-05-08 原文

我正在使用 Making Sense of Multitouch 中的代码示例 用于缩放 ImageView 。在 ScaleListener 上,我添加了 ScaleGestureDetector.getFocusX() 和 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;
    }
}

这里是我如何在我的 Activity 中使用它。

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);

最佳答案

你可以使用这个类:TouchImageView

关于Android ImageView 捏缩放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10630373/

有关Android ImageView 捏缩放的更多相关文章

  1. ruby-on-rails - 谷歌地图、Ruby on Rails、用一个标记缩放级别 - 2

    我正在使用apneadiving/Google-Maps-for-Rails添加googlemaps支持(感谢awesomegem)但是,我发现了一个小故障,这很可能是我的错。当有多个标记时,auto_zoom效果很好。但是,当只有一个标记时,它会放大到不漂亮的最大级别。“缩放”仅在auto_zoom为false时有效,所以这不是我想要的。因此您可以使用“maxZoom”,但现在用户无法手动放大超出该点,这不是我想要的。有解决办法吗?我的解释有道理吗?这是GoogleMapsAPI的限制吗?谢谢... 最佳答案 此行为是由于goog

  2. 图形学-变换(平移矩阵,旋转矩阵,缩放矩阵,线性变换,仿射变换,齐次坐标) - 2

    1.变换1.1什么是变换?变换(Transform)是计算机图形学中非常重要的一部分。变换包含模型变换(Modelingtransform)以及视图变换(Viewtransform)。模型变换指的是变换模型(被拍摄物体)的位置,大小和角度;视图变换指的是变换照相机的位置和角度。从相对运动的角度来看,两种变换是可以相互转化的。1.2模型变换1.2.1二维变换缩放变换缩放变换(Scale)中,如果一个图片以原点(0,0)为中心缩放𝑠倍。那么点(𝑥,𝑦)变换后数学形式可以表示为写成矩阵形式为:当然,我们也可以给x轴和y轴不同的缩放倍数𝑠𝑥和𝑠𝑦。在非均匀情况下,缩放变换的矩阵形式为反射变换反射变换(

  3. javascript - SVG feOffset 过滤器放大/缩放 - 2

    为了在svg多边形或圆上有两个笔划和模糊,我创建了一个滤镜来执行此操作,尽管第二个“笔划”(使用滤镜创建)被剪裁或不像一个完美的圆。知道如何以正确的方式解决这个问题吗? 最佳答案 feMorphology在执行扩张时使用方形搜索框,因此它将创建这些裁剪效果。另一种扩大形状并保留原始形状的方法是进行高斯模糊,然后使用feComposite/feFuncA/table将模糊区域转换为完全不透明的形状。像这样: 关于javascript-SVGfeOffset过滤器放大/缩放,我们在Stack

  4. javascript - v4 中的 d3 缩放功能问题 - 2

    我在使用v4时遇到D3中的缩放功能问题。它抛出一个错误,指出zoom.translate未定义。我主要使用此答案中的以下代码d3focusonnodeonclick,这对v3非常有效。但是,由于我在使用v3时遇到问题,因为它对源和节点采用字符串形式(而不是索引)的数据有限制D3JSONfilewithsourceandindexasstringsratherthanindices,我切换到v4..linksline{stroke:#999;stroke-opacity:0.6;}.nodescircle{stroke:#fff;stroke-width:1.5px;}varsvg=d3

  5. javascript - 在缩放/拖动时缩放/重绘 d3.js 网格线 - 2

    我昨天才开始使用d3.js,但在完成我的工作时遇到了一些麻烦。现在我创建了一个带有两个y轴的图表,每个显示一些值,x轴显示日期。点击y轴上的值,我会显示相应的水平网格线。我的问题是,在放大或缩小或拖动时,网格线(水平和垂直)无法根据轴值正确缩放,它们根本就不动。我今天下午进行了很多搜索,找到了一些如何执行此操作的示例,但它们似乎都不适用于我已有的代码。我想,应该将逻辑添加到缩放行为中,但我不确定//xaxisgridlinesfunctionmake_x_gridlines(){returnd3.axisBottom(x).ticks(5)}//addtheXgridlinesletx

  6. javascript - 通过单击缩放按钮放大和缩小图像 (Javascript) - 2

    我正在尝试通过两个缩放按钮(+)和(-)放大和缩小图像。问题是当图像为全屏尺寸(宽度100%)时“放大”停止。我需要将图像放大到比屏幕尺寸大得多。只是不知道该怎么做。我是Javascript的初学者,所以我希望有人有动力帮助我解决这个Javascript小问题。我想知道是否有任何简单的放大/缩小/重置插件可以与缩放按钮一起使用?图像抓取也很酷。再次感谢!functionzoomin(){varmyImg=document.getElementById("map");varcurrWidth=myImg.clientWidth;if(currWidth==2500)returnfalse

  7. javascript - 如何在不改变位置的情况下缩放网格? - 2

    我在这个场景中有27个网格,每个网格都有一个关联的编号。数字最高的将具有标度1。其余的将依次具有小于1的值。接下来我希望它相应地爬上每个循环。当每个网格的位置发生变化时,就会出现我的问题。确实它被缩放到应有的大小,但它改变了位置。几个屏幕堆叠在一起,我很吃力。我只需要你爬上去,并保持在这个例子中的相同位置:美国各州已按比例缩放,但仍保持其位置。我认为它们会缩放到图的中心。我创建了网格(每个都称为“municipios”)for(vars=0;s 最佳答案 因为网格位置不在它的中心,或者任何你想要的引用:如果你创建一个平均顶点x分量超

  8. javascript - 如何添加点击并拖动以缩放 SVG 中的图像? - 2

    我想让访问者使用点击和拖动来缩放图像:是否有可以帮助我的JavaScript库?我注意到Raphaelhasclickanddrag方法,但我仍然需要编写大量JS来:找到图像的Angular使Angular落附近的区域可选为Angular绘制图标,使其明显可见在Angular落添加点击、拖放更新图片的尺寸我可以做到所有这些,但听起来很费时。有没有我应该使用的开源脚本?其他建议? 最佳答案 我在这篇文章中找到了这个解决方案:DraggablesandResizablesinSVG.在答案中,您可以找到一个jsfiddle链接:http

  9. javascript - 在 Google Maps API V3 中缩放至 map 中心 - 2

    我是使用谷歌地图的新手,正在尝试找出如何限制缩放功能,使其不会缩放到map中心以外的任何地方,也不会缩放到鼠标点。基本上,无论您的鼠标指针在map上的哪个位置,它都会缩放到返回map的中心,而不是缩放鼠标指针在map上的位置。我什至不知道目前是否可行,希望能提供一些帮助。functioninitialize(){varlatlng=newgoogle.maps.LatLng(51.285583,1.091045);varmyOptions={zoom:15,center:latlng,scrollwheel:true,navigationControl:false,mapTypeCon

  10. javascript - cytoscape.js 缩放以适合当前选定的节点 - 2

    我希望缩放cyjsView以适合(很好地包含)当前选定的节点。可以手动或以编程方式选择节点。如果只选择了一个小的网络邻居,那么放大效果会非常显着。如果远处的节点在选择中,则放大甚至可能不会引人注意。cy.fit()非常适合在窗口中显示整个网络。但是尽我所能,我找不到cy.fitSelected()或一些等效的功能。有什么建议吗? 最佳答案 这是一个单行代码,因为cy.fit()将eles作为它的第一个参数:例如cy.fit(cy.$(':selected'),50)填充50http://cytoscape.github.io/cyt

随机推荐