### Android應用界面 ###
- 視圖組件與容器組件
- Android 應用的絕大部分UI 組件都放在android. widget 包及其子包、android.view 包及其子包中, Android 應用的所有UI 組件都繼承了View 類
- View 類還有一個重要的子類: ViewGroup , 但ViewGroup 通常主要作為其他組件的容器使用。但由ViewGroup 是一個抽象類,因此實際使用中通常總是使用ViewGroup的子類來作為容器,例如各種布局管理器。
- Android 的所有UI 組件都是建立在View 、VtewGroup 基礎之上的, Android 采用了“組合器”設計模式來設計View 和ViewGroup: ViewGroup 是View 的子類,因此ViewGroup 也可被當成View 使用。對于一個Android 應用的圖形用戶界面來說, ViewGroup 作為容器來盛裝其他組件, 而ViewGroup 里除了可以包含普通View 組件之外, 還可以再次包含VtewGroup 組件。
- Android 推薦使用XML布局文件來定義用戶界面,而不是使用Java 代碼來開發用戶界面;大部分時候,控制UI組件的XML 屬性都有對應的方法。如果希望在代碼中控制UI界面, 那么所有UI組件都將通過new 關鍵字創建出來, 然后以合適的方式“ 搭建” 在一起即可。
- ViewGroup 容器控制其子.組件的分布依賴于ViewGroup.LayoutParams、ViewGroup.MarginLayoutParams 兩個內部類。
- ViewGroup.LayoutParams 所支持的兩個XML 屬性。
- android: layout_ height、android:layout_ wid由兩個屬性
- VtewGroup.MarginLayoutParams 用于控制子組件周圍的頁邊距( Margin, 也就是組件四周的留自〉,XML文件中屬性為android: layout_ marginBottom、android: layout_ marginLeft、android: layout_ marginRight、android:layout_marginTop
- 自定義view
android在繪制view前,也必須對view進行測量,即告訴系統該畫一個多大的view,該過程是在onMeasure()方法中進行,測量好一個view ,就可以在界面繪制相應的圖像,就必須在Canvas上進行繪制,Canvas就像是一個畫板,使用Paint就可以在畫板上作畫,這通常需要通過繼承View并重寫onDraw()方法;而且,在自定義view時,通常會重寫onDraw()方法來繪制view顯示的內容,如果該view還需要wrap_content屬性,那么必須重寫onMeasure()方法,另外,通過自定義attrs屬性,還可以設置新的屬性配置值。
- 通常需要重寫的方法
- 構造器: 重寫構造器是定制View 的最基本方式, 當Java 代碼創建一個View 實例,或根據XML布局文件加載并構建界面時將需要調用該構造器。
- onFinishInflate():這是一個回調方法,當應用從XML布局文件加載該組件并利用它來構建界面之后,該方法將會被回調。
- onMeasure(int,int:調用該方法來檢測View 組件及其所包含的所有子組件的大小。
- onLayout(boolean, int,int,int,int):當該組件需要分配其子組件的位置、大小時,該方法就會被回調。
- onSizeChanged(int,int,int,int): 當該組件的大小被改變時回調該方法。
- onDraw(Canvas): 當該組件將要繪制它的內容時回調該方法進行繪制。
- onKeyDown(int,KeyEvent): 當某個鍵被按下時觸發該方法。
- onKeyUp(int, KeyEvent): 當松開某個鍵時觸發該方法。
- onTrackballEvent(MotionEvent): 當發生軌跡球事件時觸發該方法。
- onTouchEvent(MotionEvent): 當發生觸摸屏事件時觸發該方法。
- onFocusChanged(boolean gain Focus, int direction, Rect previouslyFocusedRect):當該組件焦點發生改變時觸發該方法。
- onWindowFocusChanged(boolean): 當包含該組件的窗口失去或得到焦點時觸發該方法。
- onAttachedToWindow(): 當把該組件放入某個窗口時觸發該方法。
- onDetachedFromWindow(): 當把該組件從某個窗口上分離時觸發該方法。
- onWindowVisibilityChanged(int): 當包含該組件的窗口的可見性發生改變時觸發該方法。
ps:以上的方法,并不是所有的方法都需要重寫,根據業務需要重寫部分方法即可
- 自定義View三種情況
1. 對現有控件進行拓展
- 在原生控件的基礎上進行拓展,增加新的功能,修改顯示的UI等,一般可以再onDraw()方法中對原生控件行為進行拓展
- 程序在調用`super.onDraw(canvas);`來實現原生控件的功能,但是在調用`super.onDraw(canvas);`之前和之后,都可以實現自己的邏輯,比如自定義一個拓展于原生的TextView的TextView,如下代碼
```
@Override
protected void onDraw(Canvas canvas) {
//在回調父類方法前,實現自己的邏輯,對TextView 來說即是在繪制文本內容前
super.onDraw(canvas);
//在回調父類方法前,實現自己的邏輯,對TextView 來說即是在繪制文本內容后
}
```
2. 通過組合來實現新的控件
- 這種方式通常需要繼承一個合適的ViewGroup,再給它添加指定功能的控件,從而組合成新的復合控件。這種方式創建的控件,一般我們給它指定一些可配置的屬性,讓它具有更強的拓展性;為一個View 提供可自定義的屬性非常簡單,只需要在res 資源目錄的values 目錄下創建一個attrs.xmll 的屬性定義文件,并在該文件中通過相應的代碼定義相應的屬性即可。即:只需要在res 資源目錄的values 目錄下創建一個attrs.xmll 的屬性定義文件,并在該文件中通過相應的代碼定義相應的屬性即可。在代碼中通過<declare-styleable>標簽聲月了使用了自定義屬性,并通過name 屬性來確定引用的名稱。最后,通過<attr〉標簽來聲明具體的自定義屬性
3. 重寫View來實現全新的控件
- 創建一個全新的自定義View了,難點在于繪制控制控件和實現交互,通常需要繼承View類,并重寫它的onDraw()、onMeasure()等方法實現繪制邏輯,同時通過重寫onTouchEvent()等觸控事件來實現交互邏輯,還可以引入自定義屬性,豐富自定義View的可定制性。
- 自定義viewGroup
- ViewGroup 存在的目的就是為了對其子View 進行管理,為其子View 添加顯示、響應的規則。因此,自定義ViewGroup 通常需要重寫onMeasure()方法來對子View 進行測量,重寫onLayout()方法來確定子View 的位置,重寫onTouchEvent()方法增加響應事件。
- 布局管理器

- 從上圖 可以看出, 所有布局都可作為容器類使用, 因此可以調用多個重載的addViewO 向布局管理器中添加組件。實際上, 我們完全可以用一個布局管理器嵌套到其他布局管理器中一一因為布局管理器也繼承了View , 也可以作為普通UI 組件使用。
- 線性布局
- Android 的線性布局不會換行,當組件一個挨著一個地排列到頭之后, 剩下的組件將不會被顯示出來。
- 使用9patch圖片作為背景
- 為什么用9patch圖片?
- 當按鈕的內容太多或者按鈕寬度為match_content填充父布局,或者按鈕的背景圖片的大小和按鈕定義的寬度高度大小不匹配時, Android 會自動縮放整張圖片,以保證背景圖片能覆蓋整個按鈕。但這種縮放整張圖片的效果可能并不好。可能存在的情況是我們只想縮放圖片中某個部分, 這樣才能保證按鈕的視覺效果。
- 作用:實現只縮放圖片中某個部分的效果
- 介紹
- 9Patch 圖片是一種特殊的PNG圖片, 這種圖片以.9 .png 結尾, 它在原始圖片四周各添加一個寬度為1像素的線條,這4 條線就決定了該圖片的縮放規則、內容顯示規則。
- 左側和上側的直線共同決定了圖片的縮放區域: 以左邊直線為左邊界繪制矩形, 它覆蓋的區域可以在縱向上縮放; 以上面直線為上邊界繪制矩形,它覆蓋的區域可以水平縮放; 它們二者的交集可以在兩個方向上縮放。下圖中的四周粉色的小矩形區域就是圖片縮放區域。、

- 右側和下側的直線共同決定圖片的內容顯示區域: 以右邊直線為右邊界繪制矩形,以下邊直線為下邊界繪制矩形, 它們二者的交集就是圖片的內容顯示區域。下圖中的紫色的文本矩形局域就是圖片的內容顯示區域的示意圖。

- 
- XML Nine-Patch
- 一個XML Nine-Patch是一種在XML中定義的資源,指向一個Nine-Patch文件。XML可以為圖像指定抖動。
- 文件位置:res/drawable/filename.xml
- 語法
- 、
- xmlns:android----字符串。必備。定義 XML 命名空間,其必須是 `"http://schemas.android.com/apk/res/android"。`
- android:src----可繪制對象資源。必備。引用九宮格文件。
- android:dither----布爾值。當位圖的像素配置與屏幕不同時(例如:ARGB 8888 位圖和 RGB 565 屏幕),啟用或停用位圖抖動。
- 前言
- Android系統的體系結構
- Dalvik VM 和 JVM 的比較
- Android 打包應用程序并安裝的過程
- Android ADB工具
- Android應用開發
- Android UI相關知識總結
- Android 中window 、view、 Activity的關系
- Android應用界面
- Android中的drawable和bitmap
- AndroidUI組件adapterView及其子類和Adapter的關系
- Android四大組件
- Android 數據存儲
- SharedPreference
- Android應用的資源
- 數組資源
- 使用Drawable資源
- Material Design
- Android 進程和線程
- 進程
- 線程
- Android Application類的介紹
- 意圖(Intent)
- Intent 和 Intent 過濾器(Google官網介紹)
- Android中關于任務棧的總結
- 任務和返回棧(官網譯文)
- 總結
- Android應用安全現狀與解決方案
- Android 安全開發
- HTTPS
- 安卓 代碼混淆與打包
- 動態注入技術(hook技術)
- 一、什么是hook技術
- 二、常用的Hook 工具
- Xposed源碼剖析——概述
- Xposed源碼剖析——app_process作用詳解
- Xposed源碼剖析——Xposed初始化
- Xposed源碼剖析——hook具體實現
- 無需Root也能Hook?——Depoxsed框架演示
- 三、HookAndroid應用
- 四、Hook原生應用程序
- 五、Hook 檢測/修復
- Android 應用的逆向與加固保護技術
- OpenCV在Android中的開發
- Android高級開發進階
- 高級UI
- UI繪制流程及原理
- Android新布局ConstraintLayout約束布局
- 關鍵幀動畫
- 幀動畫共享元素變換
- Android異步消息處理機制完全解析,帶你從源碼的角度徹底理解
- Android中為什么主線程不會因為Looper.loop()里的死循環卡死?
- 為什么 Android 要采用 Binder 作為 IPC 機制?
- JVM 中一個線程的 Java 棧和寄存器中分別放的是什么?
- Android源碼的Binder權限是如何控制?
- 如何詳解 Activity 的生命周期?
- 為什么Android的Handler采用管道而不使用Binder?
- ThreadLocal,你真的懂了嗎?
- Android屏幕刷新機制