Android简单实现画图功能

内容摘要
如何在图片上画画呢?这里写了一个demo,供大家参考

一、先看一眼工程结构

工程结构:

二、自定义view

这个自定义view实现了保留轨迹的功能,代码如下




package picturegame
文章正文

如何在图片上画画呢?这里写了一个demo,供大家参考
一、先看一眼工程结构
工程结构:

二、自定义view
这个自定义view实现了保留轨迹的功能,代码如下

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;//默认画笔颜色为红色 
   
  private float strokeWidth =2.0f;//默认画笔粗度 
   
   
 
  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); 
  } 
 
  //清除函数 
  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  设定文件 
  * @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);//设置为画线 
     
    paint.setAntiAlias(true);//可以让线条圆滑一些 
     
    paint.setColor(color);//设置画笔颜色 
     
    paint.setStrokeWidth(strokeWidth);//设置画笔线条的粗细 
  } 
   
  /** 
  * @Title: setColor 
  * @Description: TODO(设置线条颜色的对外接口) 
  * @param @param color  设定文件 
  * @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; 
    } 
     
  } 
    
} 

五、效果
运行效果图如下

六、疑问
当线条变粗时,线条会出现如上图中不连续的问题。请问高手这个怎么处理呢?我猜测应该要运行算法,但还不知道怎么运行。

文章就为大家介绍到这,其实还有许多知识点小编也不是很清楚,希望大家可以进行补充扩展,共同进步。


代码注释

作者:喵哥笔记

IDC笔记

学的不仅是技术,更是梦想!