1. 程式人生 > >Android Canvas清屏失效

Android Canvas清屏失效

自定義控制元件時經常用到Canvas,畫新的東西之前需要先清除畫布內容,人臉識別專案中需要準確畫出當前人臉位置,清空上一幀位置。

關於清除畫布內容網上有兩種非常流行的方法:

方法一:

        mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
方法二:
        Paint paint = new Paint();
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mCanvas.drawPaint(paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
遺憾的是這兩種方法在我自定義的SurfaceView中都不起作用,嘗試結果如出一轍,左右晃一下 畫面如下:

我的解決方案是在每次設定Path畫線前,清空一下Path,問題迎刃而解。

清除Path中的內容有兩個方法:
reset( )不保留內部資料結構,但會保留FillType.
rewind( )會保留內部的資料結構,但不保留FillType

關於Path其他更多方法解釋詳見這篇部落格

自定義SurfaceView程式碼如下:

/**
 * Title:
 * Description:
 * Company: 北京****科技有限公司,010-62538800,[email protected]
* * @author Created by ylwang on 2018/1/30 */ public class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable { private SurfaceHolder mHolder; private Canvas mCanvas;//繪圖的畫布 private volatile boolean mIsDrawing;//控制繪畫執行緒的標誌位 private Paint mPaint; private Path mPath; public CustomSurfaceView(Context context) { super(context); initView(); } public CustomSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public CustomSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } private Gson gson; private List<FaceBean.FacesEntity> listFaces; public void setFaceInfo(String faceInfo) { FaceBean bean = gson.fromJson(faceInfo, FaceBean.class); if (null != bean && null != bean.getFaces()) { listFaces = bean.getFaces(); } } private void initView() { mPaint = new Paint(); mPaint.setColor(Color.GREEN);//畫筆顏色 mPaint.setAntiAlias(true);//抗鋸齒 mPaint.setStrokeWidth(6);//畫筆寬度 mPaint.setStyle(Paint.Style.STROKE);//空心 mPath = new Path(); mHolder = getHolder();//獲取SurfaceHolder物件 //TODO:保證該SurfaceView在最上層,避免兩個SurfaceView疊加,遮擋問題 mHolder.setFormat(PixelFormat.TRANSPARENT); setZOrderOnTop(true); mHolder.addCallback(this);//註冊SurfaceHolder的回撥方法 setFocusable(true);// 能否用鍵盤獲得焦點 setFocusableInTouchMode(true);//能否通過觸控獲得焦點 this.setKeepScreenOn(true);//螢幕常亮 gson = new Gson(); listFaces = new ArrayList<>(); } @Override public void surfaceCreated(SurfaceHolder holder) { mIsDrawing = true; new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { mIsDrawing = false; } public static final int TIME_IN_FRAME = 20; @Override public void run() { long start; while (mIsDrawing) { start = SystemClock.uptimeMillis();//開始繪製 synchronized (this) { setPathToCanvas(); } //保證穩定幀率重新整理介面 while (SystemClock.uptimeMillis() - start <= TIME_IN_FRAME) { Thread.yield();//執行緒讓出 } } } private void setPathToCanvas() { mPath.rewind();//TODO:必須重置,否則不能清屏 //mPath.reset(); // mPath = new Path(); for (FaceBean.FacesEntity face : listFaces) { int[] ps = getPositions(face.getFace_rectangle()); mPath.moveTo(ps[0], ps[1]); for (int i = 2; i < ps.length - 1; i += 2) { mPath.lineTo(ps[i], ps[i + 1]); } mPath.close();//第一個點連線到最後一個點,形成一個閉合區域 //mPath.lineTo(ps[0], ps[1]); drawSth(); } } /** * 獲取每個人臉的四點位置座標 * * @param fre * @return */ private int[] getPositions(FaceBean.FacesEntity.Face_rectangleEntity fre) { int[] faces = new int[8]; faces[0] = fre.getLeft_top().getX(); faces[1] = fre.getLeft_top().getY(); faces[2] = fre.getRight_top().getX(); faces[3] = fre.getRight_top().getY(); faces[4] = fre.getRight_bottom().getX(); faces[5] = fre.getRight_bottom().getY(); faces[6] = fre.getLeft_bottom().getX(); faces[7] = fre.getLeft_bottom().getY(); for (int i = 0; i < faces.length; i++) { faces[i] *= 2; if (i % 2 == 0) { faces[i] = (640 * 2) - faces[i]; } } return faces; } private void drawSth() { try { mCanvas = mHolder.lockCanvas(); //拿到當前畫布 然後鎖定 mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); mCanvas.drawPath(mPath, mPaint); } catch (Exception e) { e.printStackTrace(); } finally { if (mCanvas != null) { mHolder.unlockCanvasAndPost(mCanvas);//保證每次都將繪圖的內容提交 } } } }
說明一下,多個SurfaceView疊加可能會遇到的問題,請參考這篇部落格
        mHolder = getHolder();//獲取SurfaceHolder物件
        //TODO:保證該SurfaceView在最上層,避免兩個SurfaceView疊加,遮擋問題
        mHolder.setFormat(PixelFormat.TRANSPARENT);
        setZOrderOnTop(true);

相關推薦

Android Canvas失效

自定義控制元件時經常用到Canvas,畫新的東西之前需要先清除畫布內容,人臉識別專案中需要準確畫出當前人臉位置,清空上一幀位置。 關於清除畫布內容網上有兩種非常流行的方法: 方法一: mCanvas.drawColor(Color.TRANSPARENT,

解決 canvas 繪圖在高中的模糊問題

解決 canvas 繪圖在高清屏中的模糊問題 為什麼模糊 我們知道,CSS 畫素是一個抽象單位(1 px),瀏覽器根據某種規則將 css 畫素轉化為螢幕需要的實際畫素值。 在高清屏之前,螢幕上顯示一個畫素點需要 1 x 1 個 css 畫素。高清屏出現後,同樣大小的螢幕上要顯示一個點,就需要 n x 1

Android 設定禁止橫失效解決方法

    最近在處理app的介面的時候,由於當手機進行橫屏旋轉時,顯示的效果很差,故需要將橫屏的旋轉關閉。到網上查了很多的方法,網上的處理辦法主要為:在androidMainfest.xml中對activity進行橫屏限制。 具體操作方法為:<activity andr

總結的Android中surfaceView的方式。兩種。(目的是為了自己方便回顧)僅供參考。

public static void qingP() {   Canvas canvas = sh.lockCanvas(null);   canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);   Paint p = new Pa

canvas繪圖在高顯示模糊

問題:canvas在高清屏顯示模糊 前幾天在做PDF預覽時(使用mozilla的pdf.js),發現PDF文字在canvas中顯示非常模糊,在網上搜出來的中文結果都沒有這方面相關的,後面用英文搜尋到了

Canvas 在高下繪製圖片變模糊的解決方法

問題: 用canvas繪製圖片的時候會模糊,但是用img顯示的時候就不會,canvas和img的大小是相同的  至於為什麼會變模糊,這和瀏覽器處理 canvas 的方式有關,相關的文章可以參考這篇 High DPI Canvas,這裡不作深入介紹。 下面是相關的程式碼:

Python IDLE 增加功能

none ini oge python key ngs tex sta logs 保存如下代碼到 ClearWindow.py """ Clear Window Extension Version: 0.2 Author: Roger D. Serwy

Android 長截原理

ava listen near blank version package getcount recycle XML https://android-notes.github.io/2016/12/03/android%E9%95%BF%E6%88%AA%E5%B1%8F%

ANDROID N 分設置

重新 單擊 高亮 star sage 周期 拖拽 橫豎 onpause 一 概述  android N的發布,最大的亮點有2個,原生系統對應用分屏的支持和快捷回復。現在只介紹分屏功能,目前最新的Android N系統支持橫屏時讓兩個APP並排,豎屏時上下排放,而在Andro

Android中鎖密碼算法解析以及破解方案

.net water mda 介紹 數據 watermark 悲劇 ids 界面 一、前言 最近玩王者榮耀,下載了一個輔助樣本,結果被鎖機了,當然破解它很簡單,這個後面會詳細分析這個樣本,但是因為這個樣本引發出的欲望就是解析Android中鎖屏密碼算法,然後用一種高效的方式

Android canvas繪制柱形統計圖

ext.get hit 選擇 etc new 工廠模式 imp 設計模式 layout 如今非常多應用都須要一些統計圖。眼下第三方的統計圖也有非常多。可是在自己看來僅僅要不是特別耽誤時間還是選擇用canvas自己繪制比較合理。依賴於第三方的繪制在需求上也

python自帶的IDLE如何

鏈接 過程 tex alter current tor efi mar and 作者:知乎用戶 鏈接:https://www.zhihu.com/question/20917976/answer/32876441 來源:知乎 著作權歸作者所有。商業轉載請聯系作者獲得授權,非

Android最簡單幕適配,項目用dp,sp的只需加一行代碼

img use pause xtend 簡書 nth 初始 分辨 sca AutoScreenAdaptation 安卓屏幕適配 項目直接用dp和sp的可以不用改動 直接加入一句代碼即可實現適配 還未確定會不會有兼容性問題和性能問題 需要時間測試 目前測試過模擬器的不同

DOS當中的基本操作命令,如何切換磁盤,如何查看文件和文件夾,如何,進入文件夾的命令,javac是什麽意思,作用是什麽?DOS如何建文件夾?退出文件夾?

ava mpi dos compile 通配符 pil jdk 使用 onf 如何切換磁盤:使用盤符+:舉例 d: 如何查看文件和文件夾 dir/w 如何清屏: cls (clear screen) 進入文件夾的命令cd ,舉例cd JDK javac是什麽意思,c 是co

c語言、等待、隨機函數

函數 font signed 說明 b- include 利用 意義 lee 清屏函數 #include<conio.h> system("CLS");或system(cls); 等待函數 #include<windows.h> Sleep

Canvas

改變 綁定 clear map mod xfermode ear 清空 bit 當canvs與bitmap綁定時,canvas上繪制會導致bitmap改變內容,而且內容時疊加的。這時候需要清空bitmap上的內容,可以用以下做法。  Paint paint = new Pa

Android N分模式Activity生命周期的變化

preview .... 多任務 google tro reat pau 分屏 窗口大小 昨天Google發布了Android N Preview, balabala....我是用模擬器去驗證的, 通過長按多任務窗口(口)進入分屏模式, 這裏只進行了簡單的測試, 不排除通過

【轉】關於在linux下的幾種技巧

內容 可能 printf html get 技術分享 用不了 小寫 int 在windows的DOS操作界面裏面,清屏的命令是cls,那麽在linux 裏面的清屏命令是什麽呢?下面筆者分享幾種在linux下用過的清屏方法。 1、clear命令、這個命令將會刷新屏幕,本質上只

C語言函數

++ sys cls AI c++ for tdi std int Devc++ 與VC中的清屏函數 #include<stdio.h> #include<stdlib.h>//清屏函數的頭文 int main() { int i;

IDLE的GUI交互模式下完美

onf 安裝位置 modified tar undo cfg delete around === IDLE的GUI交互模式下完美清屏=======================================================================