Android究極のスクリーンアダプタ

9501 ワード

Android画面の適合問題の由来
Androidの破片化問題が心を痛め、画面の違いが本格的に破片化した問題の中心であることはよく知られています.画面のサイズは3インチから10インチ、解像度は320から1920までそろっており、uiの適合に大きな困難をもたらしています.画面の断片化の問題では、Androidはuiに適したサイズ単位としてdpを推奨しているので、px、dp、dpi、ppi、densityなどの概念を理解する必要があります.
定義#テイギ#
コンセプト
へんかん
px
画素点、例えば携帯電話の解像度320 x 480は幅320画素、高さ480画素を表す
px = density * dp
ppi
画素密度は、1インチあたりの画素数であり、これはスクリーン物理パラメータであり、例えばmate 20 proのppiは538である.
ppiはddpiにほぼ等しい
dpi
画素密度は、ppiとは異なり、dpiは人為的に調整される可能性があり、例えば、同じ解像度の異なるサイズの携帯電話ppiが430440450であり、androidはdpiが480に指定される.
dpiはppiに約等しい
dp
density-independent pixelsは、密度に関係のない寸法を説明するためにスクリーン物理解像度の抽象単位に基づいている.
px = dp *(dpi/160)
density
密度、画面の平方インチあたりのピクセルポイント数
density = dpi/160)
一般的に、dpと適応レイアウトによってスクリーンの断片化の問題を基本的に解決することができます.これもAndroidが推奨するスクリーン互換性案ですが、2つの大きな問題があります.
  • 不一致.dpiとppiの違いの実際の違いにより,同じ解像度の携帯電話ではコントロールの実際の大きさが異なる.
  • 効率.デザイナーの設計原稿はすべてpx単位で、開発者は適合のためにdpに換算する必要がある.

  • dpアダプティブに加えて、今日はシステムdensityを修正することでアダプティブになります.
    xmlファイルを作成するとき、コントロールの幅をdpでもpxでもptでも、最終的にandroidはpx表示に変換します.ソースコードを通して知ることができます.
       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;
        }
    

    だから、dpを使うと、システムは私たちのdp値にmetricsを乗じていることがわかります.density換算のpx値は携帯電話に表示され、spはmetricsを乗じる.scaleddensity、デフォルトではmetrics.scaledDensity = metrics.density.システムのmetricsを変更するだけですdensityは適切な効果を達成することができます.では、どのように修正しますか?width=320 dpなど、uiが図を出すときに参照の幅の値を決めることができます.現在の携帯電話のdisplayMetricsに基づいてwidthPixels/widthはdensityを算出し、システムのdensityを置き換える.あまりコードを言わないで~
    public class Density {
    
        private static final float  WIDTH = 320;//      
    
        private static float appDensity;//      
        private static float appScaleDensity; //      ,  appDensity
    
        public static void setDensity(final Application application, Activity activity){
            //    app       
            DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();
            if (appDensity == 0){
                //       
                appDensity = displayMetrics.density;
                appScaleDensity = displayMetrics.scaledDensity;
    
            //     density, scaleDensity, densityDpi
            float targetDensity = displayMetrics.widthPixels / WIDTH; // 1080 / 360 = 3.0
            float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);
            int targetDensityDpi = (int) (targetDensity * 160);
    
            //  Activity density, scaleDensity, densityDpi
            DisplayMetrics dm = activity.getResources().getDisplayMetrics();
            dm.density = targetDensity;
            dm.scaledDensity = targetScaleDensity;
            dm.densityDpi = targetDensityDpi;
        }
    
    }
    

    現在の携帯電話の幅の画素値/参照の幅値からターゲットdensityを算出し、システムを置き換えればよい.それからmainActivityでdensityを呼び出します.setDensity(getApplication(),this);