姓名:李昕洲 学号:16030120026
转载自:http://blog.csdn.net/lin_dianwei/article/details/78791795
【嵌牛导读】:Android开发中,有时需要一个半透明的草稿界面,上面可当草稿纸一样画图,还可以撤销、恢复和清除。为此做了个简单的DrawView控件,包含了以上的功能。下面为将介绍。
【嵌牛鼻子】:DrawView控件。
【嵌牛提问】:怎么具体实现及其代码是什么?
【嵌牛正文】:
代码如下DrawView.java:
package com.ldw.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* 说明:自定义画图控件,继承View
* @author ldw
* 日期:2017.12.13
*/
public class DrawView extends View {
//画笔
private Paint mPaint = null;
//绘制的记录
private List
<path>
mPathList = new ArrayList<>();
//丢弃的记录,redo用
private List
<path>
mRecycleList = new ArrayList<>(); //临时变量 private float preX; private float preY; private Path path; public DrawView(Context context, AttributeSet attrs) { super(context, attrs); //设置抖动处理 mPaint = new Paint(Paint.DITHER_FLAG); //设置画笔颜色 mPaint.setColor(Color.BLACK); //设置画笔风格 mPaint.setStyle(Style.STROKE); mPaint.setStrokeWidth(3); //反锯齿 mPaint.setAntiAlias(true); mPaint.setDither(true); // 设置外边缘 mPaint.setStrokeJoin(Paint.Join.ROUND); // 圆形样式 mPaint.setStrokeCap(Paint.Cap.ROUND); } @Override public boolean onTouchEvent(MotionEvent event){ float x = event.getX(); float y = event.getY(); switch(event.getAction()){ case MotionEvent.ACTION_DOWN: path = new Path(); mPathList.add(path); mRecycleList.clear(); preX = x; preY = y; path.moveTo(x, y); break; case MotionEvent.ACTION_MOVE: float dx = Math.abs(x - preX); float dy = Math.abs(y - preY); if(dx >= 2.0 || dy >= 2.0){ /* * 二次贝塞尔曲线参数说明: * 控制点:为每次event获得的点(x, y) * 起点和终点:为获得的点(x, y)的一系列中间点。 * 说明:这样贝塞尔曲线一般是不会经过(x, y)(除非是直线的时候),而是经过所有中间点。 * 但却能保证曲线向(x, y)的方向弯曲。 * 如果终点设置为(x, y),控制点很难去计算。 * 缺点:根据贝塞尔曲线公式可以知道:控制点和启动终点共线的话,曲线段变成直线。 * 刚开始绘线的一小段会变成直线,因为起点和控制点重叠,不过效果很不明显。 * 如果是path.quadTo(preX, preY, x, y);也变成画直线,跟path.lineTo(x,y);一样效果 */ //二次贝塞尔曲线:控制点设置为起点,终点设置为中间点 path.quadTo(preX, preY, (preX + x)/2, (preY + y)/2); preX = x; preY = y; } break; case MotionEvent.ACTION_UP: path.lineTo(x, y); break; } invalidate(); return true; } @Override public void onDraw(Canvas canvas){ for(Path path : mPathList){ canvas.drawPath(path, mPaint); } } /** * 能否撤销 */ public boolean canUndo(){ return mPathList.size() > 0; } /** * 能否恢复 */ public boolean canRedo(){ return mRecycleList.size() > 0; } /** * 撤销 */ public void undo() { if(canUndo()){ mRecycleList.add(mPathList.remove(mPathList.size() - 1)); invalidate(); } } /** * 恢复 */ public void redo(){ if(canRedo()){ mPathList.add(mRecycleList.remove(mRecycleList.size() - 1)); invalidate(); } } /** * 清除全部 */ public void clear() { mRecycleList.clear(); if(canUndo()) { mPathList.clear(); invalidate(); } } /** * 设置画笔大小 */ public void setPaintWidth(int width) { mPaint.setStrokeWidth(width); } }
</path>
</path>
Activity中使用如下:
1、activity要设置半透明的背景,主题要加上:
<item name="android:windowBackground">
@color/translucentWindow
</item>//半透明值为#7fffffff
<item name="android:windowIsTranslucent">
true
</item>
2、把控件放进布局,使用提供的几个接口。
网友评论