Android简单实现画图功能

所属分类: 软件编程 / Android 阅读数: 1016
收藏 0 赞 0 分享

如何在图片上画画呢?这里写了一个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; 
    } 
     
  } 
    
} 

五、效果
运行效果图如下

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

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

更多精彩内容其他人还在看

老生常谈Android HapticFeedback(震动反馈)

下面小编就为大家带来一篇老生常谈Android HapticFeedback(震动反馈)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详谈OnTouchListener与OnGestureListener的区别

下面小编就为大家带来一篇详谈OnTouchListener与OnGestureListener的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Android仿知乎悬浮功能按钮FloatingActionButton效果

前段时间在看属性动画,恰巧这个按钮的效果可以用属性动画实现,下面通过本文给大家分享adroid仿知乎悬浮功能按钮FloatingActionButton效果,需要的朋友参考下吧
收藏 0 赞 0 分享

解决Android V7后自定义Toolbar、ActionBar左侧有空白问题

这篇文章主要介绍的Android V7后自定义Toolbar、ActionBar左侧有空白问题的解决方法,需要的朋友可以参考下
收藏 0 赞 0 分享

Android常见控件使用详解

这篇文章主要为大家详细介绍了Android常见控件的使用方法,包括ProgressBar进度条控件、AlertDialog对话框控件等,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android实现简洁的APP更新dialog数字进度条

这篇文章主要为大家详细介绍了Android实现简洁的APP更新dialog数字进度条,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android 判断当前语言环境是否是中文环境

本文主要介绍了Android 判断当前语言环境是否是中文环境的方法。具有很好的参考价值。下面跟着小编一起来看下吧
收藏 0 赞 0 分享

详谈Android中Matrix的set、pre、post的区别

下面小编就为大家带来一篇详谈Android中Matrix的set、pre、post的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Android实现登录界面记住密码的存储

这篇文章主要为大家详细介绍了Android SharedPreferrences实现登录界面记住密码的存储,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android 使用SharedPreferrences储存密码登录界面记住密码功能

Android存储方式有很多种,在这里所用的存储方式是SharedPreferrences, 其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,下面通过实例代码给大家讲解下,需要的朋友参考下吧
收藏 0 赞 0 分享
查看更多