Android:在ImageView顶部手动绘制
我想在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
<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);
}