0
我想在ImageView
之上实现手绘功能。Android:在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>
我遵循了HandDrawingCanvasView
类Multi-Touch Tracking in Android example:
public class HandDrawingCanvasView: View
{
// Two collections for storing polylines
Dictionary<int, HandDrawingPolyline> InProgressPolylines = new Dictionary<int, HandDrawingPolyline>();
List<HandDrawingPolyline> CompletedPolylines = new List<HandDrawingPolyline>();
Paint paint = new Paint(PaintFlags.AntiAlias);
public HandDrawingCanvasView(Context context) : base(context)
{
Initialize();
}
public HandDrawingCanvasView(Context context, IAttributeSet attrs) :
base(context, attrs)
{
Initialize();
}
void Initialize()
{
}
// External interface accessed from MainActivity
public Color StrokeColor { set; get; } = Color.Red;
public float StrokeWidth { set; get; } = 2;
public void ClearAll()
{
CompletedPolylines.Clear();
Invalidate();
}
// Overrides
public override bool OnTouchEvent(MotionEvent args)
{
// Get the pointer index
int pointerIndex = args.ActionIndex;
// Get the id to identify a finger over the course of its progress
int id = args.GetPointerId(pointerIndex);
// Use ActionMasked here rather than Action to reduce the number of possibilities
switch (args.ActionMasked)
{
case MotionEventActions.Down:
case MotionEventActions.PointerDown:
// Create a Polyline, set the initial point, and store it
HandDrawingPolyline polyline = new HandDrawingPolyline
{
Color = StrokeColor,
StrokeWidth = StrokeWidth
};
polyline.Path.MoveTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));
InProgressPolylines.Add(id, polyline);
break;
case MotionEventActions.Move:
// Multiple Move events are bundled, so handle them differently
for (pointerIndex = 0; pointerIndex < args.PointerCount; pointerIndex++)
{
id = args.GetPointerId(pointerIndex);
InProgressPolylines[id].Path.LineTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));
}
break;
case MotionEventActions.Up:
case MotionEventActions.Pointer1Up:
InProgressPolylines[id].Path.LineTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));
// Transfer the in-progress polyline to a completed polyline
CompletedPolylines.Add(InProgressPolylines[id]);
InProgressPolylines.Remove(id);
break;
case MotionEventActions.Cancel:
InProgressPolylines.Remove(id);
break;
}
// Invalidate to update the view
Invalidate();
// Request continued touch input
return true;
}
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
// Clear canvas to white
paint.SetStyle(Paint.Style.Fill);
paint.Color = Color.Transparent;
canvas.DrawPaint(paint);
// Draw strokes
paint.SetStyle(Paint.Style.Stroke);
paint.StrokeCap = Paint.Cap.Round;
paint.StrokeJoin = Paint.Join.Round;
// Draw the completed polylines
foreach (HandDrawingPolyline polyline in CompletedPolylines)
{
paint.Color = polyline.Color;
paint.StrokeWidth = polyline.StrokeWidth;
canvas.DrawPath(polyline.Path, paint);
}
// Draw the in-progress polylines
foreach (HandDrawingPolyline polyline in InProgressPolylines.Values)
{
paint.Color = polyline.Color;
paint.StrokeWidth = polyline.StrokeWidth;
canvas.DrawPath(polyline.Path, paint);
}
}
}
正如你可以看到,我甚至可以在图像外面画图(蓝色区域是t他ImageView
背景)。如何限制可绘制区域只在图片的边界内?
我已经试过您的解决方案和边界区域转移,你可以在这里看到:https://imgur.com/a/d1IvO 然后,经过二/三次绘制,将有'异常InProgressPolylines.Add(id,polyline);' – currarpickt
啊好的。您已经在视图的本地坐标系中获取了触摸事件。我会更新我的答案。我不能评论崩溃,但必须在你的代码 – cjurjiu
检查新版本的代码,应该现在确定。以前的版本也垂直翻译事件,假设事件在屏幕的坐标系中,以匹配图像视图的坐标系统。但由于你的onTouchEvent是ImageView本身的,所以这个翻译没有必要 – cjurjiu