阿里面試官;Android自定義View你都知道嗎?

鏈接:https://juejin.im/post/5e54e2de5188254945386529

阿里面試官;Android自定義View你都知道嗎?

前言

View,有很多的名稱。不論是你熟知的佈局,還是控件,他們全部都繼承自View。

阿里面試官;Android自定義View你都知道嗎?

文內部分圖片轉載自Carson_Ho大佬的文章

思維導圖

阿里面試官;Android自定義View你都知道嗎?

工作流程

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系統的座標系和平時畫的座標系並不相同。

阿里面試官;Android自定義View你都知道嗎?

所以相對應的,我們的位置計算方法自然和我們原來的正好是相反的。

阿里面試官;Android自定義View你都知道嗎?

4個頂點的位置分別由4個值決定:

  • top:子View上邊界到所在容器上邊界的距離。
  • left:子View左邊界到所在容器左邊界的距離。
  • bottom:子View下邊界到所在容器上邊界的距離。
  • right:子View右邊界到所在容器左邊界的距離。

所有的計算都是相對於所在容器才能夠開始的。

draw

一共有6個步驟:

  1. 如果需要,則繪製背景 --drawBackground(canvas);
  2. 保存當前canvas層 --saveCount = canvas.getSaveCount();
  3. 繪製View的內容 --if (!dirtyOpaque) onDraw(canvas);
  4. 繪製子View --dispatchDraw(canvas);
  5. 如果需要,則繪製View的褪色邊緣,類似於陰影效果 --canvas.restoreToCount(saveCount);
  6. 繪製裝飾,比如滾動條 --
    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"這樣標籤,其實他就是用來引入我們自定義的標籤使用的。

  1. 在res/values目錄下創建attrs
<code>
/<code>
  1. 在DefaultView(Context context, @Nullable AttributeSet attrs)中獲取。以下是整個完整代碼。
<code>/**
/<code>

基礎的性能優化

首先的話我們先了解如何去知道一個View是否被過度繪製了?

其實在我們手機中的開發模式已經存在這個選項了。

開啟前開啟後

阿里面試官;Android自定義View你都知道嗎?

阿里面試官;Android自定義View你都知道嗎?

下方給出繪製的次數對應圖

阿里面試官;Android自定義View你都知道嗎?

那如何做到性能優化呢?

在這個問題之前,需要了解什麼是過度繪製,你可以理解為同一位置的控件不斷的疊加而產生的無用數據,那我們就來說說集中解決方案吧。

方案1:減少嵌套層數。

使用線性佈局 | 使用約束佈局 |

阿里面試官;Android自定義View你都知道嗎?

阿里面試官;Android自定義View你都知道嗎?

因為只是一個案例,想說的意思,如果多個LinearLayout嵌套實現的效果,如果能被一個ConstraintLayout直接實現,那麼就用後者替代,因為不會這樣在同一個區域重複出現。

方案2:去除默認的背景

阿里面試官;Android自定義View你都知道嗎?

這個解決方案其實針對的背景會被自動繪製的問題,如果我們把這個層次消去,從繪製角度老說也是一種提升了。正如圖示一般直接減少了一層的繪製。

在代碼中的具體表現,通過對****style.xml中的Theme進行修改:

<code><item>@null/<item>
/<code>

總結

阿里面試官;Android自定義View你都知道嗎?


以上就是我的學習成果,如果有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。


分享到:


相關文章: