自定義視圖view使用Canvas實(shí)現(xiàn)手寫板和涂鴉功能
預(yù)覽圖

一、xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:id="@+id/main_linlayout"
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="確定"/>
<Button
android:id="@+id/bt_clear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="清空"/>
</LinearLayout>
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_gravity="center"/>
</LinearLayout>
布局預(yù)覽圖

二、MainActivity代碼
package tester.ermu.com.handdrawdemo;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.EmbossMaskFilter;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends Activity implements View.OnClickListener{
EmbossMaskFilter emboss;
BlurMaskFilter blur;
DrawView drawView;
private LinearLayout main_linlayout;
private Button bt,bt_clear;
private ImageView img;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init(); //初始化組件
getWH();//獲取我們xml布局中view的寬高
}
//獲取我們xml布局中view的寬高
private void getWH() {
// 獲取創(chuàng)建的寬度和高度
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
// 創(chuàng)建一個(gè)DrawView,該DrawView的寬度、高度與該Activity保持相同
main_linlayout = (LinearLayout)findViewById(R.id.main_linlayout);
drawView = new DrawView(this, displayMetrics.widthPixels, displayMetrics.heightPixels);
main_linlayout.addView(drawView);
drawView.requestFocus();
}
private void init() {
bt = (Button)findViewById(R.id.bt);
bt.setOnClickListener(this);
bt_clear = (Button)findViewById(R.id.bt_clear);
bt_clear.setOnClickListener(this);
img = (ImageView) findViewById(R.id.img);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.bt:
Bitmap bit = drawView.getPaintBitmap();
img .setImageBitmap(bit);
break;
case R.id.bt_clear:
drawView.clear();
break;
}
}
}
三、我們自定義view的類
package tester.ermu.com.handdrawdemo;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class DrawView extends View {
// 定義記錄前一個(gè)拖動(dòng)事件發(fā)生點(diǎn)的坐標(biāo)
float preX;
float preY;
private Path path;
public Paint paint = null;
// 定義一個(gè)內(nèi)存中的圖片,該圖片將作為緩沖區(qū)
Bitmap cacheBitmap = null;
// 定義cacheBitmap上的Canvas對(duì)象
Canvas cacheCanvas = null;
public DrawView(Context context) {
super(context);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DrawView(Context context, int width , int height) {
super(context);
// 創(chuàng)建一個(gè)與該View相同大小的緩存區(qū)
cacheBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
cacheCanvas = new Canvas();
path = new Path();
// 設(shè)置cacheCanvas將會(huì)繪制到內(nèi)存中的cacheBitmap上
cacheCanvas.setBitmap(cacheBitmap);
// 設(shè)置畫筆的顏色
paint = new Paint(Paint.DITHER_FLAG);
paint.setColor(Color.RED);
// 設(shè)置畫筆風(fēng)格
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
// 反鋸齒
paint.setAntiAlias(true);
paint.setDither(true);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// 獲取拖動(dòng)事件的發(fā)生位置
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
// 從前一個(gè)點(diǎn)繪制到當(dāng)前點(diǎn)之后,把當(dāng)前點(diǎn)定義成下次繪制的前一個(gè)點(diǎn)
path.moveTo(x, y);
preX = x;
preY = y;
break;
case MotionEvent.ACTION_MOVE:
// 從前一個(gè)點(diǎn)繪制到當(dāng)前點(diǎn)之后,把當(dāng)前點(diǎn)定義成下次繪制的前一個(gè)點(diǎn)
path.quadTo(preX, preY, x, y);
preX = x;
preY = y;
break;
case MotionEvent.ACTION_UP:
cacheCanvas.drawPath(path, paint); // ①
path.reset();
break;
}
invalidate();
// 返回true表明處理方法已經(jīng)處理該事件
return true;
}
@Override
public void onDraw(Canvas canvas)
{
Paint bmpPaint = new Paint();
// 將cacheBitmap繪制到該View組件上
canvas.drawBitmap(cacheBitmap, 0, 0, bmpPaint); // ②
// 沿著path繪制
canvas.drawPath(path, paint);
}
//獲取我們繪制成功后的圖片
public Bitmap getPaintBitmap() {
return resizeImage(cacheBitmap, 620, 780);
}
// 縮放
public static Bitmap resizeImage(Bitmap bitmap, int width, int height) {
//獲取圖片的寬高
int originWidth = bitmap.getWidth();
int originHeight = bitmap.getHeight();
//這里縮放我們的尺寸,縮放多少自己去定義
float scaleWidth = ((float) width) / originWidth;
float scaleHeight = ((float) height) / originHeight;
//進(jìn)行縮放
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, originWidth,
originHeight, matrix, true);
return resizedBitmap;
}
//清除畫板
public void clear() {
if (cacheBitmap != null) {
path.reset();
cacheCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
invalidate();
}
}
}
到此這篇關(guān)于自定義視圖view使用Canvas實(shí)現(xiàn)手寫板和涂鴉功能的文章就介紹到這了,更多相關(guān)自定義視圖Canvas手寫板涂鴉內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android開發(fā)之使用ViewPager實(shí)現(xiàn)圖片左右滑動(dòng)切換效果
這篇文章主要介紹了Android開發(fā)之使用ViewPager實(shí)現(xiàn)圖片左右滑動(dòng)切換效果的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08
Android Adapter里面嵌套ListView實(shí)例詳解
這篇文章主要介紹了Android Adapter里面嵌套ListView實(shí)例詳解的相關(guān)資料,這里提供實(shí)例代碼并說明如何實(shí)現(xiàn)該功能,需要的朋友可以參考下2017-07-07
android換膚功能 如何動(dòng)態(tài)獲取控件中背景圖片的資源id?
這篇文章主要為大家詳細(xì)介紹了android換膚功能中如何動(dòng)態(tài)獲取控件中背景圖片的資源id? ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08
Android實(shí)現(xiàn)測(cè)試環(huán)境噪音分貝
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)測(cè)試環(huán)境噪音分貝,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Android 中圖片和按鈕按下狀態(tài)變化實(shí)例代碼解析
這篇文章通過實(shí)例代碼給大家總結(jié)了android 中圖片和按鈕按下狀態(tài)變化問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-06-06
Android實(shí)現(xiàn)可點(diǎn)擊的幸運(yùn)大轉(zhuǎn)盤
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)可點(diǎn)擊的幸運(yùn)大轉(zhuǎn)盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02

