Android初級第九講之適配和調試



 本文來自http://blog.csdn.net/liuxian13183/ ,引用必須註明出處!

Android適配需要考慮方方面面,主要是圖片字體大小和API,但也要考慮其他場景下的一些問題。

先熟悉一下Android設備的dpi(dots per inch),設計上叫ppi(pixel per inch),即1inch中有多少個像素

1、考慮橫豎屏幕,注意屏幕布局資源的替換和頁面數據的保存和重加載,配合onSaveInstance和onRestoreInstance使用

以及適配的屏幕尺寸,通過在主配置文件的Application處,設計supports-screen,normal、large、xlarge等

以下摘抄自Google官方:https://developer.android.com/guide/practices/screens_support.html

屏幕尺寸
按屏幕對角測量的實際物理尺寸。

爲簡便起見,Android 將所有實際屏幕尺寸分組爲四種通用尺寸:小、 正常、大和超大。

屏幕密度
屏幕物理區域中的像素量;通常稱爲 dpi(每英寸 點數)。例如, 與“正常”或“高”密度屏幕相比,“低”密度屏幕在給定物理區域的像素較少。

爲簡便起見,Android 將所有屏幕密度分組爲六種通用密度: 低、中、高、超高、超超高和超超超高。

方向
從用戶視角看屏幕的方向,即橫屏還是 豎屏,分別表示屏幕的縱橫比是寬還是高。請注意, 不僅不同的設備默認以不同的方向操作,而且 方向在運行時可隨着用戶旋轉設備而改變。
分辨率
屏幕上物理像素的總數。添加對多種屏幕的支持時, 應用不會直接使用分辨率;而只應關注通用尺寸和密度組指定的屏幕 尺寸及密度。
密度無關像素 (dp)
在定義 UI 佈局時應使用的虛擬像素單位,用於以密度無關方式表示佈局維度 或位置。

密度無關像素等於 160 dpi 屏幕上的一個物理像素,這是 系統爲“中”密度屏幕假設的基線密度。在運行時,系統 根據使用中屏幕的實際密度按需要以透明方式處理 dp 單位的任何縮放 。dp 單位轉換爲屏幕像素很簡單: px = dp * (dpi / 160)。 例如,在 240 dpi 屏幕上,1 dp 等於 1.5 物理像素。在定義應用的 UI 時應始終使用 dp 單位 ,以確保在不同密度的屏幕上正常顯示 UI。

支持的屏幕範圍

從 Android 1.6(API 級別 4)開始,Android 支持多種屏幕尺寸和密度,反映設備可能具有的多種不同屏幕配置。 您可以使用 Android 系統的功能優化應用在各種屏幕配置下的用戶界面 ,確保應用不僅正常渲染,而且在每個屏幕上提供 最佳的用戶體驗。

爲簡化您爲多種屏幕設計用戶界面的方式,Android 將實際屏幕尺寸和密度的範圍 分爲:

  • 四種通用尺寸正常、  和超大

    :從 Android 3.2(API 級別 13)開始,這些尺寸組 已棄用,而採用根據可用屏幕寬度管理屏幕尺寸的 新技術。如果爲 Android 3.2 和更高版本開發,請參閱聲明適用於 Android 3.2 的平板電腦佈局以瞭解更多信息。

  • 六種通用的密度
    • ldpi(低)~120dpi ~density=0.75
    • mdpi(中)~160dpi ~density=1
    • hdpi(高)~240dpi ~density=1.5
    • xhdpi(超高)~320dpi ~density=2
    • xxhdpi(超超高)~480dpi ~density=3
    • xxxhdpi(超超超高)~640dpi ~density=4

以上是對屏幕密度的描述,希望大家明白一點:分辨率越高的手機,指的是密度越高,即單位區域內像素越多。


從 Android 3.2(API 級別 13)開始,以上尺寸組已棄用,您 應改爲使用 sw<N>dp 配置限定符來定義佈局資源 可用的最小寬度。例如,如果多窗格平板電腦佈局 需要至少 600dp 的屏幕寬度,應將其放在 layout-sw600dp/ 中。聲明適用於 Android 3.2 的平板電腦佈局一節將進一步討論如何使用新技術聲明佈局資源。

如果未配置到相應尺寸,則高分辨率的會向高配置的資源擴展,低分辨率的會向低配置的資源擴展。舉個栗子:只有hdpi、xhdpi三種資源,則mdpi的手機默認使用hdpi,而xxhdpi使用xhdpi,以實現屏幕的最佳顯示效果。


關於圖片、佈局和密度,根據上述參數可以做如下配置


上面是對大體的尺寸做適配,而安卓的廠商不要太多,各家規範又不太一致,因此可以對具體的尺寸做適配。


以上即對圖片、佈局,甚至具體尺寸做的適配。

適配的部分代碼

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;



2、字體、佈局大小

字體儘量用sp,間距和尺寸儘量用dp,理解density就可以明白,這樣字體、間距和尺寸就會隨着屏幕密度而自動改變爲px


3、不同系統API不同-如setBackground,碎片化問題

舉個栗子:不同系統對從webView本地拿圖片方法不一樣

        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            listener.showConfirmDialog(uploadMsg);
 }

        // For Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            listener.showConfirmDialog(uploadMsg);
        }

        // For Android 4.1
            listener.showConfirmDialog(uploadMsg);
        }



更多詳見:http://blog.csdn.net/reboot123/article/details/52461897


4、Cpu不同-如arm、mips、x86

一般不同手機,會適配不同硬件,而選擇合適的cpu是驅動不同硬件達到完美狀態的關鍵,arm是主流。廠商會根據不同功能如拍照美顏、視頻流暢度選擇不同cpu,有的比較放鬆如Nexus,有的比較嚴格如Oppo;嚴格的結果就是,如果你沒有適配它的so包,則相關功能就不可用,銀聯3.2.5版本即是如此。

一般情況下只適配arm-v7a即可,x86會自動轉譯,mips幾乎可以忽略

更多關於cpu的介紹:http://blog.csdn.net/reboot123/article/details/51601368

5、狀態欄、導航欄、菜單欄的長度

比如:http://blog.csdn.net/u010156024/article/details/48321485

6、橫豎屏切換,且各生命週期不再重新調用

1)Activity設置  android:configChanges="keyboard|screenSize|orientation|layoutDirection"

2)在Activity中實現onConfigurationChanged方法,重新佈局和初始化數據(注意全局變量數據依然存在)

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mScreenChanged.set(true);//記錄橫豎屏發生過變化
        if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            //land
            setContentView(R.layout.activity_land);
            initLand();//初始化橫屏數據
        } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            //port
            setContentView(R.layout.activity_port);
            initPort();//初始化豎屏數據
        }
    }

3)在點擊事件,強制執行橫豎屏操作                                                                             

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_close:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//強制爲豎屏
                break;
            case R.id.iv_stretch:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//強制爲橫屏
                break;
        }
    }

7、圖片等比例縮放,需要maxWidth、maxHeight和adjustViewBounds設置爲true同時進行纔可以
注意,maxWidth和maxHeight不能直接設爲屏幕寬高,否則等比例縮放會失敗,因爲某一方達到最大值,則另一方也會執行同樣操作
photo = new ImageView(mContext);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
photo.setLayoutParams(lp);
photo.setMaxWidth((int) (screenWidth * 0.99));
photo.setMaxHeight((int) (screenHeight * 0.99));
photo.setScaleType(ImageView.ScaleType.FIT_CENTER);
photo.setAdjustViewBounds(true);
如果需要左右滑動、拉伸縮放,做圖片預覽,那麼可以用下面的資源:
http://download.csdn.net/detail/liuxian13183/9846522
ImageView的繪畫,先後執行順序爲:
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }




    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }
    @Override
    public void onGlobalLayout() {




    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
前三個可能執行多次,最後一個僅執行一次。

8、H5調試方案:https://segmentfault.com/a/1190000009240637


更多技巧:http://blog.csdn.net/reboot123/article/details/46127797



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章