鏈接:https://juejin.im/post/5e54e2de5188254945386529
前言
View,有很多的名稱。不論是你熟知的佈局,還是控件,他們全部都繼承自View。
文內部分圖片轉載自Carson_Ho大佬的文章
思維導圖
工作流程
measure
其實通過layout中的第二張圖我們已經知道了控件大小的計算了。
- height = bottom - top
- width = right - left
對於ViewGroup而言,就是對容器內子控件的遍歷和計算了。
因為直接繼承自View的控件使用wrap_cotent和match_parent是顯示出來的效果是相同的。需要我們使用MeasureSpec中的getMode()方法來對當前的模式進行區分和比較。
模式狀態UNSPECIFIED未指定模式,View想多大就多大,父容器不做限制,一般用於系統內部的測量AT_MOST最大模式,對應wrap_content,View的大小不大於SpecSize的值EXACTLY精確模式,對應match_parent,View的大小為SpecSize的值
<code>@Override
/<code>
layout
在確定位置時,我們有一個非常需要主要的地方—— 座標系。
Android系統的座標系和平時畫的座標系並不相同。
所以相對應的,我們的位置計算方法自然和我們原來的正好是相反的。
4個頂點的位置分別由4個值決定:
- top:子View上邊界到所在容器上邊界的距離。
- left:子View左邊界到所在容器左邊界的距離。
- bottom:子View下邊界到所在容器上邊界的距離。
- right:子View右邊界到所在容器左邊界的距離。
所有的計算都是相對於所在容器才能夠開始的。
draw
一共有6個步驟:
- 如果需要,則繪製背景 --drawBackground(canvas);
- 保存當前canvas層 --saveCount = canvas.getSaveCount();
- 繪製View的內容 --if (!dirtyOpaque) onDraw(canvas);
- 繪製子View --dispatchDraw(canvas);
- 如果需要,則繪製View的褪色邊緣,類似於陰影效果 --canvas.restoreToCount(saveCount);
- 繪製裝飾,比如滾動條 -- onDrawForeground(canvas);
關於開發者需要重寫的方法一般是第三步繪製View的內容對應的onDraw()。
<code>private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
/<code>
入門自定義View
在日常項目的佈局文件中我們經常會使用到xmlns:app="http://schemas.android.com/apk/res-auto"這樣標籤,其實他就是用來引入我們自定義的標籤使用的。
- 在res/values目錄下創建attrs
<code>
/<code>
- 在DefaultView(Context context, @Nullable AttributeSet attrs)中獲取。以下是整個完整代碼。
<code>/**
/<code>
基礎的性能優化
首先的話我們先了解如何去知道一個View是否被過度繪製了?
其實在我們手機中的開發模式已經存在這個選項了。
開啟前開啟後
下方給出繪製的次數對應圖
那如何做到性能優化呢?
在這個問題之前,需要了解什麼是過度繪製,你可以理解為同一位置的控件不斷的疊加而產生的無用數據,那我們就來說說集中解決方案吧。
方案1:減少嵌套層數。
使用線性佈局 | 使用約束佈局 |
因為只是一個案例,想說的意思,如果多個LinearLayout嵌套實現的效果,如果能被一個ConstraintLayout直接實現,那麼就用後者替代,因為不會這樣在同一個區域重複出現。
方案2:去除默認的背景
這個解決方案其實針對的背景會被自動繪製的問題,如果我們把這個層次消去,從繪製角度老說也是一種提升了。正如圖示一般直接減少了一層的繪製。
在代碼中的具體表現,通過對****style.xml中的Theme進行修改:
<code><item>@null/<item>
/<code>
總結
以上就是我的學習成果,如果有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。
閱讀更多 架構師的搖籃 的文章