中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

android繪制,android繪制人像輪廓

android繪圖之Paint(1)

Paint 講解開篇

創(chuàng)新互聯(lián)從2013年成立,先為德州等服務(wù)建站,德州等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為德州企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

android中繪制特定圖案類似顯示中的繪畫需要畫筆和畫紙,為此android提供了Paint和Canvas。

Paint和Canvas分別代表畫筆和畫布。

The Paint class holds the style and color information about how to draw geometries, text and bitmaps.

Paint類似畫筆,保存著繪制文本,圖形,圖片的樣式和顏色信息。(顏色,寬度,粗細(xì),透明度,字體樣式,字體大?。?。

提供了三種初始化方法:

Paint(),

Paint(int flags),

Paint(Paint paint)。

第二種構(gòu)造函數(shù)傳入了flag,相當(dāng)于無參構(gòu)造之后調(diào)用了setFlags(int),有很多種flag,這里舉個(gè)例子UNDERLINE_TEXT_FLAG(其他的flag見developers文檔),繪制文字時(shí)會(huì)有下劃線,多個(gè)flag或可以達(dá)到設(shè)置多個(gè)flag的目的。

Paint常用的設(shè)置函數(shù):

setAlpha()透明度

setAntiAlias()抗鋸齒

setColor(),setARGB()設(shè)置顏色

setStyle(Paint.Style style) 設(shè)置填充樣式

setStrokeCap(Paint.Cap cap) 畫筆的樣式(落筆,收筆時(shí))

setStrokeJoin(Paint.Join join)連接點(diǎn)的樣式

setStrokeWidth(float width)設(shè)置畫筆寬度

setShadowLayer(float radius, float dx, float dy, int shadowColor) 設(shè)置陰影

setTextSize(float textSize) 字體大小

setTextAlign(Paint.Align.RIGHT)設(shè)置字體對(duì)齊方式

后期講解:

setColorFilter(ColorFilter filter) 設(shè)置顏色過濾

setUnderlineText(true) 下劃線

setPathEffect() 設(shè)置路徑效果

setTypeface() 設(shè)置字體風(fēng)格

setFilterBitmap() 設(shè)置圖片過濾

setXfermode(Xfermode xfermode) xfermode設(shè)置圖像混合模式

setShader(Shader shader) 設(shè)置shader包括漸變shader,圖片shader

。。。。。。。。

setAlpha(int a) 設(shè)置透明度,a 值得范圍 [0..255],僅僅改變setColor()的顏色的透明度,不改變顏色值,0是完全透明,255完全不透明。

注意:需要先調(diào)用setColor(),再調(diào)用setAlpha才會(huì)生效,否則將會(huì)被覆蓋,因?yàn)閟etColor中包含了alpha。

setStyle設(shè)置填充樣式,所謂填充的樣式指只繪制線或者繪制同時(shí)填充:

Paint.Style.FILL 填充內(nèi)部,會(huì)把閉合區(qū)域填充顏色

Paint.Style.FILL_AND_STROKE 填充內(nèi)部和描邊

Paint.Style.STROKE 僅描邊,僅僅繪制邊界

默認(rèn)FILL 填充內(nèi)部,

STROKE樣式

FILL_AND_STROKE樣式和FILL 類似但當(dāng)畫筆寬度很寬時(shí)會(huì)產(chǎn)生不同

setColor,setARGB設(shè)置顏色,設(shè)置畫筆的顏色,setARGB()參數(shù)范圍0-255。

setAntiAlias(boolean) 抗鋸齒,使邊界更順滑(有些屏幕分辨率不高,導(dǎo)致像素點(diǎn)比較大,繪制邊界可能會(huì)有顆粒感,打開抗鋸齒邊界顆粒感會(huì)減少)。

setTextSize(float textSize) 字體大小,單位是px,如果是dp要注意轉(zhuǎn)換。

setTextAlign(Paint.Align.RIGHT)設(shè)置字體對(duì)齊方式,根據(jù)下面的實(shí)例可以,對(duì)齊方式基于開始繪制的點(diǎn)。

一起講解:

mPaint.setTextSize(50);

mPaint.setTextAlign(Paint.Align.LEFT);

canvas.drawText("android Paint 學(xué)習(xí) LEFT",300,300,mPaint);

mPaint.setTextAlign(Paint.Align.CENTER);

canvas.drawText("android Paint 學(xué)習(xí) CENTER",300,400,mPaint);

mPaint.setTextAlign(Paint.Align.RIGHT);

canvas.drawText("android Paint 學(xué)習(xí) RIGHT",300,500,mPaint);

setTextAlign對(duì)齊是相對(duì)于開始繪制的坐標(biāo)點(diǎn)。

setShadowLayer(float radius, float dx, float dy, int shadowColor) 設(shè)置陰影

mPaint.setShadowLayer(10,-20,30,Color.GRAY);

canvas.drawText("android Paint 學(xué)習(xí) CENTER",getWidth()/2,450,mPaint);

setShadowLayer(float radius, float dx, float dy, int shadowColor)

Radius設(shè)置角度,dx,dy控制字體的上下左右出現(xiàn),有正負(fù)之分,dx的正負(fù)代表右左,dy的正負(fù)代表下上。

setStrokeCap(Paint.Cap.ROUND)

設(shè)置繪制起始點(diǎn)和結(jié)尾點(diǎn)的樣式,

三種樣式ROUND,BUTT,SQUARE

Cap.ROUND(圓形)、Cap.SQUARE(方形)、Paint.Cap.BUTT(無)

ROUND:

BUTT和SQUARE差別不大:

setStrokeJoin(Paint.Join join),設(shè)置繪制path連接點(diǎn)的樣式

mPaint.setStrokeJoin(Paint.Join.ROUND);

// mPaint.setStrokeJoin(Paint.Join.MITER);

// mPaint.setStrokeJoin(Paint.Join.BEVEL);

Join.MITER(結(jié)合處為銳角)、

Join.Round(結(jié)合處為圓弧)、

Join.BEVEL(結(jié)合處為直線)

ROUND樣式:

MITER樣式:

BEVEL樣式:

setXfermode(Xfermode xfermode) xfermode設(shè)置圖像混合模式

setShader(Shader shader) 設(shè)置shader包括漸變shader,圖片shader

還有很多其他屬性會(huì)后續(xù)講解。

android繪圖之Paint(1)

android繪圖之Canvas基礎(chǔ)(2)

Android繪圖之Path(3)

Android繪圖之drawText繪制文本相關(guān)(4)

Android繪圖之Canvas概念理解(5)

Android繪圖之Canvas變換(6)

Android繪圖之Canvas狀態(tài)保存和恢復(fù)(7)

Android繪圖之PathEffect (8)

Android繪圖之LinearGradient線性漸變(9)

Android繪圖之SweepGradient(10)

Android繪圖之RadialGradient 放射漸變(11)

Android繪制之BitmapShader(12)

Android繪圖之ComposeShader,PorterDuff.mode及Xfermode(13)

Android繪圖之drawText,getTextBounds,measureText,FontMetrics,基線(14)

Android繪圖之貝塞爾曲線簡(jiǎn)介(15)

Android繪圖之PathMeasure(16)

Android 動(dòng)態(tài)修改漸變 GradientDrawable

五、Android繪制知識(shí)總結(jié)(Xfermode和硬件加速)

Xfermode表示圖層的混合模式,用于描述兩個(gè)圖層之間進(jìn)行融合時(shí),像素點(diǎn)進(jìn)行計(jì)算的規(guī)則。

在API16之前,Xfermode有3個(gè)子類:AvoidXfermode、PixelXorXfermode、PorterDuffXfermode。但在API16以后,前兩個(gè)已經(jīng)過時(shí),甚至從源碼里移除,所以我們只需學(xué)習(xí) PorterDuffXfermode 即可。

PorterDuffXfermode 最早是在1984年由Porter和Duff兩人發(fā)表的論文《Compositing Digital Images》中出現(xiàn),所以該混合模式也根據(jù)作者來命名。

PorterDuffXfermode 構(gòu)造函數(shù)需要指定一個(gè) PorterDuff.Mode ,而PorterDuff.Mode在以下地方都會(huì)涉及:

它提供18種模式可選項(xiàng):

各種模式下的效果如下圖所示:

這里可以發(fā)現(xiàn),兩種效果是不一樣的,谷歌官方給的是第一種,但是,通常情況應(yīng)該是第二種,具體原因可 參考該文章 。比如我們畫一個(gè)矩形,應(yīng)該按第二種效果來考慮,因?yàn)樵磮D和目標(biāo)圖大小不一致;如果畫相同大小的Bitmap,則按第一種做。

在實(shí)際應(yīng)用中,我們可以從以下三個(gè)方面來決定使用哪種模式:

1、沒有硬件加速:

invalidate the view hierarchy ------ draw the view hierarchy

2、有硬件加速:

invalidate the view hierarchy ------ record and update the display list ------ draw the display list

1、繪制不正確:可能使用了不支持硬件加速的操作, 需要關(guān)閉硬件加速或者繞過該操作

2、拋出異常:可能使用了不支持硬件加速的操作, 需要關(guān)閉硬件加速或者繞過該操作

在Android系統(tǒng)中,有4個(gè)不同級(jí)別的打開或者關(guān)閉硬件加速操作:

1、Application級(jí)別:

application android:hardwareAccelerated="false"

默認(rèn)為true,用于控制這個(gè)app是否開啟硬件加速。

2、Activity級(jí)別:

activity android:hardwareAccelerated="false"

3、Window級(jí)別:(只支持開啟操作)

getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

4、View級(jí)別:(只支持關(guān)閉操作)

view.setLayerType(View.LAYER_TYPE_HARDWARE, null);

LAYER_TYPE_HARDWARE ,使用硬件加速(GPU)進(jìn)行繪制

LAYER_TYPE_SOFTWARE ,使用CPU進(jìn)行繪制

或者布局文件中,指定以下屬性:

android:layerType="software"

1、view.isHardwareAccelerated()

如果返回true,表示view掛在一個(gè)開啟了硬件加速的Window之下,也就意味著,它在繪制時(shí),并不一定開啟了硬件加速。

2、canvas.isHardwareAccelerated()

如果返回true,因?yàn)橹鴆anvas在繪制的時(shí)候啟用了硬件加速,盡量采用此方法來判斷是否開啟了硬件加速。

Android - View 繪制流程

我們知道,在 Android 中,View 繪制主要包含 3 大流程:

Android 中,主要有兩種視圖: View 和 ViewGroup ,其中:

雖然 ViewGroup 繼承于 View ,但是在 View 繪制三大流程中,某些流程需要區(qū)分 View 和 ViewGroup ,它們之間的操作并不完全相同,比如:

對(duì) View 進(jìn)行測(cè)量,主要包含兩個(gè)步驟:

對(duì)于第一個(gè)步驟,即求取 View 的 MeasureSpec ,首先我們來看下 MeasureSpec 的源碼定義:

MeasureSpec 是 View 的一個(gè)公有靜態(tài)內(nèi)部類,它是一個(gè) 32 位的 int 值,高 2 位表示 SpecMode(測(cè)量模式),低 30 位表示 SpecSize(測(cè)量尺寸/測(cè)量大?。?/p>

MeasureSpec 將兩個(gè)數(shù)據(jù)打包到一個(gè) int 值上,可以減少對(duì)象內(nèi)存分配,并且其提供了相應(yīng)的工具方法可以很方便地讓我們從一個(gè) int 值中抽取出 View 的 SpecMode 和 SpecSize。

一個(gè) MeasureSpec 表達(dá)的是:該 View 在該種測(cè)量模式(SpecMode)下對(duì)應(yīng)的測(cè)量尺寸(SpecSize)。其中,SpecMode 有三種類型:

對(duì) View 進(jìn)行測(cè)量,最關(guān)鍵的一步就是計(jì)算得到 View 的 MeasureSpec ,子View 在創(chuàng)建時(shí),可以指定不同的 LayoutParams (布局參數(shù)), LayoutParams 的源碼主要內(nèi)容如下所示:

其中:

LayoutParams 會(huì)受到父容器的 MeasureSpec 的影響,測(cè)量過程會(huì)依據(jù)兩者之間的相互約束最終生成子View 的 MeasureSpec ,完成 View 的測(cè)量規(guī)格。

簡(jiǎn)而言之,View 的 MeasureSpec 受自身的 LayoutParams 和父容器的 MeasureSpec 共同決定( DecorView 的 MeasureSpec 是由自身的 LayoutParams 和屏幕尺寸共同決定,參考后文)。也因此,如果要求取子View 的 MeasureSpec ,那么首先就需要知道父容器的 MeasureSpec ,層層逆推而上,即最終就是需要知道頂層View(即 DecorView )的 MeasureSpec ,這樣才能一層層傳遞下來,這整個(gè)過程需要結(jié)合 Activity 的啟動(dòng)過程進(jìn)行分析。

我們知道,在 Android 中, Activity 是作為視圖組件存在,主要就是在手機(jī)上顯示視圖界面,可以供用戶操作, Activity 就是 Andorid 中與用戶直接交互最多的系統(tǒng)組件。

Activity 的基本視圖層次結(jié)構(gòu)如下所示:

Activity 中,實(shí)際承載視圖的組件是 Window (更具體來說為 PhoneWindow ),頂層View 是 DecorView ,它是一個(gè) FrameLayout , DecorView 內(nèi)部是一個(gè) LinearLayout ,該 LinearLayout 由兩部分組成(不同 Android 版本或主題稍有差異): TitleView 和 ContentView ,其中, TitleView 就是標(biāo)題欄,也就是我們常說的 TitleBar 或 ActionBar , ContentView 就是內(nèi)容欄,它也是一個(gè) FrameLayout ,主要用于承載我們的自定義根布局,即當(dāng)我們調(diào)用 setContentView(...) 時(shí),其實(shí)就是把我們自定義的布局設(shè)置到該 ContentView 中。

當(dāng) Activity 啟動(dòng)完成后,最終就會(huì)渲染出上述層次結(jié)構(gòu)的視圖。

因此,如果我們要求取得到子View 的 MeasureSpec ,那么第一步就是求取得到頂層View(即 DecorView )的 MeasureSpec 。大致過程如下所示:

經(jīng)過上述步驟求取得到 View 的 MeasureSpec 后,接下來就可以真正對(duì) View 進(jìn)行測(cè)量,求取 View 的最終測(cè)量寬/高:

Android 內(nèi)部對(duì)視圖進(jìn)行測(cè)量的過程是由 View#measure(int, int) 方法負(fù)責(zé)的,但是對(duì)于 View 和 ViewGroup ,其具體測(cè)量過程有所差異。

因此,對(duì)于測(cè)量過程,我們分別對(duì) View 和 ViewGroup 進(jìn)行分析:

綜上,無論是對(duì) View 的測(cè)量還是 ViewGroup 的測(cè)量,都是由 View#measure(int widthMeasureSpec, int heightMeasureSpec) 方法負(fù)責(zé),然后真正執(zhí)行 View 測(cè)量的是 View 的 onMeasure(int widthMeasureSpec, int heightMeasureSpec) 方法。

具體來說, View 直接在 onMeasure(...) 中測(cè)量并設(shè)置自己的最終測(cè)量寬/高。在默認(rèn)測(cè)量情況下, View 的測(cè)量寬/高由其父容器的 MeasureSpec 和自身的 LayoutParams 共同決定,當(dāng) View 自身的測(cè)量模式為 LayoutParams.UNSPECIFIED 時(shí),其測(cè)量寬/高為 android:minWidth / android:minHeight 和其背景寬/高之間的較大值,其余情況皆為自身 MeasureSpec 指定的測(cè)量尺寸。

而對(duì)于 ViewGroup 來說,由于布局特性的豐富性,只能自己手動(dòng)覆寫 onMeasure(...) 方法,實(shí)現(xiàn)自定義測(cè)量過程,但是總的思想都是先測(cè)量 子View 大小,最終才能確定自己的測(cè)量大小。

當(dāng)確定了 View 的測(cè)量大小后,接下來就可以來確定 View 的布局位置了,也即將 View 放置到屏幕具體哪個(gè)位置。

View 的布局過程由 View#layout(...) 負(fù)責(zé),其源碼如下:

View#layout(...) 主要就做了兩件事:

ViewGroup 的布局流程由 ViewGroup#layout(...) 負(fù)責(zé),其源碼如下:

可以看到, ViewGroup#layout(...) 最終也是通過 View#layout(...) 完成自身的布局過程,一個(gè)注意的點(diǎn)是, ViewGroup#layout(...) 是一個(gè) final 方法,因此子類無法覆寫該方法,主要是 ViewGroup#layout(...) 方法內(nèi)部對(duì)子視圖動(dòng)畫效果進(jìn)行了相關(guān)設(shè)置。

由于 ViewGroup#layout(...) 內(nèi)部最終調(diào)用的還是 View#layout(...) ,因此, ViewGroup#onLayout(...) 就會(huì)得到回調(diào),用于處理 子View 的布局放置,其源碼如下:

由于不同的 ViewGroup ,其布局特性不同,因此 ViewGroup#onLayout(...) 是一個(gè)抽象方法,交由 ViewGroup 子類依據(jù)自己的布局特性,擺放其 子View 的位置。

當(dāng) View 的測(cè)量大小,布局位置都確定后,就可以最終將該 View 繪制到屏幕上了。

View 的繪制過程由 View#draw(...) 方法負(fù)責(zé),其源碼如下:

其實(shí)注釋已經(jīng)寫的很清楚了, View#draw(...) 主要做了以下 6 件事:

我們知道,在 Activity 啟動(dòng)過程中,會(huì)調(diào)用到 ActivityThread.handleResumeActivity(...) ,該方法就是 View 視圖繪制的起始之處:

可以看到, ActivityThread.handleResumeActivity(...) 主要就是獲取到當(dāng)前 Activity 綁定的 ViewManager ,最后調(diào)用 ViewManager.addView(...) 方法將 DecorView 設(shè)置到 PhoneWindow 上,也即設(shè)置到當(dāng)前 Activity 上。 ViewManager 是一個(gè)接口, WindowManager 繼承 ViewManager ,而 WindowManagerImpl 實(shí)現(xiàn)了接口 WindowManager ,此處的 ViewManager.addView(...) 實(shí)際上調(diào)用的是 WindowManagerImpl.addView(...) ,源碼如下所示:

WindowManagerImpl.addView(...) 內(nèi)部轉(zhuǎn)發(fā)到 WindowManagerGlobal.addView(...) :

在 WindowManagerGlobal.addView(...) 內(nèi)部,會(huì)創(chuàng)建一個(gè) ViewRootImpl 實(shí)例,然后調(diào)用 ViewRootImpl.setView(...) 將 ViewRootImpl 與 DecorView 關(guān)聯(lián)到一起:

ViewRootImpl.setView(...) 內(nèi)部首先關(guān)聯(lián)了傳遞過來的 DecorView (通過屬性 mView 指向 DecorView 即可建立關(guān)聯(lián)),然后最終調(diào)用 requestLayout() ,而 requestLayout() 內(nèi)部又會(huì)調(diào)用方法 scheduleTraversals() :

ViewRootImpl.scheduleTraversals() 內(nèi)部主要做了兩件事:

Choreographer.postCallback(...) 會(huì)申請(qǐng)一次 VSYNC 中斷信號(hào),當(dāng) VSYNC 信號(hào)到達(dá)時(shí),便會(huì)回調(diào) Choreographer.doFrame(...) 方法,內(nèi)部會(huì)觸發(fā)已經(jīng)添加的回調(diào)任務(wù), Choreographer 的回調(diào)任務(wù)有以下四種類型:

因此, ViewRootImpl.scheduleTraversals(...) 內(nèi)部通過 mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null) 發(fā)送的異步視圖渲染消息就會(huì)得到回調(diào),即回調(diào) mTra

分享名稱:android繪制,android繪制人像輪廓
鏈接分享:http://www.rwnh.cn/article32/dscojpc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄外貿(mào)建站、定制開發(fā)定制網(wǎng)站、網(wǎng)站設(shè)計(jì)微信公眾號(hào)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名
河池市| 砚山县| 伽师县| 扶余县| 古田县| 应用必备| 贵定县| 禹州市| 中牟县| 济南市| 石门县| 怀安县| 台北市| 乐平市| 昌图县| 门源| 吉首市| 山东省| 易门县| 甘泉县| 南江县| 衡水市| 阿城市| 彩票| 江门市| 宿松县| 镇原县| 满洲里市| 泰安市| 石渠县| 甘洛县| 绥宁县| 兴安盟| 色达县| 定陶县| 佛坪县| 东源县| 闽清县| 珲春市| 保康县| 高雄县|