简体   繁体   English

在拖动视图的任何地方在画布上绘制

[英]Draw on canvas wherever view is dragged

I am trying to create a simple paint app using canvas. 我正在尝试使用画布创建一个简单的绘画应用程序。 The end product would be for the user to select a tool of choice (pen, marker, eraser, etc) and draw or erase accordingly anywhere the tool is dragged on the canvas. 最终产品将是供用户选择的工具(笔,记号笔,橡皮擦等),并在工具拖动到画布上的任何位置相应地绘制或擦除。

As of now, I only have a pen and I am trying to draw a line wherever the pen is dragged in the canvas. 截至目前,我只有一支笔,并且无论笔在画布中的拖动位置如何,我都试图画一条线。 However, I am finding this task challenging. 但是,我发现此任务具有挑战性。 I can drag the pen and I can draw lines, but I can't draw while I am dragging the pen. 我可以拖动笔并且可以画线,但是在拖动笔时不能画图。 I am reaching out to the SO community to bridge these two features. 我正在联系SO社区来桥接这两个功能。

Below is what I have: 以下是我所拥有的:

MainActivity.java MainActivity.java

public class MainActivity extends AppCompatActivity {

private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;
private RelativeLayout pl;
private ImageView w1;
private boolean clicked1 = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    CanvasView canvasView = new CanvasView(MainActivity.this);

    w1 = (ImageView) findViewById(R.id.wand1);
    pl = (RelativeLayout) findViewById(R.id.coordAct);
    RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.coordAct);

    rootLayout.addView(canvasView);

    RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
    layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
    canvasView.setLayoutParams(layoutParams1w2);

    w1.setOnTouchListener(new ChoiceTouchListener());
}

public static int getScreenWidth() {
    return Resources.getSystem().getDisplayMetrics().widthPixels;
}

public static int getScreenHeight() {
    return Resources.getSystem().getDisplayMetrics().heightPixels;
}

public class ChoiceTouchListener implements View.OnTouchListener {
    public boolean onTouch(View view, MotionEvent event) {
        if (!clicked1){
            rootLayout = (ViewGroup) w1.getParent();
            if (rootLayout != null) {
                // detach the child from parent
                rootLayout.removeView(w1);
            }
            RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(300, 300);
            pl.addView(w1);

            w1.setLayoutParams(layoutParams1);
            clicked1 = true;
        }
        final int X = (int) event.getRawX();
        final int Y = (int) event.getRawY();

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
                _xDelta = X - lParams.leftMargin;
                _yDelta = Y - lParams.topMargin;
                break;
            case MotionEvent.ACTION_MOVE:
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
                        .getLayoutParams();
                layoutParams.leftMargin = X - _xDelta;
                layoutParams.topMargin = Y - _yDelta;
                layoutParams.rightMargin = -250;
                layoutParams.bottomMargin = -250;
                view.setLayoutParams(layoutParams);
                break;
        }
        rootLayout.invalidate();
        return true;
    }
}

CanvasView.java CanvasView.java

public class CanvasView extends View{
Context context;
int width, height;
Bitmap bitmap;
Path path;
Canvas canvas;
Paint paint;
float mX, mY;
static final float TOLERANCE=4;
public CanvasView(Context context) {
    super(context);
    this.context=context;
    path=new Path();
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeWidth(50);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w,h,oldw,oldh);
    bitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
    canvas=new Canvas(bitmap);
}

public void startTouch(float x, float y) {
    path.moveTo(x, y);
    mX = x;
    mY = y;
}

public void moveTouch(float x, float y) {
    float dx = Math.abs(x-mX);
    float dy = Math.abs(y-mY);

    if(dx>=TOLERANCE || dy>= TOLERANCE) {
        path.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
        mX=x;
        mY=y;
    }
}

//To clear canvas
public void clearCanvas() {
    path.reset();
    invalidate();
}

public void upTouch() {
    path.lineTo(mX,mY);
}
@Override
protected void onDraw(Canvas canvas){
    super.onDraw(canvas);
    canvas.drawPath(path,paint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction())
    {
        case MotionEvent.ACTION_DOWN:
            startTouch(x,y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            moveTouch(x,y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            upTouch();
            invalidate();
            break;
        default:
            return false;
    }
    invalidate();
    return true;
}

activity_main.xml activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/coordAct"
tools:context="com.simplepaintapp.MainActivity">

<RelativeLayout
    android:id="@+id/parLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:weightSum="3"
    android:background="#0000ff">



    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="28dp"
        android:background="#BA9DF7"
        android:gravity="bottom"
        android:orientation="vertical">

        <HorizontalScrollView
            android:id="@+id/backgd"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:weightSum="1">

            <LinearLayout
                android:id="@+id/parentLL"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="horizontal"
                android:weightSum="5">


                <ImageView
                    android:id="@+id/wand1"
                    android:layout_width="100dp"
                    android:layout_height="100dp"
                    android:layout_centerInParent="true"
                    android:layout_gravity="center"
                    android:src="@drawable/pen" />


            </LinearLayout>
        </HorizontalScrollView>
    </RelativeLayout>


</RelativeLayout>

Current bug after implementing the dispatchTouchEvent() method inside onTouch() 在onTouch()内实现dispatchTouchEvent()方法后的当前错误

An update to MainActivity and CanvasView is required. 需要更新MainActivity和CanvasView。 See the new source code below: 请参阅下面的新源代码:

MainActivity.java MainActivity.java

public class MainActivity extends AppCompatActivity {

private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;
private RelativeLayout pl;
private ImageView w1;
private boolean clicked1 = false;
CanvasView canvasView;
public static int X;
public static int Y;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    canvasView = new CanvasView(MainActivity.this);

    w1 = (ImageView) findViewById(R.id.wand1);
    pl = (RelativeLayout) findViewById(R.id.coordAct);
    RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.coordAct);

    rootLayout.addView(canvasView);

    RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
    layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
    canvasView.setLayoutParams(layoutParams1w2);

    w1.setOnTouchListener(new ChoiceTouchListener());
}

public static int getScreenWidth() {
    return Resources.getSystem().getDisplayMetrics().widthPixels;
}

public static int getScreenHeight() {
    return Resources.getSystem().getDisplayMetrics().heightPixels;
}

public class ChoiceTouchListener implements View.OnTouchListener {
    public boolean onTouch(View view, MotionEvent event) {

        if (!clicked1){
            rootLayout = (ViewGroup) w1.getParent();
            if (rootLayout != null) {
                // detach the child from parent
                rootLayout.removeView(w1);
            }
            RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(300, 300);
            pl.addView(w1);

            w1.setLayoutParams(layoutParams1);
            clicked1 = true;
        }
        X = (int) event.getRawX();
        Y = (int) event.getRawY();

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
                _xDelta = X - lParams.leftMargin;
                _yDelta = Y - lParams.topMargin;
                canvasView.dispatchTouchEvent(event);
                break;
            case MotionEvent.ACTION_MOVE:
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
                        .getLayoutParams();
                layoutParams.leftMargin = X - _xDelta;
                layoutParams.topMargin = Y - _yDelta;
                layoutParams.rightMargin = -250;
                layoutParams.bottomMargin = -250;
                view.setLayoutParams(layoutParams);
                canvasView.dispatchTouchEvent(event);
                break;
        }
        rootLayout.invalidate();
        return true;
    }
}

CanvasView.java: CanvasView.java:

public class CanvasView extends View{
Context context;
int width, height;
Bitmap bitmap;
Path path;
public Canvas canvas;
Paint paint;
float mX, mY;
static final float TOLERANCE=4;
public static float x;
public static float y;
public CanvasView(Context context) {
    super(context);
    this.context=context;
    path=new Path();
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeWidth(50);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w,h,oldw,oldh);
    bitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
    canvas=new Canvas(bitmap);
}

public void startTouch(float x, float y) {
    path.moveTo(x, y);
    mX = x;
    mY = y;
}

public void moveTouch(float x, float y) {
    float dx = Math.abs(x-mX);
    float dy = Math.abs(y-mY);

    if(dx>=TOLERANCE || dy>= TOLERANCE) {
        path.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
        mX=x;
        mY=y;
    }
}

//To clear canvas
public void clearCanvas() {
    path.reset();
    invalidate();
}

public void upTouch() {
    path.lineTo(mX,mY);
}
@Override
protected void onDraw(Canvas canvas){
    super.onDraw(canvas);
    canvas.drawPath(path,paint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    switch (event.getAction())
    {
        case MotionEvent.ACTION_DOWN:
            startTouch(MainActivity.X,MainActivity.Y-380);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            moveTouch(MainActivity.X,MainActivity.Y-380);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            upTouch();
            invalidate();
            break;
        default:
            return false;
    }
    invalidate();
    return true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM