绘制具有多种颜色的路径

时间:2017-05-14 17:33:31

标签: java android canvas

我使用android.graphics.Path绘制android.graphics.Canvas。我希望允许用户使用一系列颜色和笔触宽度进行绘制,但是,每当更改颜色或笔触宽度时,都会使用新的颜色或笔触宽度重新绘制所有内容。我该如何解决这个问题?

的xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/activity_main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:id="@+id/btnW10"
            android:layout_margin="3sp"
            android:layout_weight="1"
            android:text="Width10"/>
        <Button
            android:id="@+id/btnW40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="3sp"
            android:layout_weight="1"
            android:text="Width40"/>
        <Button
            android:id="@+id/btnW70"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="3sp"
            android:layout_weight="1"

            android:text="Width70"/>

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="20dp"></LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="3sp"
            android:layout_weight="1"
            android:id="@+id/btnBlue"
            android:text="Blue"/>
        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="3sp"
            android:layout_weight="1"
            android:id="@+id/btnRed"
            android:text="Red"/>
        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="3sp"
            android:layout_weight="1"

            android:id="@+id/btnGreen"
            android:text="Green"/>

    </LinearLayout>

    <com.vladislav.canvaswc.DrawLine
        android:id="@+id/drwLine"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</LinearLayout>

main.java:

public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
   DrawLine dr;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btnB=(Button) findViewById(R.id.btnBlue);
        Button btnG=(Button) findViewById(R.id.btnGreen);
        Button btnR=(Button) findViewById(R.id.btnRed);
        Button btnW10=(Button) findViewById(R.id.btnW10);
        Button btnW40=(Button) findViewById(R.id.btnW40);
        Button btnW70=(Button) findViewById(R.id.btnW70);
        dr =(DrawLine) findViewById(R.id.drwLine);
        btnB.setOnClickListener(this);
        btnG.setOnClickListener(this);
        btnR.setOnClickListener(this);
        btnW10.setOnClickListener(this);
        btnW40.setOnClickListener(this);
        btnW70.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch(v.getId())
        {
            case R.id.btnBlue : dr.changeColor(Color.BLUE);break;
            case R.id.btnGreen : dr.changeColor(Color.GREEN);break;
            case R.id.btnRed : dr.changeColor(Color.RED);break;
            case R.id.btnW10 : dr.changeWidth(10f);break;
            case R.id.btnW40 : dr.changeWidth(40f);break;
            case R.id.btnW70 : dr.changeWidth(70f);break;
        }
    }
}

drawline.java ChangeWidthColor它的界面有2个方法changeColor() 和changeWidth()

public class DrawLine extends View implements ChangeWidthColor {

    private Paint paint = new Paint();
    private Path path = new Path();
    public float x;
    public float y;

    public DrawLine(Context context) {
        super(context);
        init(context);

    }

    public DrawLine(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public DrawLine(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public void init(Context context) {

        //paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.MITER);
        //paint.setStrokeWidth(5f);

    }

    @Override
    public void changeColor(int color) {
        paint.setColor(color);


    }

    @Override
    public void changeWidth(float width) {
        paint.setStrokeWidth(width);

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
       canvas.drawPath(path,paint);

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {


        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x= event.getX();
                y= event.getY();
                path.moveTo(x, y);
                break;
            case MotionEvent.ACTION_MOVE:
                x= event.getX();
                y= event.getY();
                path.lineTo(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                invalidate();
                break;
        }
        invalidate();
        return true;
    }
}

3 个答案:

答案 0 :(得分:3)

此解决方案维护一个Path对象列表和一个用于存储颜色的整数列表。这些列表是并行的 - 路径和颜色对的每个列表中有1个条目。 onDraw迭代这些列表,使用相应的颜色绘制每个路径。

每次用户单击以更改颜色时,都会创建一个新路径。 ACTION_DOWN和ACTION_MOVE在路径上调用moveTo(x,y)和lineTo(x,y),ACTION_UP会将路径和当前颜色添加到列表中。

注意:我没有实现笔触宽度的解决方案,但是,您应该能够按照示例自行添加。

public class DrawLine extends View {

    private Path path = new Path();
    private Paint paint = new Paint();
    private int currentColor = Color.BLACK;
    private List<Path> paths = new ArrayList<Path>();
    private List<Integer> colors = new ArrayList<Integer>();
    private float x;
    private float y;

    public DrawLine(Context context) {
        super(context);
        init(context);
    }

    public DrawLine(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public DrawLine(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public void init(Context context) {
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.MITER);
        paint.setColor(currentColor);
    }

    public void changeColor(int color) {
        currentColor = color;
        path = new Path();
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int x = 0; x < paths.size(); x++) {
            paint.setColor(colors.get(x));
            canvas.drawPath(paths.get(x), paint);
        }
    }

    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = event.getX();
                y = event.getY();
                path.moveTo(x, y);
                break;
            case MotionEvent.ACTION_MOVE:
                x = event.getX();
                y = event.getY();
                path.lineTo(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                paths.add(path);
                colors.add(currentColor);
                invalidate();
                break;
        }
        invalidate();
        return true;
    }
}

`

答案 1 :(得分:0)

public class DrawLine extends View implements ChangeWidthColor {


    private Path path = new Path();
    private Paint paint = new Paint();
    private int currentColor = Color.BLACK;
    private float width = 1f;
    public float x;
    public float y;

    private LinkedList<Integer> color = new LinkedList<Integer>();
    private LinkedList<Float> widthSize = new LinkedList<Float>();
    private LinkedList<Path> paths = new LinkedList<Path>();

    public DrawLine(Context context) {
        super(context);
        init(context);


    }

    public DrawLine(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public DrawLine(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public void init(Context context) {
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.MITER);
        paint.setColor(currentColor);
        paint.setStrokeWidth(5f);

    }

    @Override
    public void changeColor(int color) {
        currentColor = color;
        path = new Path();


    }

    @Override
    public void changeWidth(float width) {
        this.width = width;
        path = new Path();


    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        for (int i = 0; i < paths.size(); i++) {
            paint.setStrokeWidth(widthSize.get(i));
            paint.setColor(color.get(i));
            canvas.drawPath(paths.get(i), paint);
        }


    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = event.getX();
                y = event.getY();
                path.moveTo(x, y);
                break;

            case MotionEvent.ACTION_MOVE:
                x = event.getX();
                y = event.getY();
                path.lineTo(x, y);
                invalidate();

                break;
            case MotionEvent.ACTION_UP:

                color.add(currentColor);
                paths.add(path);
                widthSize.add(width);
                break;
            default:
                return false;
        }
        invalidate();
        return true;
    }


}

答案 2 :(得分:-1)

每当您修改与UI相关的内容时,您都需要在自定义视图中调用invalidate()。所以更新的方法将是:

@Override
public void changeColor(int color) {
    paint.setColor(color);
    invalidate();

}

@Override
public void changeWidth(float width) {
    paint.setStrokeWidth(width);
    invalidate();
}