一. 前言
封装了画板的一些基本操作。
Github地址:XLDrawBoard

二. 自定义View
1. 自定义用到的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| private int bg_color = Color.WHITE;
private int board_state = BOARD_STATE_PEN; public static final int BOARD_STATE_PEN = 0; public static final int BOARD_STATE_ERASER = 1;
private int lineColor = Color.MAGENTA;
private int lineWidth = 20;
private Path temp_path;
private List<Graph> graphs;
private List<Graph> last_graphs;
|
2. 在values文件夹下自定义属性
1 2 3 4 5 6 7
| <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="XLDrawBoard"> <attr name="bg_color" format="color"/> </declare-styleable> </resources>
|
3. 创建构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
public XLDrawBoard(Context context, int bg_color) { super(context);
this.bg_color = bg_color;
init(); }
public XLDrawBoard(Context context, @Nullable AttributeSet attrs) { super(context, attrs);
if (attrs != null){ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.XLDrawBoard); bg_color = typedArray.getColor(R.styleable.XLDrawBoard_bg_color,bg_color); typedArray.recycle(); }
init(); }
private void init() { graphs = new ArrayList<>(); last_graphs = new ArrayList<>();
setBackgroundColor(bg_color); }
|
4. 绘制过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);
for (Graph graph : graphs) { canvas.drawPath(graph.path, graph.paint); } }
private static class Graph { Path path; Paint paint;
Graph(Path path, Paint paint) { this.path = path; this.paint = paint; }
}
|
5. 触摸事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
@SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY();
switch (event.getAction()){ case MotionEvent.ACTION_DOWN: temp_path = new Path(); temp_path.moveTo(x,y);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(lineColor); paint.setStrokeWidth(lineWidth); paint.setStyle(Paint.Style.STROKE); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeJoin(Paint.Join.ROUND);
Graph graph = new Graph(temp_path, paint); graphs.add(graph); last_graphs.add(graph);
break; case MotionEvent.ACTION_MOVE: temp_path.lineTo(x,y);
break; case MotionEvent.ACTION_UP: break; }
invalidate();
return true; }
|
6. 事件的管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
public void removeLast(){ if (graphs.size() > 0){ remove_graphs.add(graphs.get(graphs.size()-1)); graphs.remove(graphs.size()-1);
invalidate(); } }
public void resumeLast(){ if (remove_graphs.size() > 0){ graphs.add(remove_graphs.get(remove_graphs.size()-1)); remove_graphs.remove(remove_graphs.size()-1);
invalidate(); return; }
Toast.makeText(getContext(), "不可还原", Toast.LENGTH_SHORT).show(); }
public void removeAll(){ if (graphs.size() > 0){ graphs.clear(); remove_graphs.clear();
invalidate(); } }
public Bitmap save(){ Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawColor(bg_color); if (graphs != null){ for (Graph graph : graphs) { canvas.drawPath(graph.path, graph.paint); } }
return bitmap; }
|
三. 具体的使用
首先需要添加依赖,添加依赖之后,在布局文件中这样调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| <?xml version="1.0" encoding="utf-8"?> <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" tools:context=".MainActivity" android:background="#696969">
<swu.xl.drawboard.XLDrawBoard android:id="@+id/board" android:layout_width="match_parent" android:layout_height="500dp" app:bg_color="#ffffff" />
<LinearLayout android:layout_above="@id/operation" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center" >
<Button android:id="@+id/size_20" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="20" />
<Button android:id="@+id/color_red" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#ff0000" />
<Button android:id="@+id/color_green" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00ff00" />
<Button android:id="@+id/size_40" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="40" />
</LinearLayout>
<LinearLayout android:id="@+id/operation" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="horizontal" android:gravity="center" >
<Button android:id="@+id/pen" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="笔" />
<Button android:id="@+id/undo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="撤销" />
<Button android:id="@+id/resume" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="重做" />
<Button android:id="@+id/clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清空" />
<Button android:id="@+id/eraser" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="橡皮" />
</LinearLayout>
</RelativeLayout>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| public class MainActivity extends AppCompatActivity implements View.OnClickListener {
XLDrawBoard board;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
board = findViewById(R.id.board);
findViewById(R.id.size_20).setOnClickListener(this); findViewById(R.id.size_40).setOnClickListener(this); findViewById(R.id.color_red).setOnClickListener(this); findViewById(R.id.color_green).setOnClickListener(this); findViewById(R.id.pen).setOnClickListener(this); findViewById(R.id.undo).setOnClickListener(this); findViewById(R.id.resume).setOnClickListener(this); findViewById(R.id.clear).setOnClickListener(this); findViewById(R.id.eraser).setOnClickListener(this); }
@Override public void onClick(View v) { switch (v.getId()){ case R.id.size_20: board.setLineWidth(20); break;
case R.id.size_40: board.setLineWidth(40);
break;
case R.id.color_red: board.setLineColor(Color.RED); break;
case R.id.color_green: board.setLineColor(Color.GREEN);
break;
case R.id.pen: board.setBoard_state(XLDrawBoard.BOARD_STATE_PEN); break;
case R.id.eraser: board.setBoard_state(XLDrawBoard.BOARD_STATE_ERASER);
break;
case R.id.undo: board.removeLast(); break;
case R.id.resume: board.resumeLast();
break;
case R.id.clear: board.removeAll(); break;
} } }
|
