最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

簡單實(shí)現(xiàn)Android繪圖板

 更新時(shí)間:2020年09月24日 10:56:26   作者:光仔December  
這篇文章主要教大家如何簡單實(shí)現(xiàn)Android繪圖板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文這個(gè)實(shí)例通過前面學(xué)過的Paint、Canvas等2D繪畫技術(shù)來實(shí)現(xiàn)一個(gè)簡單的Android的繪圖板。

具體實(shí)現(xiàn)代碼:

創(chuàng)建一個(gè)名為DrawView的類,該類繼承自android.view.View類。在該類中,首先定義程序中所需的屬性,然后添加構(gòu)造方法,并重寫onDraw(Canvas canvas)方法:

DrawView.java:

package com.example.test; 
 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.Path; 
import android.util.AttributeSet; 
import android.view.View; 
 
public class DrawView extends View{ 
 private int view_width=0;//屏幕的寬度 
 private int view_height=0;//屏幕的高度 
 private float preX;//起始點(diǎn)的x坐標(biāo) 
 private float preY;//起始點(diǎn)的y坐標(biāo) 
 private Path path;//路徑 
 public Paint paint;//畫筆 
 Bitmap cacheBitmap=null;//定義一個(gè)內(nèi)存中的圖片,該圖片將作為緩沖區(qū) 
 Canvas cacheCanvas=null;//定義cacheBitmap上的Canvas對象 
 /* 
 * 功能:構(gòu)造方法 
 * */ 
 public DrawView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
  
 } 
 
 /* 
 * 功能:重寫onDraw方法 
 * */ 
 @Override 
 protected void onDraw(Canvas canvas) { 
 super.onDraw(canvas); 
 
 } 
} 

創(chuàng)建布局文件,選擇幀布局,并加入上面創(chuàng)建的繼承了View的自定義畫圖控件:
res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 android:id="@+id/frameLayout1" 
 android:orientation="vertical" 
 > 
 <com.example.test.DrawView 
 android:id="@+id/drawView1" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent"/> 
</FrameLayout> 

在DrawView類的構(gòu)造方法中,首先獲取屏幕的高度和寬度,并創(chuàng)建一個(gè)與該View相同大小的緩存區(qū),然后創(chuàng)建一個(gè)新的畫面,并實(shí)例化一個(gè)路徑,再將內(nèi)存中的位圖繪制到cacheCanvas中,最后實(shí)例化一個(gè)畫筆,并設(shè)置畫筆的相關(guān)屬性。
關(guān)鍵代碼如下:

/* 
 * 功能:構(gòu)造方法 
 * */ 
 public DrawView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 view_width=context.getResources().getDisplayMetrics().widthPixels;//獲取屏幕寬度 
 view_height=context.getResources().getDisplayMetrics().heightPixels;//獲取屏幕高度 
 //創(chuàng)建一個(gè)與該View相同大小的緩存區(qū) 
 cacheBitmap=Bitmap.createBitmap(view_width,view_height,Config.ARGB_8888); 
 cacheCanvas=new Canvas();//創(chuàng)建一個(gè)新的畫布 
 path=new Path(); 
 //在cacheCanvas上繪制cacheBitmap 
 cacheCanvas.setBitmap(cacheBitmap); 
 paint=new Paint(Paint.DITHER_FLAG);//Paint.DITHER_FLAG防抖動(dòng)的 
 paint.setColor(Color.RED); 
 //設(shè)置畫筆風(fēng)格 
 paint.setStyle(Paint.Style.STROKE);//設(shè)置填充方式為描邊 
 paint.setStrokeJoin(Paint.Join.ROUND);//設(shè)置筆刷轉(zhuǎn)彎處的連接風(fēng)格 
 paint.setStrokeCap(Paint.Cap.ROUND);//設(shè)置筆刷的圖形樣式(體現(xiàn)在線的端點(diǎn)上) 
 paint.setStrokeWidth(1);//設(shè)置默認(rèn)筆觸的寬度為1像素 
 paint.setAntiAlias(true);//設(shè)置抗鋸齒效果 
 paint.setDither(true);//使用抖動(dòng)效果 
 } 

在DrawView類的onDraw()方法中,添加以下代碼,用于設(shè)置背景顏色、繪制cacheBitmap、繪制路徑以及保存當(dāng)前繪圖狀態(tài)到棧中,并調(diào)用restore()方法恢復(fù)所保存的狀態(tài),關(guān)鍵代碼如下:

/* 
 * 功能:重寫onDraw方法 
 * */ 
 @Override 
 protected void onDraw(Canvas canvas) { 
 super.onDraw(canvas); 
 canvas.drawColor(0xFFFFFFFF);//設(shè)置背景色 
 Paint bmpPaint=new Paint();//采用默認(rèn)設(shè)置創(chuàng)建一個(gè)畫筆 
 canvas.drawBitmap(cacheBitmap, 0, 0,bmpPaint);//繪制cacheBitmap 
 canvas.drawPath(path, paint);//繪制路徑 
 canvas.save(Canvas.ALL_SAVE_FLAG);//保存canvas的狀態(tài) 
 //恢復(fù)canvas之前保存的狀態(tài),防止保存后對canvas執(zhí)行的操作對后續(xù)的繪制有影響 
 canvas.restore(); 
 } 

在Draw類中,重寫onTouchEvent()方法,為該視圖添加觸摸事件監(jiān)聽器,在該方法中,首先獲取觸摸事件發(fā)生的位置,然后用switch語句對事件的不同狀態(tài)添加響應(yīng)代碼,最后調(diào)用invalidate()方法更新視圖。具體代碼如下:

@Override 
 public boolean onTouchEvent(MotionEvent event) { 
 //獲取觸摸事件發(fā)生的位置 
 float x=event.getX(); 
 float y=event.getY(); 
 switch(event.getAction()){ 
  case MotionEvent.ACTION_DOWN: 
  //將繪圖的起始點(diǎn)移到(x,y)坐標(biāo)點(diǎn)的位置 
  path.moveTo(x, y); 
  preX=x; 
  preY=y; 
  break; 
  case MotionEvent.ACTION_MOVE: 
  //保證橫豎繪制距離不能超過625 
  float dx=Math.abs(x-preX); 
  float dy=Math.abs(y-preY); 
  if(dx>5||dy>5){ 
   //.quadTo貝塞爾曲線,實(shí)現(xiàn)平滑曲線(對比lineTo) 
   //x1,y1為控制點(diǎn)的坐標(biāo)值,x2,y2為終點(diǎn)的坐標(biāo)值 
   path.quadTo(preX, preY, (x+preX)/2, (y+preY)/2); 
   preX=x; 
   preY=y; 
  } 
  break; 
  case MotionEvent.ACTION_UP: 
  cacheCanvas.drawPath(path, paint);//繪制路徑 
  path.reset(); 
  break; 
 } 
 invalidate(); 
 return true;//返回true,表明處理方法已經(jīng)處理該事件 
 } 

編寫clear()方法,用于實(shí)現(xiàn)橡皮擦功能,具體代碼如下:

public void clear(){ 
 //設(shè)置圖形重疊時(shí)的處理方式 
 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 
 //設(shè)置筆觸的寬度 
 paint.setStrokeWidth(50); 
 } 

編寫保存當(dāng)前繪圖的save方法,在該方法中,調(diào)用saveBitmap()方法將當(dāng)前繪圖保存為PNG圖片。save()方法的具體代碼如下:

public void save(){ 
 try{ 
  saveBitmap("myPitcture"); 
 }catch(IOException e){ 
  e.printStackTrace(); 
 } 
  
 } 

編寫保存繪制好的位圖的方法saveBitmap(),在該方法中,首先在SD卡上創(chuàng)建一個(gè)文件,然后創(chuàng)建一個(gè)文件輸出流對象,并調(diào)用Bitmap類的compress()方法將繪圖內(nèi)容壓縮為PNG格式輸出到剛剛創(chuàng)建的文件輸出流對象中,最后將緩沖區(qū)的數(shù)據(jù)全部寫出到輸出流中,并關(guān)閉文件輸出流對象。saveBitmap()方法的具體代碼如下:

private void saveBitmap(String fileName) throws IOException { 
 File file=new File(getSDPath()+fileName+".png"); 
 file.createNewFile(); 
 FileOutputStream fileOS=new FileOutputStream(file); 
 //將繪圖內(nèi)容壓縮為PNG格式輸出到輸出流對象中 
 cacheBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOS); 
 fileOS.flush();//將緩沖區(qū)中的數(shù)據(jù)全部寫出到輸出流中 
 fileOS.close();//關(guān)閉文件輸出流對象 
 } 
 
 //獲得SD卡的根目錄 
 public String getSDPath(){ 
  File sdDir = null; 
  boolean sdCardExist = Environment.getExternalStorageState() 
    .equals(android.os.Environment.MEDIA_MOUNTED); //判斷sd卡是否存在 
 
  if (sdCardExist) //如果SD卡存在,則獲取跟目錄 
  {     
  sdDir = Environment.getExternalStorageDirectory();//獲取跟目錄 
  } 
  return sdDir.toString(); 
  
 } 

在程序中需要向SD卡上保存文件,那么需要在AndroidManifest.xml文件中賦予相應(yīng)的權(quán)限,具體代碼入下:

<!-- 執(zhí)行SD卡檢查的權(quán)限 --> 
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 
<!-- SD卡寫入權(quán)限 --> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

在res目錄中,創(chuàng)建一個(gè)menu目錄,并在該目錄中創(chuàng)建一個(gè)名稱為toolsmenu.xml的菜單資源文件,在該文件中編寫實(shí)例中所應(yīng)用的功能菜單,關(guān)鍵代碼如下:

<?xml version="1.0" encoding="utf-8"?> 
<menu xmlns:android="http://schemas.android.com/apk/res/android" > 
 <item android:title="@string/color"> 
 <menu> 
  <!-- 定義一組單選菜單項(xiàng) --> 
  <group android:checkableBehavior="single"> 
  <!-- 定義子菜單 --> 
  <item android:id="@+id/red" android:title="@string/color_red"/> 
  <item android:id="@+id/green" android:title="@string/color_green"/> 
  <item android:id="@+id/blue" android:title="@string/color_blue"/> 
  </group> 
 </menu> 
 </item> 
 <item android:title="@string/width"> 
 <menu> 
  <!-- 定義子菜單 --> 
  <group> 
  <item android:id="@+id/width_1" android:title="@string/width_1"/> 
  <item android:id="@+id/width_2" android:title="@string/width_2"/> 
  <item android:id="@+id/width_3" android:title="@string/width_3"/> 
  </group> 
 </menu> 
 </item> 
 <item android:id="@+id/clear" android:title="@string/clear"/> 
 <item android:id="@+id/save" android:title="@string/save"/> 
</menu> 

其中values/strings.xml中:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
 
 <string name="app_name">test</string> 
 <string name="hello_world">Hello world!</string> 
 <string name="action_settings">Settings</string> 
 <string name="color">畫筆顏色</string> 
 <string name="color_red">紅色</string> 
 <string name="color_green">綠色</string> 
 <string name="color_blue">藍(lán)色</string> 
 <string name="width">畫筆寬度</string> 
 <string name="width_1">細(xì)</string> 
 <string name="width_2">中</string> 
 <string name="width_3">粗</string> 
 <string name="clear">擦除繪畫</string> 
 <string name="save">保存繪畫</string> 
 
</resources> 

在默認(rèn)創(chuàng)建的MainActivity中,為實(shí)例添加選項(xiàng)菜單。
首先,重寫onCreatOptionsMenu()方法,在該方法中,實(shí)例化一個(gè)MenuInflater對象,并調(diào)用該對象的inflate方法解析toolsmenu.xml的菜單資源文件。具體代碼如下:

/* 
 * 創(chuàng)建選項(xiàng)菜單 
 * */ 
 @Override 
 public boolean onCreateOptionsMenu(Menu menu) { 
 MenuInflater inflator=new MenuInflater(this); 
 inflator.inflate(R.menu.toolsmenu, menu); 
 return super.onCreateOptionsMenu(menu); 
 } 

然后,重寫onOptionsItemSelected方法,分別對各個(gè)菜單項(xiàng)被選擇時(shí)做出相應(yīng)的處理,具體代碼如下:

/* 
 * 當(dāng)菜單項(xiàng)被選擇時(shí),做出相應(yīng)的處理 
 * */ 
 @Override 
 public boolean onOptionsItemSelected(MenuItem item) { 
 //獲取自定義的繪圖視圖 
 DrawView dv=(DrawView)findViewById(R.id.drawView1); 
 dv.paint.setXfermode(null);//取消擦除效果 
 dv.paint.setStrokeWidth(1);//初始化畫筆的寬度 
 switch(item.getItemId()){ 
  case R.id.red: 
  dv.paint.setColor(Color.RED);//設(shè)置筆的顏色為紅色 
  item.setChecked(true); 
  break; 
  case R.id.green: 
  dv.paint.setColor(Color.GREEN);//設(shè)置筆的顏色為綠色 
  item.setChecked(true); 
  break; 
  case R.id.blue: 
  dv.paint.setColor(Color.BLUE);//設(shè)置筆的顏色為藍(lán)色 
  item.setChecked(true); 
  break; 
  case R.id.width_1: 
  dv.paint.setStrokeWidth(1);//設(shè)置筆觸的寬度為1像素 
  break; 
  case R.id.width_2: 
  dv.paint.setStrokeWidth(5);//設(shè)置筆觸的寬度為5像素 
  break; 
  case R.id.width_3: 
  dv.paint.setStrokeWidth(10);//設(shè)置筆觸的寬度為10像素 
  break; 
  case R.id.clear: 
  dv.clear();//擦除繪畫 
  break; 
  case R.id.save: 
  dv.save();//保存繪畫 
  break; 
 } 
 return true; 
 } 

運(yùn)行效果如圖

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解ListView中多種item的實(shí)現(xiàn)方式

    詳解ListView中多種item的實(shí)現(xiàn)方式

    這篇文章主要給大家介紹了關(guān)于ListView中多種item的實(shí)現(xiàn)方式,文中通過示例代碼介紹的很詳細(xì),有需要的朋友們可以參考借鑒,下面來一起看看吧。
    2016-12-12
  • Android通過XListView實(shí)現(xiàn)上拉加載下拉刷新功能

    Android通過XListView實(shí)現(xiàn)上拉加載下拉刷新功能

    這篇文章主要為大家詳細(xì)介紹了Android通過XListView實(shí)現(xiàn)上拉加載下拉刷新功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Android 實(shí)現(xiàn)徹底退出自己APP 并殺掉所有相關(guān)的進(jìn)程

    Android 實(shí)現(xiàn)徹底退出自己APP 并殺掉所有相關(guān)的進(jìn)程

    這篇文章主要介紹了Android 實(shí)現(xiàn)徹底退出自己APP 并殺掉所有相關(guān)的進(jìn)程,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android應(yīng)用內(nèi)存泄漏優(yōu)化指南

    Android應(yīng)用內(nèi)存泄漏優(yōu)化指南

    內(nèi)存泄漏(Memory Leak)是指應(yīng)用中不再使用的對象因錯(cuò)誤引用無法被垃圾回收(GC),導(dǎo)致內(nèi)存占用持續(xù)增長,最終可能引發(fā) OOM(Out Of Memory)崩潰?或 應(yīng)用卡頓,以下是 Android 內(nèi)存泄漏的優(yōu)化方案,涵蓋檢測工具、常見場景及解決方案,需要的朋友可以參考下
    2025-03-03
  • Android震動(dòng)與提示音實(shí)現(xiàn)代碼

    Android震動(dòng)與提示音實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了Android震動(dòng)與提示音實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Android View如何繪制

    Android View如何繪制

    要了解View如何繪制,就需要了解canvas(畫布)是什么?paint(畫筆)能夠做什么,想要深入了解的朋友可以參考一下
    2016-05-05
  • Android自制九宮格解鎖控件

    Android自制九宮格解鎖控件

    這篇文章主要為大家詳細(xì)介紹了Android自制九宮格解鎖控件的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Android實(shí)現(xiàn)倒計(jì)時(shí)結(jié)束后跳轉(zhuǎn)頁面功能

    Android實(shí)現(xiàn)倒計(jì)時(shí)結(jié)束后跳轉(zhuǎn)頁面功能

    最近在工作中遇到一個(gè)需求,需要在倒計(jì)時(shí)一段時(shí)間后進(jìn)行跳轉(zhuǎn)頁面,通過查找相關(guān)資料發(fā)現(xiàn)其中涉及的知識(shí)還不少,所以分享出來,下面這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)倒計(jì)時(shí)結(jié)束后跳轉(zhuǎn)頁面功能的相關(guān)資料,需要的朋友可以參考下。
    2017-11-11
  • Android Dialog對話框?qū)嵗a講解

    Android Dialog對話框?qū)嵗a講解

    本文通過實(shí)例代碼給大家介紹了Android Dialog對話框的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-08-08
  • Android實(shí)現(xiàn)ViewFlipper圖片動(dòng)畫滑動(dòng)

    Android實(shí)現(xiàn)ViewFlipper圖片動(dòng)畫滑動(dòng)

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)ViewFlipper圖片動(dòng)畫滑動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05

最新評論

垫江县| 丹巴县| 当涂县| 晴隆县| 建瓯市| 苏州市| 航空| 昭苏县| 囊谦县| 平谷区| 万山特区| 呼玛县| 霍城县| 广宁县| 湖南省| 延吉市| 盘锦市| 延安市| 开封市| 富蕴县| 长垣县| 三江| 南平市| 陵川县| 成都市| 介休市| 兴国县| 革吉县| 长汀县| 九龙县| 印江| 辽宁省| 林州市| 云南省| 石城县| 阳西县| 华坪县| 科技| 枣强县| 通辽市| 朝阳县|