Android简单实现画图功能

所属分类: 软件编程 / Android 阅读数: 1039
收藏 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网络编程之获取网络上的Json数据实例

这篇文章主要介绍了Android网络编程之获取网络上的Json数据实例,本文用完整的代码实例讲解了在Android中读取网络中Json数据的方法,需要的朋友可以参考下
收藏 0 赞 0 分享

Android中的windowSoftInputMode属性详解

这篇文章主要介绍了Android中的windowSoftInputMode属性详解,本文对windowSoftInputMode的9个属性做了详细总结,需要的朋友可以参考下
收藏 0 赞 0 分享

Android网络编程之UDP通信模型实例

这篇文章主要介绍了Android网络编程之UDP通信模型实例,本文给出了服务端代码和客户端代码,需要的朋友可以参考下
收藏 0 赞 0 分享

Android中使用ListView实现漂亮的表格效果

这篇文章主要介绍了Android中使用ListView实现漂亮的表格效果,本文用详细的代码实例创建了一个股票行情表格,需要的朋友可以参考下
收藏 0 赞 0 分享

Android中刷新界面的二种方法

这篇文章主要介绍了Android中刷新界面的二种方法,本文使用Handler、postInvalidate两种方法实现界面刷新,需要的朋友可以参考下
收藏 0 赞 0 分享

Android SDK三种更新失败及其解决方法

这篇文章主要介绍了Android SDK三种更新失败及其解决方法,需要的朋友可以参考下
收藏 0 赞 0 分享

Android学习笔记——Menu介绍(一)

Android3.0(API level 11)开始,Android设备不再需要专门的菜单键。随着这种变化,Android app应该取消对传统6项菜单的依赖。取而代之的是提供anction bar来提供基本的用户功能
收藏 0 赞 0 分享

Android学习笔记——Menu介绍(二)

这次将继续上一篇文章没有讲完的Menu的学习,上下文菜单(Context menu)和弹出菜单(Popup menu)
收藏 0 赞 0 分享

Android学习笔记——Menu介绍(三)

今天继续昨天没有讲完的Menu的学习,主要是Popup Menu的学习,需要的朋友可以参考下
收藏 0 赞 0 分享

Android显示网络图片实例

这篇文章主要介绍了Android显示网络图片的方法,以实例形式展示了Android程序显示网络图片的方法,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多