Android:在ImageView顶部手动绘制

Android:在ImageView顶部手动绘制,android,xamarin.android,imageview,drawing,landscape-portrait,Android,Xamarin.android,Imageview,Drawing,Landscape Portrait,我想在ImageView上实现手绘功能 这是我的布局: <android.support.constraint.ConstraintLayout android:id="@+id/constraintLayoutEditImage" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@str

我想在ImageView上实现手绘功能

这是我的布局:

<android.support.constraint.ConstraintLayout
        android:id="@+id/constraintLayoutEditImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <RelativeLayout
            android:id="@+id/relativeLayoutEditImage"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginRight="0dp"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_marginLeft="0dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="0dp"
            android:layout_marginBottom="0dp"
            app:layout_constraintBottom_toTopOf="@+id/constraintLayoutEditImageToolbar">

            <ImageView
                android:id="@+id/imageViewEditImage"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/light_blue" />

            <mobileclient.Droid.HandDrawingCanvasView
                android:id="@+id/canvasViewEditImage"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/transparent"/>
        </RelativeLayout>

        <android.support.constraint.ConstraintLayout
            ........> //this is the toolbar, etc
        </android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
结果如下:


如你所见,我甚至可以在图像外部绘制蓝色区域是ImageView背景。如何将可绘制区域限制为仅在图片边界内?

首先需要在显示图像的ImageView中找到绘制图像的边界

一旦你有了它,你可以放弃任何超出该区域的触摸事件。onTouchEvent的伪代码将位于以下行中的某个位置:

    Overrides
    public override bool OnTouchEvent(MotionEvent touchEvent){

        if(!isInsideDesiredArea(touchEvent.getX(), touchEvent.getY()){
            return false;
        }

        ... //same with what you have now
    }
要查找由ImageView绘制的可绘制边界,可以使用Rect r=ImageView.getDrawable.copyBounds,它将在r中写入边界

最后,我的目标是。。。将如下所示:

private boolean isInsideDesiredArea(float x, float y) {
    //get the image view
    ImageView imageView = (ImageView) findViewById(R.id.my_imageview_id);

    //get the transform it applied on the drawable
    float[] imageViewTransformMatrixValues = new float[9];
    imageView.getImageMatrix().getValues(imageViewTransformMatrixValues);

    //get the bounds of the drawn drawable, before the transforms are applied to it, and in local coordinates
    Rect drawableRect = imageView.getDrawable().copyBounds();

    //get the drawable scale & translation, from its matrix
    float scaleX = imageViewTransformMatrixValues[Matrix.MSCALE_X];
    float scaleY = imageViewTransformMatrixValues[Matrix.MSCALE_Y];
    float translationX = imageViewTransformMatrixValues[Matrix.MTRANS_X];
    float translationY = imageViewTransformMatrixValues[Matrix.MTRANS_Y];

    //compute the actual bounds of the drawable, within the image view, in image view local coordinates
    Rect actualImageRect = new Rect();
    actualImageRect.top = Math.round(translationY + scaleY * drawableRect.top);
    actualImageRect.left = Math.round(translationX + scaleX * drawableRect.left);
    actualImageRect.bottom = Math.round(translationY + scaleY * drawableRect.bottom);
    actualImageRect.right = Math.round(translationX + scaleX * drawableRect.right);

    //finally check if the touch events are within the rectangle defined by the drawable
    return actualImageRect.contains((int) x, (int) y);
}
我在一个小样本项目上测试了它,效果很好


希望这有帮助。

我已经尝试了您的解决方案,边界区域发生了移动,如您在此处所见:然后,在绘制两次/三次后,InProgressPolyline中将出现异常。Addid,polyline;啊好的。您已经在视图的局部坐标系中获得了触摸事件。我会更新我的答案。我不能对崩溃发表评论,那一定是在你的代码中的某个地方。检查新版本的代码,现在应该可以了。以前的版本还垂直转换事件,假定事件在屏幕的坐标系中,以便与图像视图的坐标系匹配。但由于您的onTouchEvent是ImageView本身的,所以没有必要进行此翻译。我现在尝试了您的新版本,它可以正常工作。您是否知道旋转设备时如何保存手绘?现在,如果我旋转设备,手动绘图将消失。您需要保存点,然后在设备旋转后再次绘制点,或者获取手动绘图画布视图的位图。要获取视图的位图,可以使用视图图形缓存。如果已启用该功能,则可以使用位图handDrawing=myHandDrawingView.getDrawingCache,然后将位图保存在saveInstanceStateBundle myBundle与myBundle.putParcelabledrawing、handDrawing中的捆绑包中。然后,在旋转后,在onRestoreInstanceStateBundle savedState中,通过位图Bitmap=savedState.getParcelabledrawing将其取回
private boolean isInsideDesiredArea(float x, float y) {
    //get the image view
    ImageView imageView = (ImageView) findViewById(R.id.my_imageview_id);

    //get the transform it applied on the drawable
    float[] imageViewTransformMatrixValues = new float[9];
    imageView.getImageMatrix().getValues(imageViewTransformMatrixValues);

    //get the bounds of the drawn drawable, before the transforms are applied to it, and in local coordinates
    Rect drawableRect = imageView.getDrawable().copyBounds();

    //get the drawable scale & translation, from its matrix
    float scaleX = imageViewTransformMatrixValues[Matrix.MSCALE_X];
    float scaleY = imageViewTransformMatrixValues[Matrix.MSCALE_Y];
    float translationX = imageViewTransformMatrixValues[Matrix.MTRANS_X];
    float translationY = imageViewTransformMatrixValues[Matrix.MTRANS_Y];

    //compute the actual bounds of the drawable, within the image view, in image view local coordinates
    Rect actualImageRect = new Rect();
    actualImageRect.top = Math.round(translationY + scaleY * drawableRect.top);
    actualImageRect.left = Math.round(translationX + scaleX * drawableRect.left);
    actualImageRect.bottom = Math.round(translationY + scaleY * drawableRect.bottom);
    actualImageRect.right = Math.round(translationX + scaleX * drawableRect.right);

    //finally check if the touch events are within the rectangle defined by the drawable
    return actualImageRect.contains((int) x, (int) y);
}