效果圖:
首先,讓我們簡單瞭解surfaceview.
通過查找,我們不難發現SurfaceView繼承自View,所以它本質也是一個View。
其實,SurfaceView也是一個自定義View.主要方法也沒有多少。
我們需要寫一個自定義View.
SurfaceHolder 回調的依附,相當於句柄,手柄,接口的擁有者,是操作處理的持有者。
我們要使用句柄的callback接口,實現三個方法:創建、改變、銷燬。
public interface Callback {
void surfaceCreated(SurfaceHolder var1);
void surfaceChanged(SurfaceHolder var1, int var2, int var3, int var4);
void surfaceDestroyed(SurfaceHolder var1);
}
還有繪製時觸摸時間,還有線程持續操作。
用畫筆繪製在畫布上繪製路徑。
代碼比較簡單:
自定義View MSurfaceView.java
public class MSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
/**
* 是否處於繪製狀態
*/
private boolean mIsDrawing;
/**
* 幫助類
*/
private SurfaceHolder mHolder;
/**
* 畫布
*/
private Canvas mCanvas;
/**
* 路徑
*/
private Path mPath;
/**
* 畫筆
*/
private Paint mPaint;
public MSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return true;
}
private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
if (mPath == null) {
mPath = new Path();
}
if (mPaint == null) {
mPaint = new Paint();
}
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
}
@Override
public void run() {
long start = System.currentTimeMillis();
while (mIsDrawing) {
draw();
}
long end = System.currentTimeMillis();
if (end - start < 100) {
try {
Thread.sleep(100 - (end - start));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
mIsDrawing = true;
new Thread(this).start();
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
mIsDrawing = false;
}
private void draw() {
try {
mCanvas = mHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mCanvas.drawPath(mPath, mPaint);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mCanvas != null) {
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
/**
* 清除內容
*/
public void reset() {
mPath.reset();
}
/**
* 設置字號顏色
* @param size
* @param color
*/
public void setLineSizeandColor(int size, int color) {
mPaint.setStrokeWidth(size);
mPaint.setColor(color);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
MSurfaceView mSurfaceView;
LinearLayout winpop;
TextView setSize, reset;
RadioGroup group;
RadioButton size_ten, size_twelve, size_fifteen;
FrameLayout activity_main;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
activity_main = (FrameLayout) findViewById(R.id.activity_main);
reset = (TextView) findViewById(R.id.reset);
setSize = (TextView) findViewById(R.id.setsize);
mSurfaceView = (MSurfaceView) findViewById(R.id.surfaceview);
winpop = (LinearLayout) findViewById(R.id.winpop);
activity_main.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (winpop.getVisibility() == View.VISIBLE) {
winpop.setVisibility(View.GONE);
}
}
});
reset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mSurfaceView.reset();
if (winpop.getVisibility() == View.VISIBLE) {
winpop.setVisibility(View.GONE);
}
}
});
setSize.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
winpop.setVisibility(View.VISIBLE);
}
});
//根據ID找到RadioGroup實例
group = (RadioGroup) this.findViewById(R.id.radioGroup);
size_ten = (RadioButton) findViewById(R.id.sizeten);
size_twelve = (RadioButton) findViewById(R.id.sizetwelve);
size_fifteen = (RadioButton) findViewById(R.id.sizefifteen);
size_ten.setChecked(true);
//綁定一個匿名監聽器
group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup arg0, int arg1) {
// TODO Auto-generated method stub
int size, color;
if (arg1 == size_ten.getId()) {
size = 10;
color = Color.BLACK;
} else if (arg1 == size_twelve.getId()) {
size = 12;
color = Color.BLUE;
} else {
size = 15;
color = Color.RED;
}
mSurfaceView.setLineSizeandColor(size, color);
winpop.setVisibility(View.GONE);
}
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--第一層-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:textColor="#642100"
android:textSize="18dp"
android:gravity="center"
android:text="畫板使用" />
<TextView
android:id="@+id/setsize"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:clickable="true"
android:gravity="center"
android:textColor="#642100"
android:text="設置字號/顏色" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="#dedede" />
</RelativeLayout>
<com.lcl.view.MSurfaceView
android:id="@+id/surfaceview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentTop="true"
android:background="#dedede" />
<TextView
android:id="@+id/reset"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:textColor="#642100"
android:gravity="center"
android:text="重繪" />
</RelativeLayout>
</LinearLayout>
<!--第二層-->
<LinearLayout
android:id="@+id/winpop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="right|top"
android:layout_marginTop="60dp"
android:background="#cdcdcd">
<RadioButton
android:id="@+id/sizeten"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="10號|黑色" />
<RadioButton
android:id="@+id/sizetwelve"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="12號|藍色" />
<RadioButton
android:id="@+id/sizefifteen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="15號|紅色" />
</RadioGroup>
</LinearLayout>
</FrameLayout>