「條條大路通羅馬。」工做中,實現某個需求的方式每每不是惟一的,這些不一樣實現方式不只表如今代碼質量上,還影響着咱們的工做效率。就像,在 Android 系統中,總有那麼一些不爲人知的 API 可以減小咱們不少零碎的工做量。因而,就想憑着一些經驗,整理一些經常使用的,找個地方概括總結,也供往後翻閱。html
根據資源名稱獲取資源 id。正常狀況下,咱們會在代碼中直接根據資源ID獲取資源,好比:java
getResources().getDrawable(R.drawable.ic_launcher);複製代碼
但有時候,資源並非固定的,須要根據使用狀況從多個同類資源中動態選擇,好比根據服務器傳遞給客戶端的接口數據動態設置,怎麼辦呢?設置一個硬編碼的映射關係數組?太繁瑣!不妨用上這個方法。android
一個完整的資源名爲package:type/entry
,對應該方法的三個參數:資源名稱、資源類型、應用包名。舉幾個例子:程序員
imageView.setImageResource(getResources().getIdentifier("ic_launcher", "drawable", getPackageName()));
radioGroup.check(getResources().getIdentifier("rb_indicator_" + position, "id", getPackageName()));複製代碼
實際使用過程當中,第一個參數 name,也就是資源名稱,根據須要動態設置,這就須要多個資源在命名時保持必定的規範格式。另外,須要注意的是,直接經過 id 獲取資源比經過名字的方式效率更高,因此,若是沒有這般特殊需求的話,不提倡使用這個方法獲取資源。web
使用頻率超高的字符串判空方法,返回一個 boolean 值,內部實現的判斷條件爲:str == null || str.length() == 0
。備受開發人員喜好的一個 if 字符串判斷,系統已經幫咱們封裝過。正則表達式
解析 Html 格式的富文本內容,並返回一個帶樣式的字符串,供 TextView 等控件顯示。能夠解決一些含超連接、圖文混排等格式的富文本內容的顯示問題。算法
利用 Android SDK 提供的這個日期工具類能夠將 long 類型的毫秒級時間數據格式化成特定顯示格式的字符串。一般咱們使用 Java SDK 中的 SimpleDateFormat
格式化日期數據,好比 new SimpleDateFormat("yyyy-MM-dd HH:mm").format()
,DateUtils
的做用就是替咱們封裝了這個過程。格式化結果與當前設備的本地語言環境有關。這裏列舉幾個經常使用 format 格式(中文環境下):canvas
格式化文件大小,將字節數據格式化爲 B、KB、M 等單位的相應數據。context 參數用於判斷返回結果的字符串順序,right-to-left 仍是 left-to-right 形式的。這個工具類免去咱們本身轉化計算的過程,很是方便,特別適用於應用內文件下載的相似場景。數組
將指定單位的尺寸數據按照當前設備屏幕信息轉化爲相應的像素值。其中,TypedValue 爲第一個參數提供了經常使用的單位值,好比:安全
源碼以下:
public static float applyDimension(int unit, float value, DisplayMetrics metrics){
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}複製代碼
其實在實際使用過程當中,像素值都是 int 整數類型,而該方法返回的是 float 類型,若是直接強制轉換的話,會自動捨去小數部分。因此,若是不用該方法的話,一般咱們會這麼轉換:
public static int convertDipToPx(Context context, int dip) {
float scale = context.getResources().getDisplayMetrics().density;
// 0.5f 用於向上取整
return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));
}複製代碼
官方註釋以下:
Space is a lightweight View subclass that may be used to create gaps between components in general purpose layouts.
Space 是一個用於建立視圖之間空隙的輕量級 View。在 onDraw() 方法中不執行任何繪製,因此 android:background
屬性對他來講不起做用。一般咱們使用 View 建立視圖間的空隙,在不考慮背景色的狀況下,Space 其實效率更高。注意,因爲是 API 14 引入的控件,若是須要向前兼容的話,須要使用到 support v4 包。
自動調用 View 點擊事件。一般按鈕等控件只有在用戶點擊時才能觸發其點擊事件,該方法能夠由某些特殊條件觸發模擬用戶點擊行爲。相似的還有 performLongClick()
方法。
Log
類提供的一個公共靜態方法,與常見的 Log.i()
等方法打印日誌到 logcat 控制檯不一樣的是,該方法從 Throwable 對象中獲取錯誤信息,並以字符串的形式返回。當你須要作錯誤信息的數據持久化,好比保存至本地存儲卡中或者上傳至服務器時,利用這個方法就很是方便。
咱們知道對於 TextView 文本控件中的內容,經過 android:autoLink
屬性能夠爲其添加諸如 web、phone 等固定模版的超連接點擊事件。但畢竟系統模版有限,而利用 Linkify.addLinks()
方法能夠添加一些應用內自定義模版,好比新浪微博中的 "@XXX" 格式的超連接跳轉等,均可以經過自定義正則表達式來匹配處理。
設置安全窗口,禁用系統截屏。防止 App 中的一些界面被截屏,並顯示在其餘設備中形成信息泄漏。(常見手機設備系統截屏操做方式爲:同時按下電源鍵和音量鍵。)
好比支付寶 App 的「向商家付款」的包含付款二維碼的界面。(補充說明一點,微信付款界面不是這麼作的,採用的是在 onResume() 生命週期方法中實時刷新付款二維碼,與支付寶在安全方法採起的手段不一樣。)
@Override
public void onBackPressed() {
Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
launcherIntent.addCategory(Intent.CATEGORY_HOME);
startActivity(launcherIntent);
}複製代碼
使用 Back 鍵返回桌面,但不關閉當前應用,而是使之進入後臺,就像按下 Home 鍵同樣。
這個技巧厲害了。一般爲了防止出現用戶誤按 Back 鍵退出 App 的狀況,咱們會在應用首頁的 Activity 中監聽返回鍵操做,使用 Toast 弱提示甚至 Dialog 強提示的方式給到用戶一個再次確認的操做,但沒法阻止用戶經過返回鍵逐步關閉應用。
然而,若是用這個方法攔截 App 最後一個 Activity(常見爲首頁界面),既沒有阻礙用戶操做(回到桌面),又沒有關閉掉咱們的應用(後臺運行中),間接提升 App 的存活時間,真乃暗度陳倉。而且據我實驗,微信、支付寶、微博等 App 都是這麼作的,你們不妨一試。
縮略圖工具類,能夠根據本地視頻文件源、Bitmap 對象生成縮略圖,經常使用的公共靜態方法爲:
從源 bitmap 中根據 alpha 獲取一個新的 bitmap 對象。比較繞口,一般 App 中的 Icon 多數是純色透明像素背景組成,利用這個方法能夠對該圖的非透明區域着色,有多種使用場景,常見如 Button 的 pressed 狀態,View 的陰影狀態等。舉個例子:
private static Bitmap getDropShadow(ImageView iv, Bitmap src, float radius, int color) {
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
final int width = src.getWidth(), height = src.getHeight();
final Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(dest);
final Bitmap alpha = src.extractAlpha();
canvas.drawBitmap(alpha, 0, 0, paint);
final BlurMaskFilter filter = new BlurMaskFilter(radius, BlurMaskFilter.Blur.OUTER);
paint.setMaskFilter(filter);
canvas.drawBitmap(alpha, 0, 0, paint);
iv.setImageBitmap(dest);
return dest;
}複製代碼
系統提供的一個 TypeEvaluator ,咱們只須要提供兩個起始顏色值和一個分值,系統會經過特定的算法計算得出一個新的顏色中間值。利用這個類,咱們至少能夠作兩件事情。
第一,用於屬性動畫中。因爲其實現了 TypeEvaluator
接口,能夠用來作自定義屬性動畫的求值器,改變 View 的顯示狀態。好比:
int colorStart = ContextCompat.getColor(this, R.color.black);
int colorEnd = ContextCompat.getColor(this, R.color.green);
ValueAnimator valueAnimator = ValueAnimator
.ofObject(new ArgbEvaluator(), colorStart, colorEnd)
.setDuration(3000);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
textView.setTextColor((Integer) animation.getAnimatedValue());
}
});
valueAnimator.start();複製代碼
第二,利用該類提供的顏色求值算法,配合 ViewPager
提供的滑動偏離值使用。這種場景常見於使用 ViewPager
實現的引導頁,其背景色隨着滑動距離動態改變;使用 ViewPager
實現的 Tab 樣式菜單頁面,Tab 中文本內容隨着滑動距離動態改變字體顏色(能夠參考安卓版微信)。這兩種使用都使得 ViewPager
頁面切換過渡得很天然,體驗極佳。如:
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
new ArgbEvaluator().evaluate(positionOffset, startColor, endColor);
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});複製代碼
另外,關於顏色差值的計算,Google Sample 裏有另外一種算法,可參考 SlidingTabStrip.java 文件源碼,核心方法內容以下:
/** * Blend {@code color1} and {@code color2} using the given ratio. * * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, * 0.0 will return {@code color2}. */
private static int blendColors(int color1, int color2, float ratio) {
final float inverseRation = 1f - ratio;
float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
return Color.rgb((int) r, (int) g, (int) b);
}複製代碼
用於 LinearLayout
中,用於設置 Children weight 的總比重。在 LinearLayout
的 children 中,咱們常常會使用 android:layout_weight
按比例分配容器佈局的空間,但有時候不必定會分完。以往,有些朋友可能會使用一個空
用於 ViewGroup 中,解決做爲 Parent 的 ViewGroup 與 Children View 之間的焦點佔用問題。最最多見的使用場景就是 list item 中含有一些點擊效果的控件,好比 Button、CheckBox 等,相信你們都遇到過。取值有三種,含義就不用再多說了:
是否將 View 自身的 drawable state 交給直接 parent ViewGroup 控制,值爲 boolean 類型。好比有一個 item 佈局,item 中有一個 button,若是點擊 item layout 時,須要 button 呈現對應的點擊效果,就能夠在 button 中用到這個屬性。不過,從設計的角度來說,這種場景仍是比較少見的。知道有這個屬性就好,不推薦這種交互設計。
ScrollView 的一個屬性,用於設置內容部分是否填滿屏幕,主要針對內容不足以填滿屏幕的狀況。這裏推薦一個使用技巧,參考我以前寫的文章:Android 平常開發中,兩個很是實用的佈局技巧。
使用 ImageView 時,你可能會用 android:scaleType
屬性設置圖片縮放方式。卻不知,android:adjustViewBounds
屬性也能起到相似的效果。但要注意的是,後者須要至少指定 ImageView 寬高中的一個屬性,或者 maxHeight 之類的,而後另外一個屬性隨之適配。這個屬性用在列表中較爲合適,好比 App 中的活動列表頁面,圖片寬度設置爲 match_parent,而後高度設爲 wrap_content 使其自適應,這樣便能保證從服務獲取的高分辨率圖片在不一樣的屏幕中不被拉伸變形。(備註:最好在項目資源文件中放置一個與網絡圖片相同尺寸的默認圖,起到 placeholder 做用,避免圖片顯示前高度爲 0 的較差體驗。)
本文先記這麼多吧,日積月累,後續持續更新中,敬請關注...(固然,你有什麼高效而又少見的 API,歡迎一塊兒分享交流哦~)
安卓筆記俠:專一於 Android 開發,和程序員之路。