web-dev-qa-db-ja.com

Android-画像の一部を円形にズーム/拡大するにはどうすればよいですか?

ユーザーが画像に触れることができるようにしようとしていますが、基本的には円形の拡大鏡が表示され、ユーザーが画像上の特定の領域をより適切に選択できるようになります。ユーザーがタッチを離すと、拡大された部分が消えます。これはいくつかの写真編集アプリで使用されており、私はそれの独自のバージョンを実装しようとしています。以下のコードは、imageviewの円形部分を拡大しますが、指を離すとズームを削除またはクリアしません。現在、canvas = new Canvas(bitMap);を使用してビットマップをキャンバスに設定してから、takenPhoto.setImageBitmap(bitMap);を使用してimageviewを設定しています。正しい方法で実行しているかどうかはわかりません。 onTouchコードは以下のとおりです。

zoomPos = new PointF(0,0);
        takenPhoto.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                 int action = event.getAction(); 
                    switch (action) { 
                        case MotionEvent.ACTION_DOWN: 
                            zoomPos.x = event.getX();
                            zoomPos.y = event.getY();
                            matrix.reset();
                            matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
                            shader.setLocalMatrix(matrix);
                            canvas.drawCircle(zoomPos.x, zoomPos.y, 20, shaderPaint);
                            takenPhoto.invalidate();
                            break; 
                        case MotionEvent.ACTION_MOVE: 
                            zoomPos.x = event.getX();
                            zoomPos.y = event.getY();
                            matrix.reset();
                            matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
                            canvas.drawCircle(zoomPos.x, zoomPos.y, 20, shaderPaint);
                            takenPhoto.invalidate();
                            break; 
                        case MotionEvent.ACTION_UP:   
                            //clear zoom here?

                            break; 
                        case MotionEvent.ACTION_CANCEL: 
                            break; 
                        default: 
                            break; 
            }
                    return true; 
            } 
            });
22
IZI_Shadow_IZI

あなたのコードを適応させることで、私は次のアプローチを機能させることができました。

OnTouch関数で、ユーザーがタッチした場所を判別するためのグローバルポイントを設定し、ズームが現在アクティブであるかどうかを示すブール値を設定します。

@Override
public boolean onTouch(View view, MotionEvent event) {

    int action = event.getAction(); 

    zoomPos.x = event.getX();
    zoomPos.y = event.getY();

    switch (action) { 
    case MotionEvent.ACTION_DOWN:
    case MotionEvent.ACTION_MOVE:
        zooming = true;
        this.invalidate();
        break; 
    case MotionEvent.ACTION_UP:   
    case MotionEvent.ACTION_CANCEL:
        zooming = false;
        this.invalidate();
        break; 

    default: 
        break; 
    }

    return true; 
}

次に、onDrawメソッドで、コードを使用してズームイン部分を描画します。

@Override
protected void onDraw(Canvas canvas) {

    super.onDraw(canvas);

    if (zooming) {
        matrix.reset();
        matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
        mPaint.getShader().setLocalMatrix(matrix);

        canvas.drawCircle(zoomPos.x, zoomPos.y, 100, mPaint);
    }
}

シェーダーには、説明されているようにビットマップシェーダーを使用したことに注意してください ここ これは次のように作成されました:

mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
mShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);

mPaint = new Paint();
mPaint.setShader(mShader);
18
qzikl

イメージに加えられた変更を元に戻す最良の方法は、ソースファイルからイメージをリロードすることです。または、変換を開始する前に、MotionEvent.ACTION_UPで元の行列をロードしている間、元の行列のコピー変数を保持します。

6
blaffie

何人かの人々は固定された場所の拡大鏡の位置を求めました、私はそれを実験して解決策を思いつきました:

// bitmapWidth is the width of bitmap used for BitmapShader
// bitmapHeight is the height of bitmap used for BitmapShader
// canvasWidth is the width of canvas where the zoom touch events are tracked (usually has the same image as shader but can be different size)
// canvasHeight is the height of canvas where the zoom touch events are tracked
// touchPoint is the point on the canvas which area should be shown in zoom circle
// fixedZoomPoint is the center of the zoom circle (different from touch point)
// ZOOM_SCALE is the zooming ratio (e.g.: 2f)
// ZOOM_RADIUS is the radius of the zoom circle

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    if (zooming) {
        val widthRatio = bitmapWidth / canvasWidth // This can be omitted if 1.0
        val heightRatio = bitmapHeight / canvasHeight // This can be omitted if 1.0
        matrix.reset()
        matrix.postScale(ZOOM_SCALE, ZOOM_SCALE, touchPoint.x * widthRatio, touchPoint.y * heightRatio)
        matrix.postTranslate(fixedZoomPoint.x - touchPoint.x * widthRatio, fixedZoomPoint.y - touchPoint.y * heightRatio)
        Paint.getShader().setLocalMatrix(matrix)
        drawCircle(fixedZoomPoint.x, fixedZoomPoint.y, ZOOM_RADIUS, Paint)
    }
}
2
Mate Herber

カスタムimageviewを使用して実装でき、パッケージにCodesforMagnifierImageView.Javaクラスを作成します。それぞれのクラスのコードは CodesforMagnifier.Java で確認でき、imageviewの代わりにレイアウトファイルで次のコードを使用するだけです。

<com.yourpackage.CodesforMagnifierImageView
     Android:layout_width="wrap_content"
      Android:layout_height="wrap_content"
      Android:src="@drawable/your image" />
0
Ramees