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

时间:2018-06-11 21:10:22

标签: android canvas draggable android-drawable

我正在尝试使用canvas创建一个简单的绘图应用程序。最终产品将供用户选择所选工具(笔,标记,橡皮擦等),并相应地绘制或擦除工具在画布上拖动的任何位置。

截至目前,我只有一支笔,我试图在画布中拖动笔的任何地方画一条线。但是,我发现这项任务具有挑战性。我可以拖动笔,我可以绘制线条,但是在拖动笔时我无法绘制。我正在与SO社区联系,以弥合这两个特征。

以下是我所拥有的:

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

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中

<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()

1 个答案:

答案 0 :(得分:0)

需要更新MainActivity和CanvasView。请参阅以下新的源代码:

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:

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;
}