Android API相容,其他API,UI適配(------ 分割線 -----)

desaco發表於2018-12-16

Android XML shape 標籤使用詳解- http://www.cnblogs.com/popfisher/p/6238119.html

shape寫line虛線的時候發現4.0以上機型很多都沒辦法顯示,後來在xml中 android:layerType="software"  
line.setLayerType(View.LAYER_TYPE_SOFTWARE, null);  

- GradientDrawable
GradientDrawable, API小於16的時候,需要使用GradientDrawable的帶參建構函式;API大於16的時候,直接呼叫相關方法就行了。
//TODO:判斷版本是否大於16  專案中預設的都是Linear散射 都是從左到右 都是隻有開始顏色和結束顏色
        GradientDrawable drawable;
        if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
        {
            drawable=new GradientDrawable();
            drawable.setOrientation(GradientDrawable.Orientation.LEFT_RIGHT);
            drawable.setColors(colors);
        }else{
            drawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
        }

/**
     *
     * @param drawable 生成的背景
     * @param view 需要新增背景的View
     */
    public static void setBackground(GradientDrawable drawable,View view)
    {
        //判斷當前版本號,版本號大於等於16,使用setBackground;版本號小於16,使用setBackgroundDrawable。
        if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
        {
            view.setBackground(drawable);
        }else{
            view.setBackgroundDrawable(drawable);
        }
    }

-- gridView的getVerticalSpacing() getColumnWidth()
 一個流暢的拖動排序DragSortGridView,自動滾屏- https://blog.csdn.net/u013147734/article/details/51577246
gridView.getVerticalSpacing()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    totalHeight += listItem.getMeasuredHeight() + gridView.getVerticalSpacing(); // 統計所有子項的總高度
                } else {
                    totalHeight += listItem.getMeasuredHeight();
                }


public int getColumnWidth(){
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) return super.getColumnWidth();
        else{
            try{
                Field field = GridView.class.getDeclaredField("mColumnWidth");
                field.setAccessible(true);
                Integer value = (Integer) field.get(this);
                field.setAccessible(false);
                return value.intValue();
            }catch(NoSuchFieldException e){
                throw new RuntimeException(e);
            }catch(IllegalAccessException e){
                throw new RuntimeException(e);
            }
        }
    }

-- 橫豎屏切換時候Activity的生命週期的總結- https://blog.csdn.net/wulianghuan/article/details/8603982
android:screenOrientation="landscape" 強制橫屏;
android:screenOrientation="portrait" 強制豎屏;

- TaskStackBuilder  API level16(4.1);4.0對應API是:14.

— //MediaCodeC是Android 4.1(API16 ) 版本加入的一個新的音視訊處理API
"video/x-vnd.on2.vp8" - VP8 video (i.e. video in .webm) 
"video/x-vnd.on2.vp9" - VP9 video (i.e. video in .webm) 
"video/avc" - H.264/AVC video 
"video/hevc" - H.265/HEVC video 
"video/mp4v-es" - MPEG4 video 
"video/3gpp" - H.263 video 
"audio/3gpp" - AMR narrowband audio 
"audio/amr-wb" - AMR wideband audio 
"audio/mpeg" - MPEG1/2 audio layer III 
"audio/mp4a-latm" - AAC audio (note, this is raw AAC packets, not packaged in LATM!) 
"audio/vorbis" - vorbis audio 
"audio/g711-alaw" - G.711 alaw audio 
"audio/g711-mlaw" - G.711 ulaw audio

-- android音訊 資料格式pcm流8位和16位的相互轉換-https://blog.csdn.net/tklwj/article/details/80352065
  8位PCM 編碼每個聲音取樣點用8bit來表示,16位PCM 編碼每個聲音取樣點用16bit表示。因為16位PCM編碼的取樣精度更高,所以音質好一些,但8位PCM 編碼所使用的資料量小一半,所以更容易儲存和傳輸。
  8位PCM編碼常用於電話等通訊電路,取樣速率8k,節省傳輸頻寬。16位PCM 編碼常用於電腦多媒體聲音檔案,取樣速率44.1K,音質好。
  為了提高訊雜比,8位PCM編碼動態壓縮技術,也就是說非線性量化,對小訊號取樣級數更多,壓縮方法有A率和u率兩種,中國和歐洲用A率,美國用U率。8位PCM 編碼播放的時候也要解壓縮成16位pcm播放。

-- ||的使用
||,當使用||(短路或)時,若前面的表示式結果為真,則程式不會再執行後面的表示式,直接得出TRUE的結果。
捕獲異常:try catch。

-- WifiP2pManager 4.0, 4.0以上。
Android WiFi P2P開發實踐筆記-https://www.jianshu.com/p/e9a23dfda330
WifiP2p Service Discovery是安卓4.0增加的功能,只需要開啟wifi就可以,不必要事先連線區域網或建立熱點。
WifiP2pManager等類,建立連線後傳輸檔案就用到Socket。

-- GradientDrawable
 arg1.setBackgroundColor(Color.parseColor("#87CEFA"));
 我們平常需要為一個控制元件設定background屬性,直接用"控制元件.setBackground()"就可以了。但是有的時候會遇到這種情況:需要為控制元件動態的設定shape,你可以建立多個shape的drawable,這當然算是一種思路。這此我想提供另一種思路:
 GradientDrawable gd = textView.getBackground();
 gd.setColor(Color.parseColor("#333333");

//在程式碼中動態設定背景
//新建一個Drawable物件
GradientDrawable drawable=new GradientDrawable();
//設定背景色
drawable.setColor(Color.rgb(255,0,0));
//設定邊框的厚度以及邊框的顏色
drawable.setStroke(1,Color.rgb(0,0,0));
//設定圓角的半徑  當然也是可以一個個設定圓角的半徑
drawable.setCornerRadius(20);
//設定背景的形狀,預設就是矩形,跟xml檔案中型別android:shape的值保持一致,具體有:GradientDrawable.LINE  GradientDrawable.OVAL GradientDrawable.RECTANGLE  GradientDrawable.RING
drawable.setShape(GradientDrawable.RECTANGLE);

//實現背景漸變的效果
GradientDrawable drawable;
        //API大於等於16
        if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
        {
            drawable=new GradientDrawable();
            //倆設定方法其實就是對應著帶參構造引數的那倆引數
            drawable.setOrientation(GradientDrawable.Orientation.LEFT_RIGHT);
            drawable.setColors(colors);
        }else{
            drawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
        }

        drawable.setCornerRadii(radius);
        drawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);

— Android6.0+解決getColor()方法過時
public static final int getColor(Context context, @ColorRes int id) {
        final int version = Build.VERSION.SDK_INT;
        if (version >= 23) {
            return ContextCompatApi23.getColor(context, id);
        } else {
            return context.getResources().getColor(id);
        }
}
在Java程式碼中設定控制元件的Color時,通常這樣寫:
txtLabel.setTextColor(getResources().getColor(R.color.black));
但是getColor方法在Android 6.0即API 23中已經過時,替代方法為:
import android.support.v4.content.ContextCompat;
txtLabel.setTextColor(ContextCompat.getColor(context, R.color.black));
 
//判斷當前版本號,版本號大於等於16,使用setBackground;版本號小於16,使用setBackgroundDrawable。
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
tvDrawable.setBackground(drawable);
}else{
tvDrawable.setBackgroundDrawable(drawable);
}

-- setBackgroundImage(convertView, )與getColor()相容

ViewBackgroundCompatibleUtils.getInstance().setBackgroundImage(convertView, );

ViewBackgroundCompatibleUtils.getInstance().getColor(mContext,  )

/**
 *
得到顏色色值,適配不同的版本
 * @param context
 
* @param colorId
 
* @return
 
*/
public int getColor(Context context,  int colorId) {
    if (Build.VERSION.SDK_INT >= 23) {
        return ContextCompat.getColor(context, colorId);
    } else {
        return context.getResources().getColor(colorId);
    }
}

/**
 *
設定圖片的背景,適配不同的版本
 * @param view
 
* @param drawable
 
*/
public void setBackgroundImage(View view,Drawable drawable) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        // Android系統大於等於API16,使用setBackground
       
view.setBackground(drawable);
    } else {
        // Android系統小於API16,使用setBackgroundDrawable
       
view.setBackgroundDrawable(drawable);
    }
}

-- 丟擲異常

throw new IllegalArgumentException("Can't have a viewTypeCount < 1");

throw new IllegalArgumentException(“Illegal Array size or ArrayIndexOutOfBoundsException”);

throw new RuntimeException("state already added");

throw new IllegalStateException("ImageLoader must be invoked from the main thread.");

throw new NumberFormatException("無法將其轉化為合適的數字");

throw new Error("null instance of <T extends DefaultHandler> passed to constructor");

throw new NullPointerException();

private void parseTime(String aTime) throws NumberFormatException {}

— ScriptIntrinsicBlur, Android api 17實現的虛化;
Android開發:高斯模糊blur效果相容- https://www.pocketdigi.com/20150105/1412.html

— ListView在呼叫setAdapter()方法後再呼叫addHeaderView()方法會出現 Caused by: java.lang.IllegalStateException: Cannot add header view to list setAdapter has already been called.異常,意思是呼叫addHeaderView()方法在呼叫setAdapter()方法之後。android 4.4系統以前會有這個問題,在android 4.4及以後的版本修復了這個問題,不會報錯.

— 使用String.substring時,未對字串的長度進行檢查,擷取字串時可能會發生越界而導致Crash

Android程式設計注意事項- https://blog.csdn.net/daipeng123456789/article/details/50977574
 
- API 21 ,MediaProjection;API 19, virtualDisplay;

- Android 螢幕各尺寸的獲取- https://www.jianshu.com/p/a1ab688d7ef8
//API 17之後使用,獲取的畫素寬高包含虛擬鍵所佔空間,在API 17之前通過反射獲取  
context.getWindowManager().getDefaultDisplay().getRealMetrics(metric); 
//獲取的畫素寬高不包含虛擬鍵所佔空間  
//context.getWindowManager().getDefaultDisplay().getMetrics(metric); 

-- Android手機底部有虛擬按鍵
螢幕高度是螢幕真是高度-虛擬按鍵的高度。所以有虛擬按鍵的情況獲取螢幕的高度就是另一種方法了:
public static int getRealHeight(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); int screenHeight = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { DisplayMetrics dm = new DisplayMetrics(); display.getRealMetrics(dm); screenHeight = dm.heightPixels; //或者也可以使用getRealSize方法 // Point size = new Point(); // display.getRealSize(size); // screenHeight = size.y; } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { try { screenHeight = (Integer) Display.class.getMethod("getRawHeight").invoke(display); } catch (Exception e) { DisplayMetrics dm = new DisplayMetrics(); display.getMetrics(dm); screenHeight = dm.heightPixels; } } return screenHeight; }

虛擬按鍵高度
public static int getNavigationBarHeight(Context context) { int navigationBarHeight = -1; Resources resources = context.getResources(); int resourceId = resources.getIdentifier("navigation_bar_height","dimen", "android"); if (resourceId > 0) { navigationBarHeight = resources.getDimensionPixelSize(resourceId); } return navigationBarHeight; }

狀態列高度
1.public int getStatusBarHeight() { int result = 0; int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = getResources().getDimensionPixelSize(resourceId); } return result; }
2.通過反射
Android的所有資源都會有惟一標識在R類中作為引用。我們也可以通過反射獲取R類的例項域,然後找 status_bar_height。
    public void getStatusBarHeightByReflect() {
        int statusBarHeight2 = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            int height = Integer.parseInt(clazz.getField("status_bar_height")
                    .get(object).toString());
            statusBarHeight2 = getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.e(TAG, "狀態列高度-反射方式:" + statusBarHeight2);
    }

DisplayMetrics metric = new DisplayMetrics();

WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    activity.getWindowManager().getDefaultDisplay().getRealMetrics(metric);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    try {
        screenHeight = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
    } catch (Exception e) {
        DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);
        screenHeight = dm.heightPixels;
    }
}

-- ViewTreeObserver.removeOnGlobalLayoutListener相容
if (Build.VERSION.SDK_INT < 16) {
   getViewTreeObserver().removeGlobalOnLayoutListener(this);//mOnGlobalLayoutListener
} else {
   getViewTreeObserver().removeOnGlobalLayoutListener(this);//mOnGlobalLayoutListener
}

Java-protected的使用範圍-https://www.cnblogs.com/Victor-Han/p/4861412.html

 

相關文章