乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      屏幕適配全方位解析

       西北望msm66g9f 2018-07-06

      【公眾號回復(fù)“1024”,送你一個特別推送】

      Android系統(tǒng)發(fā)布十多年以來,關(guān)于Android的UI的適配一直是開發(fā)環(huán)節(jié)中最重要的問題,但是我看到還是有很多小伙伴對Android適配方案不了解。剛好,近期準備對糗事百科Android客戶端設(shè)計一套UI尺寸適配方案,可以和小伙伴們詳細的聊一聊這個問題。

      正文

      前面八次課我們已經(jīng)將android的繪制基礎(chǔ)已經(jīng)講完,那么現(xiàn)在我們下面的兩個內(nèi)容點是事件分發(fā)問題,和屏幕適配相關(guān)今天這節(jié)課我們主要來講android當中的各種屏幕適配問題

      1.屏幕適配概念

      而隨著支持Android系統(tǒng)的設(shè)備(手機、平板、電視、手表)的增多,設(shè)備碎片化、品牌碎片化、系統(tǒng)碎片化、傳感器碎片化和屏幕碎片化的程度也在不斷地加深。而我們今天要探討的,則是對我們開發(fā)影響比較大的——屏幕的碎片化。

      下面這張圖是Android屏幕尺寸的示意圖,在這張圖里面,藍色矩形的大小代表不同尺寸,顏色深淺則代表所占百分比的大小。

      下面是IOS的

      通過對比可以很明顯知道adnroid的屏幕到底有多少種了吧。而蘋果只有5種包括現(xiàn)在最新的劉海屏

      那么想要對屏幕適配的相關(guān)處理方案有一定的自己的心得,那么首先我們需要了解關(guān)于android屏幕的一定基礎(chǔ)

      1.屏幕適配基礎(chǔ)

      那么下面是我給大家寫的一個屏幕適配基礎(chǔ)的思維導(dǎo)圖,基本為一個基礎(chǔ)篇的大綱,這里我不會在課上非常詳細的給大家去過,就全部體現(xiàn)在簡書當中

      那么屏幕適配相關(guān)概念上我們需要掌握最基礎(chǔ)的3點
      那么相對基礎(chǔ)的內(nèi)容是給段位比較低的同學(xué),高段位可選擇跳過

      1.什么是屏幕尺寸,屏幕分辨率,屏幕像素密度

      屏幕尺寸指的是:

      分辨率:

      屏幕像素密度(DPI
      指每一
      英寸長度中,可顯示輸出的像素個數(shù),
      DPI的數(shù)字受屏幕尺寸和分辨率所影響,DPI可以通過計算所得

      上述內(nèi)容在于掃盲..畢竟還是有不清楚的同學(xué),而DPI跟下面內(nèi)容結(jié)合比較密切所以啰嗦了兩句

      2.什么是dp,dip,sp,px?它們之間的關(guān)系?

      px:構(gòu)成圖像的最小單位
      dip(重點):Desity Independent pixels的縮寫,即密度無關(guān)像素
      android內(nèi)部在識別圖像像素時以160dpi為基準,1dip=1px或1dp=1px
      例:在下列兩臺設(shè)備上使用DP進行操作
      480 320 160dpi 那么這臺機器上的1DP會被翻譯成1px
      800 
      480 240dpi 而這臺機器上的1DP會被翻譯成1.5px
      也就是說當前我們設(shè)備的DP是由android給予的基礎(chǔ)標準按比例進行翻譯的,這也是為什么我們用DP能解決一部分適配的原因

      3.mdpi,hdpi,xdpi,xxdpi,xxxdpi?如何計算和區(qū)分?

       名稱                 像素密度范圍         圖片大小  mdpi                 120dp~160dp         48×48px  hdpi                 160dp~240dp         72×72px  xhdpi                240dp~320dp         96×96px  xxhdpi               320dp~480dp         144×144px  xxxhdpi              480dp~640dp         192×192px

      在Google官方開發(fā)文檔中,說明了 mdpi:hdpi:xhdpi:xxhdpi:xxxhdpi=2:3:4:6:8 的尺寸比例進行縮放。例如,一個圖標的大小為48×48dp,表示在mdpi上,實際大小為48×48px,在hdpi像素密度上,實際尺寸為mdpi上的1.5倍,即72×72px,以此類推,可以繼續(xù)往后增加,不過一般情況下已經(jīng)夠用了,這種用來去適配手機和平板之間的圖形問題

      2.屏幕適配基礎(chǔ)篇(常識,見思維導(dǎo)圖,這里只詳細講一下限定符)

      2.1使用 “wrap_content” 和 “match_parent”
      2.2相對布局控制屏幕
      2.3. .9圖的應(yīng)用
      上面三個都是最基本的android使用,我們只需要在平常應(yīng)用是注意到就行了,這里不詳細去講

      2.4.限定符

      我們在做屏幕的適配時在屏幕 尺寸相差不大的情況下,dp可以使不同分辨率的設(shè)備上展示效果相似。但是在屏幕尺寸相差比較大的情況下(平板),dp就失去了這種效果。所以需要以下的限定符來約束,采用多套布局,數(shù)值等方式來適配。

      那么其實所謂的限定符就是android在進行資源加載的時候會按照屏幕的相關(guān)信息對文件夾對應(yīng)的名字進行識別,而這些特殊名字就是我們的限定符

      限定符分類:
         屏幕尺寸    
             small   小屏幕
             normal  基準屏幕
             large   大屏幕
             xlarge  超大屏幕
         屏幕密度
             ldpi    <>120dpi
             mdpi    <=>160dpi
             hdpi    <=>240dpi
             xhdpi   <=>320dpi
             xxhdpi  <=>480dpi
             xxhdpi  <=>640dpi(只用來存放icon)
             nodpi   與屏幕密度無關(guān)的資源.系統(tǒng)不會針對屏幕密度對其中資源進行壓縮或者拉伸
             tvdpi   介于mdpi與hdpi之間,特定針對213dpi,專門為電視準備的,手機應(yīng)用開發(fā)不需要關(guān)心這個密度值.
         屏幕方向    
             land    橫向
             port    縱向
         屏幕寬高比  
             long    比標準屏幕寬高比明顯的高或者寬的這樣屏幕
             notlong 和標準屏幕配置一樣的屏幕寬高比

      2.4.1使用尺寸限定符:

      當我們要在大屏幕上顯示不同的布局,就要使用large限定符。例如,在寬的屏幕左邊顯示列表右邊顯示列表項的詳細信息,在一般寬度的屏幕只顯示列表,不顯示列表項的詳細信息,我們就可以使用large限定符。
      res/layout/main.xml 單面板:

      LinearLayout xmlns:android='http://schemas./apk/res/android'
      android:orientation='vertical'
      android:layout_width='match_parent'
      android:layout_height='match_parent'>


      fragment android:id='@+id/headlines'
               android:layout_height='fill_parent'
               android:name='com.example.android.newsreader.HeadlinesFragment'
               android:layout_width='match_parent' />

      LinearLayout>

      res/layout-large/main.xml 雙面板:

      LinearLayout xmlns:android='http://schemas./apk/res/android'
      android:layout_width='fill_parent'
      android:layout_height='fill_parent'
      android:orientation='horizontal'>


      fragment android:id='@+id/headlines'
               android:layout_height='fill_parent'
               android:name='com.example.android.newsreader.HeadlinesFragment'
               android:layout_width='400dp'
               android:layout_marginRight='10dp'/>


      fragment android:id='@+id/article'
               android:layout_height='fill_parent'
               android:name='com.example.android.newsreader.ArticleFragment'
               android:layout_width='fill_parent' />

      LinearLayout>

      如果這個程序運行在屏幕尺寸大于7inch的設(shè)備上,系統(tǒng)就會加載res/layout-large/main.xml 而不是res/layout/main.xml,在小于7inch的設(shè)備上就會加載res/layout/main.xml。

      需要注意的是,這種通過large限定符分辨屏幕尺寸的方法,適用于android3.2之前。在android3.2之后,為了更精確地分辨屏幕尺寸大小,Google推出了最小寬度限定符。

      2.4.2使用最小寬度限定符

      最小寬度限定符的使用和large基本一致,只是使用了具體的寬度限定。
      res/layout/main.xml,單面板(默認)布局:

      'http://schemas./apk/res/android'
      android:orientation='vertical'
      android:layout_width='match_parent'
      android:layout_height='match_parent'>

      fragment android:id='@+id/headlines'
               android:layout_height='fill_parent'
               android:name='com.example.android.newsreader.HeadlinesFragment'
               android:layout_width='match_parent' />

      LinearLayout>

      res/layout-sw600dp/main.xml,雙面板布局: Small Width 最小寬度

      LinearLayout xmlns:android='http://schemas./apk/res/android'
      android:layout_width='fill_parent'
      android:layout_height='fill_parent'
      android:orientation='horizontal'>

      fragment android:id='@+id/headlines'
               android:layout_height='fill_parent'
               android:name='com.example.android.newsreader.HeadlinesFragment'
               android:layout_width='400dp'
               android:layout_marginRight='10dp'/>

      fragment android:id='@+id/article'
               android:layout_height='fill_parent'
               android:name='com.example.android.newsreader.ArticleFragment'
               android:layout_width='fill_parent' />

      LinearLayout>

      這種方式是不區(qū)分屏幕方向的。這種最小寬度限定符適用于android3.2之后,所以如果要適配android全部的版本,就要使用large限定符和sw600dp文件同時存在于項目res目錄下。

      這就要求我們維護兩個相同功能的文件。為了避免繁瑣操作,我們就要使用布局別名。

      2.4.3使用布局別名
      res/layout/main.xml: 單面板布局
      res/layout-large/main.xml: 多面板布局
      res/layout-sw600dp/main.xml: 多面板布局
      由于后兩個文具文件一樣,我們可以用以下兩個文件代替上面三個布局文件:

      res/layout/main.xml 單面板布局
      res/layout/main_twopanes.xml 雙面板布局

      然后在res下建立
      res/values/layout.xml、
      res/values-large/layout.xml、
      res/values-sw600dp/layout.xml三個文件。

      默認布局
      res/values/layout.xml:

      resources>
         item name='main' type='layout'>@layout/mainitem>
      resources>

      Android3.2之前的平板布局
      res/values-large/layout.xml:

      resources>
         item name='main' type='layout'>@layout/main_twopanesitem>
      resources>

      Android3.2之后的平板布局
      res/values-sw600dp/layout.xml:

      resources>
         item name='main' type='layout'>@layout/main_twopanesitem>
      resources>

      這樣就有了main為別名的布局。
      在activity中setContentView(R.layout.main);

      這樣,程序在運行時,就會檢測手機的屏幕大小,如果是平板設(shè)備就會加載res/layout/main_twopanes.xml,如果是手機設(shè)備,就會加載res/layout/main.xml 。我們就解決了只使用一個布局文件來適配android3.2前后的所有平板設(shè)備。

      2.4.4使用屏幕方向限定符
      如果我們要求給橫屏、豎屏顯示的布局不一樣。就可以使用屏幕方向限定符來實現(xiàn)。
      例如,要在平板上實現(xiàn)橫豎屏顯示不用的布局,可以用以下方式實現(xiàn)。
      res/values-sw600dp-land/layouts.xml:橫屏

      resources>
         item name='main' type='layout'>@layout/main_twopanesitem>
      resources>

      res/values-sw600dp-port/layouts.xml:豎屏、

      resources>
         item name='main' type='layout'>@layout/mainitem>
      resources>

      那么上述是最基本的屏幕適配的解決方案
      這里找到一個神人給官方適配方案做的翻譯推給大家參考
      https://blog.csdn.net/wzy_1988/article/details/52932875

      3.屏幕適配解決方案:

      基礎(chǔ)篇結(jié)束之后,我們市場上最常用的解決方案我給大家總結(jié)了兩種
      1.通過自定義布局組件來完成

      有聽過我公開課的同學(xué)應(yīng)該知道我當時寫了一套,其核心原理是根據(jù)一個參照分辨率進行布局,然后再各個機器上提取當前機器分辨率換算出系數(shù)之后,然后再通過重新測量的方式來達到適配的效果,這一套方案基本能適用于95以上的機型,那么今天到時候再加上劉海屏的適配就OK了。
      下面是代碼,

      /**
        * Created by barry on 2018/6/7.
        */

      public class ScreenAdaptationRelaLayout extends RelativeLayout {
      public ScreenAdaptationRelaLayout(Context context) {
         super(context);
      }

      public ScreenAdaptationRelaLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
      }

      public ScreenAdaptationRelaLayout(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
      }

      static boolean isFlag = true;

      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

         if(isFlag){
             int count = this.getChildCount();
             float scaleX =  UIUtils.getInstance(this.getContext()).getHorizontalScaleValue();
             float scaleY =  UIUtils.getInstance(this.getContext()).getVerticalScaleValue();

             Log.i('testbarry','x系數(shù):'+scaleX);
             Log.i('testbarry','y系數(shù):'+scaleY);
             for (int i = 0;i <>
                 View child = this.getChildAt(i);
                 //代表的是當前空間的所有屬性列表
                 LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
                 layoutParams.width = (int) (layoutParams.width * scaleX);
                 layoutParams.height = (int) (layoutParams.height * scaleY);
                 layoutParams.rightMargin = (int) (layoutParams.rightMargin * scaleX);
                 layoutParams.leftMargin = (int) (layoutParams.leftMargin * scaleX);
                 layoutParams.topMargin = (int) (layoutParams.topMargin * scaleY);
                 layoutParams.bottomMargin = (int) (layoutParams.bottomMargin * scaleY);
             }
             isFlag = false;
         }

         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      }

      @Override
      protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
      }
      }
      public class UIUtils {

      private Context context;

      private static UIUtils utils ;

      public static UIUtils getInstance(Context context){
         if(utils == null){
             utils = new UIUtils(context);
         }
         return utils;
      }

      //參照寬高
      public final float STANDARD_WIDTH = 720;
      public final float STANDARD_HEIGHT = 1232;

      //當前設(shè)備實際寬高
      public float displayMetricsWidth ;
      public float displayMetricsHeight ;

      private  final String DIMEN_CLASS = 'com.android.internal.R$dimen';

      private UIUtils(Context context){
         this.context = context;
         //
         WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

         //加載當前界面信息
         DisplayMetrics displayMetrics = new DisplayMetrics();
         windowManager.getDefaultDisplay().getMetrics(displayMetrics);

         if(displayMetricsWidth == 0.0f || displayMetricsHeight == 0.0f){
             //獲取狀態(tài)框信息
             int systemBarHeight = getValue(context,'system_bar_height',48);

             if(displayMetrics.widthPixels > displayMetrics.heightPixels){
                 this.displayMetricsWidth = displayMetrics.heightPixels;
                 this.displayMetricsHeight = displayMetrics.widthPixels - systemBarHeight;
             }else{
                 this.displayMetricsWidth = displayMetrics.widthPixels;
                 this.displayMetricsHeight = displayMetrics.heightPixels - systemBarHeight;
             }

         }
      }

      //對外提供系數(shù)
      public float getHorizontalScaleValue(){
         return displayMetricsWidth / STANDARD_WIDTH;
      }

      public float getVerticalScaleValue(){

         Log.i('testbarry','displayMetricsHeight:'+displayMetricsHeight);
         return displayMetricsHeight / STANDARD_HEIGHT;
      }

      public int getValue(Context context,String systemid,int defValue) {

         try {
             Class clazz = Class.forName(DIMEN_CLASS);
             Object r = clazz.newInstance();
             Field field = clazz.getField(systemid);
             int x = (int) field.get(r);
             return context.getResources().getDimensionPixelOffset(x);

         } catch (Exception e) {
            return defValue;
         }
      }
      }

      2.給各個分辨率單獨適配,res,dimens里設(shè)置各個對應(yīng)的px,再統(tǒng)一調(diào)用,由系統(tǒng)篩選。

      這種方式比較久遠了,但是確實還是有很多項目在使用到這種方式
      其原理就是據(jù)設(shè)備屏幕的分辨率各自寫一套dimens.xml文件,然后根據(jù)一個基準分辨率(例如720x1080),將寬度分成720份,取值為1px——720px,將高度分成1080份,取值為1px——1080px。生成各自dimens.xml文件對應(yīng)的值。
      但是今天我根據(jù)這個方法,在這個方案的基礎(chǔ)之上給大家做了一次改變,運用之前所見的DP的概念,結(jié)合之前講的限定符,用DP來升級了這種方案,dp適配原理與px適配一樣,區(qū)別就在于px適配是根據(jù)屏幕分辨率,即拿px值等比例縮放,而dp適配是拿dp值來等比縮放而已。
      既然原理都一樣,都需要多套dimens.xml文件,為什么說dp適配就比px適配好呢?
      因為px適配是根據(jù)屏幕分辨率的,Android設(shè)備分辨率一大堆,而且還要考慮虛擬鍵盤。而dp適配無論手機屏幕的像素多少,密度比值多少,80%的手機的最小寬度dp值(widthPixels / density)都為360dp,這樣就大大減少了dimens.xml文件
      PS:(現(xiàn)在基本上手機的dpi都在350+以上 那么按最低算 350/160=2.1 那么360 2.1 = 720+ 基本上手機的分辨率都會在360dp之內(nèi) 上面例子19201080的情況 500/160=3.125 那么 360*3.125=1125其實也在360之內(nèi))
      那么傳統(tǒng)做法:

      改良后的做法:

      獲取最小寬度獲取如下:

      DisplayMetrics dm = new DisplayMetrics();

         getWindowManager().getDefaultDisplay().getMetrics(dm);

         int widthPixels = dm.widthPixels;

         float density = dm.density;

         float widthDP = widthPixels / density;

      所以通過這種兩種形式的結(jié)合能夠達到我們整體適配任意機型的目的

      原文作者:Barry

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多