Android簡單實(shí)現(xiàn)畫圖功能
如何在圖片上畫畫呢?這里寫了一個(gè)demo,供大家參考
一、先看一眼工程結(jié)構(gòu)
工程結(jié)構(gòu):

二、自定義view
這個(gè)自定義view實(shí)現(xiàn)了保留軌跡的功能,代碼如下
package picturegame.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.winton.picturegame.R;
public class GameView extends View{
private Paint paint = null; //
private Bitmap originalBitmap = null;//原始圖
private Bitmap new1Bitmap = null;
private Bitmap new2Bitmap = null;
private float clickX =0;
private float clickY=0;
private float startX=0;
private float startY=0;
private boolean isMove = true;
private boolean isClear = false;
private int color =Color.RED;//默認(rèn)畫筆顏色為紅色
private float strokeWidth =2.0f;//默認(rèn)畫筆粗度
public GameView(Context context) {
this(context,null);
// TODO Auto-generated constructor stub
}
public GameView(Context context,AttributeSet atts) {
this(context,atts,0);
// TODO Auto-generated constructor stub
}
public GameView(Context context,AttributeSet atts,int defStyle) {
super(context,atts,defStyle);
// TODO Auto-generated constructor stub
originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.default_pic).copy(Bitmap.Config.ARGB_8888, true);//加載一張背景
new1Bitmap=originalBitmap.createBitmap(originalBitmap);
}
//清除函數(shù)
public void clear(){
isClear =true;
new2Bitmap=originalBitmap.createBitmap(originalBitmap);
invalidate();//重載
}
public void setStrokeWidth(float width){
this.strokeWidth=width;
initPaint();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawBitmap(writer(new1Bitmap),0,0, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
clickX =event.getX();
clickY=event.getY();
if(event.getAction()==MotionEvent.ACTION_DOWN){
isMove =false;
invalidate();
return true;
}
else if(event.getAction()==MotionEvent.ACTION_MOVE){
isMove =true;
invalidate();
return true;
}
return super.onTouchEvent(event);
}
/**
* @Title: writer
* @Description: TODO(生成bitmap)
* @param @param pic
* @param @return 設(shè)定文件
* @return Bitmap 返回類型
* @throws
*/
public Bitmap writer(Bitmap pic){
initPaint();
Canvas canvas =null;
if(isClear){
canvas=new Canvas(new2Bitmap);
}else{
canvas=new Canvas(pic);
}
if(isMove){
canvas.drawLine(startX, startY, clickX, clickY, paint);//劃線
}
startX = clickX;
startY =clickY;
if(isClear){
return new2Bitmap;
}
return pic;
}
private void initPaint(){
paint = new Paint();//新建畫筆
paint.setStyle(Style.STROKE);//設(shè)置為畫線
paint.setAntiAlias(true);//可以讓線條圓滑一些
paint.setColor(color);//設(shè)置畫筆顏色
paint.setStrokeWidth(strokeWidth);//設(shè)置畫筆線條的粗細(xì)
}
/**
* @Title: setColor
* @Description: TODO(設(shè)置線條顏色的對(duì)外接口)
* @param @param color 設(shè)定文件
* @return void 返回類型
* @throws
*/
public void setColor(int color){
this.color=color;
initPaint();
}
}
三、主頁面布局文件
主頁面布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
>
<TextView
android:id="@+id/tv_30"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/bg_notifaction"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
>
<TextView
android:id="@+id/tv_25"
android:layout_width="25dp"
android:layout_height="25dp"
android:background="@drawable/bg_notifaction"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
>
<TextView
android:id="@+id/tv_20"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/bg_notifaction"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
>
<TextView
android:id="@+id/tv_15"
android:layout_width="15dp"
android:layout_height="15dp"
android:background="@drawable/bg_notifaction"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
>
<TextView
android:id="@+id/tv_10"
android:layout_width="10dp"
android:layout_height="10dp"
android:background="@drawable/bg_notifaction"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
>
<TextView
android:id="@+id/tv_5"
android:layout_width="5dp"
android:layout_height="5dp"
android:background="@drawable/bg_notifaction"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
>
<TextView
android:id="@+id/tv_2"
android:layout_width="2dp"
android:layout_height="2dp"
android:background="@drawable/bg_notifaction"
/>
</LinearLayout>
</LinearLayout>
<picturegame.view.GameView
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/gameview"
/>
<Button
android:layout_width="200dp"
android:layout_height="80dp"
android:text="clear"
android:textColor="@color/black"
android:id="@+id/btn_clear"
/>
</LinearLayout>
四、主Activity代碼
package com.winton.picturegame;
import picturegame.view.GameView;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.winton.basemodule.BaseActivity;
public class MainActivity extends BaseActivity implements OnClickListener {
private GameView gameview = null;
private Button clear = null;
private TextView tv30,tv25,tv20,tv15,tv10,tv5,tv2;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
@Override
public void initView() {
// TODO Auto-generated method stub
setContentView(R.layout.activity_main);
gameview=(GameView)findViewById(R.id.gameview);
clear =(Button)findViewById(R.id.btn_clear);
tv30=(TextView)findViewById(R.id.tv_30);
tv25=(TextView)findViewById(R.id.tv_25);
tv20=(TextView)findViewById(R.id.tv_20);
tv15=(TextView)findViewById(R.id.tv_15);
tv10=(TextView)findViewById(R.id.tv_10);
tv5=(TextView)findViewById(R.id.tv_5);
tv2=(TextView)findViewById(R.id.tv_2);
}
@Override
public void initListener() {
// TODO Auto-generated method stub
clear.setOnClickListener(this);
tv30.setOnClickListener(this);
tv25.setOnClickListener(this);
tv20.setOnClickListener(this);
tv15.setOnClickListener(this);
tv10.setOnClickListener(this);
tv5.setOnClickListener(this);
tv2.setOnClickListener(this);
}
@Override
public void initData() {
// TODO Auto-generated method stub
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v==clear){
gameview.clear();
return;
}
if(v==tv30){
gameview.setStrokeWidth(30f);
return;
}
if(v==tv25){
gameview.setStrokeWidth(25f);
return;
}
if(v==tv20){
gameview.setStrokeWidth(20f);
return;
}
if(v==tv15){
gameview.setStrokeWidth(15f);
return;
}
if(v==tv10){
gameview.setStrokeWidth(10f);
return;
}
if(v==tv5){
gameview.setStrokeWidth(5f);
return;
}
if(v==tv2){
gameview.setStrokeWidth(2f);
return;
}
}
}
五、效果
運(yùn)行效果圖如下

六、疑問
當(dāng)線條變粗時(shí),線條會(huì)出現(xiàn)如上圖中不連續(xù)的問題。請(qǐng)問高手這個(gè)怎么處理呢?我猜測應(yīng)該要運(yùn)行算法,但還不知道怎么運(yùn)行。
文章就為大家介紹到這,其實(shí)還有許多知識(shí)點(diǎn)小編也不是很清楚,希望大家可以進(jìn)行補(bǔ)充擴(kuò)展,共同進(jìn)步。
相關(guān)文章
Android 布局控件之LinearLayout詳細(xì)介紹
Android 布局控件之LinearLayout詳細(xì)介紹,需要的朋友可以參考一下2013-05-05
Android中Splash應(yīng)用啟動(dòng)白屏問題的解決方法
這篇文章主要為大家詳細(xì)介紹了Android中Splash應(yīng)用啟動(dòng)白屏問題的兩種解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Android應(yīng)用中使用ViewPager和ViewPager指示器來制作Tab標(biāo)簽
這篇文章主要介紹了Android中使用ViewPager和ViewPager指示器來制作Tab標(biāo)簽的方法,ViewPager指示器ViewPageIndicator是一個(gè)開源庫,文中舉了一個(gè)仿網(wǎng)易新聞客戶端Tab標(biāo)簽的例子,需要的朋友可以參考下2016-03-03
Android開發(fā)之底圖局部加載移動(dòng)的方法示例
這篇文章主要介紹了Android開發(fā)之底圖局部加載移動(dòng)的方法,涉及Android針對(duì)圖片與屏幕屬性的讀取、計(jì)算、設(shè)置等相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
Android基于Sqlite實(shí)現(xiàn)注冊(cè)和登錄功能
這篇文章主要為大家詳細(xì)介紹了Android基于Sqlite實(shí)現(xiàn)注冊(cè)和登錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Android使用GridView實(shí)現(xiàn)日歷的簡單功能
這篇文章主要為大家詳細(xì)介紹了Android使用GridView實(shí)現(xiàn)日歷的簡單功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
android基礎(chǔ)總結(jié)篇之二:Activity的四種launchMode
這篇文章主要介紹了android基礎(chǔ)總結(jié)篇之二:Activity的四種launchMode,有需要的可以了解一下。2016-11-11
Android貝塞爾曲線實(shí)現(xiàn)填充不規(guī)則圖形并隨手指運(yùn)動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android貝塞爾曲線實(shí)現(xiàn)填充不規(guī)則圖形,并隨手指運(yùn)動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09

