android開發學習筆記系列(4)--android動態佈局

前言

在作一個有關蘇果APP的項目中,可是fuck的是,我徹底使用相對佈局以後及線性佈局以後發現坑爹的事情了,屏幕不能適配,這是多大的痛,意味着,必須使用相應的代碼實現動態佈局!呵呵,不作項目不知道,只有真正地下手去作某些事情的時候,纔會發覺各類問題,本來打算先寫view與framgent實現tabhost功能的博客的,可是碰到了這個棘手問題必須先把他解決了!同時不知道各位網友有什麼好的方法來適配全部的安卓手機屏幕android

問題

  • 在xml文件中使用px以後出現了各類不適應屏幕的狀況,控件不是大了就是小了,要知道在android世界裏面有太對的屏幕尺寸了,真羨慕搞蘋果開發的人!
  • UI變得奇醜無比
  • 控件太多的誤差了!

解決之道

其實解決之道有不少,我選用的是使用代碼計算等比例高寬,讓其在相應的屏幕上顯示相應的比例高度就能夠了!固然網上有不少都是給的建議,卻沒有實實在在解決問題的博客!(但願集思廣益,可以獲得一個適合所有屏幕類型的架包,方便全部的安卓開發人員)工具

關於網上的建議

網上的建議,我進行了概括:佈局

1、關於佈局適配

  1. 不要使用絕對佈局
  2. 儘可能使用match_parent 而不是fill_parent 。
  3. 可以使用權重的地方儘可能使用權重(android:layout_weight)
  4. 若是是純色背景,儘可能使用android的shape 自定義。
  5. 若是須要在特定分辨率下適配,能夠在res目錄上新建layout-HxW.xml的文件夾。好比要適配1080x1800的屏幕(魅族MX3採用此分辨率)則新建layout-1800x1080.xml的文件夾,而後在下面定義佈局。Android系統會優先查找分辨率相同的佈局,若是不存在則換使用默認的layout下的佈局。

2、術語和概念

  • 四種屏幕尺寸分類:: small, normal, large, and xlarge
  • 四種密度分類: ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high)
  • 須要注意的是: xhdpi是從 Android 2.2 (API Level 8)纔開始增長的分類.
  • xlarge是從Android 2.3 (API Level 9)纔開始增長的分類.
  • DPI是「dot per inch」的縮寫,每英寸像素數。

通常狀況下的普通屏幕:ldpi是120,mdpi是160,hdpi是240,xhdpi是320。字體

3、如何作到自適應屏幕大小呢?

一、界面佈局方面

須要根據物理尺寸的大小準備5套佈局,layout(放一些通用佈局xml文件,好比界面中頂部和底部的佈局,不會隨着屏幕大小變化,相似windos窗口的title bar),layout-small(屏幕尺寸小於3英寸左右的佈局),layout-normal(屏幕尺寸小於4.5英寸左右),layout-large(4英寸-7英寸之間),layout-xlarge(7-10英寸之間)this

二、圖片資源方面

須要根據dpi值準備5套圖片資源,drawable,drawalbe-ldpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi設計

Android有個自動匹配機制去選擇對應的佈局和圖片資源code

4、兩種獲取屏幕分辨率信息的方法:

DisplayMetrics metrics = new DisplayMetrics();
Display display = activity.getWindowManager().getDefaultDisplay();
display.getMetrics(metrics);//這裏獲得的像素值是設備獨立像素dp
//DisplayMetrics metrics=activity.getResources().getDisplayMetrics(); 這樣得到的參數信息不正確,不要使用這種方式。

不能使用android.content.res.Resources.getSystem().getDisplayMetrics()。這個獲得的寬和高是空的。orm

5、關於圖片製做

關於設計

設計圖先定下一個要設計的尺寸,並且儘可能採用在目前最流行的屏幕尺寸(好比目前佔屏幕比重比較多的是480系列,也便是480x800或者400x854,下面的圖標製做也在次基礎上進行比例的換算)上設計。
先了解一下屏幕的級別:xml

說明:htm

  • 屏幕級別:
    注意屏幕級別是按照密度分級,和像素沒有關係。若是非要讓密度和像素扯上關係,則須要一個參照系,android使用mdpi級別做爲標準參照屏幕,也就是說在320x480分辨率的手機上一個密度能夠容納一個像素。而後其餘密度級別則在此基礎上進行對比。若是理想狀況下,480x800的屏幕一個密度能夠容納1.5個像素。

  • 物理大小:
    單位是英寸而不是像素,也就說一個英寸在任何分辨率下顯示的大小都是同樣的,可是像素在密度不一樣的手機裏面顯示的實際的大小是不同的(這就是爲何android手機須要適配的緣由)。
    而後就是重點。

    假設1像素在160密度下顯示1英寸,則1像素在240密度基礎上顯示大約0.67英寸,在320密度下顯示0.5英寸。因而就出現一種狀況,在電腦上的一個像素,在不一樣的手機上看實際的大小不同。那麼怎麼讓「設計效果」在不一樣的手機上看起來顯示的區域同樣呢?

仍是假設一個像素在160密度下的顯示在一個密度內,也假設就是一英寸。那麼須要幾個像素才能在240密度級別下顯示在一英寸範圍內呢?答案是1.5個像素(根據上圖的比率換算)。
瞭解了這個關係,接下來就是圖標的製做。

關於切圖

關於切圖有幾個建議:

  1. 長寬最好是3的倍數(根據android的推薦logo圖標的大小是48(mdpi),72(hdpi),96(xhdpi)得出的最小公約數)。
  2. 長寬最好是偶數。由於奇數在進行等比壓縮的時候可能有問題。
  3. 根據上面兩條,若是長寬是6的倍數最理想。
  4. 若是能夠拉伸而不改變設計意圖的狀況下,好比純色背景,則使用android的9path工具製做成.9的圖片。

關於圖標的適配。

而後接下來的一切就和設計稿沒什麼關係。在切好圖的基礎上,根據屏幕密度、像素和實際大小的比例關係。假如設計司在480x800的分辨率下作好了設計圖,而且切好圖,若是你須要適配720x1280屏幕,該怎麼作?根據比例,他們的關係是2:3,因而你須要按照1.5倍比例製做圖標,好比你在480x800的設計稿上切下來一個20*20像素的圖,那麼你就須要製做一個等比放大成30x30像素的圖標,這樣同一個圖標在480x800的屏幕和720x1280的屏幕上顯示的實際大小才同樣。同理,若是你須要適配xxhdpi則須要在20x20的基礎上製做一個等比放大成40x40像素的圖標。

關於圖標的目錄

480*800切下來的圖咱們放在drawable-hdpi目錄下,按照2:3放大的圖標放在drawable-xhdpi目錄下,按照2倍放大的圖標放在drawable-xxhdpi目錄下。

android會根據手機的密度優先查找對應的目錄的資源,
好比408800分辨率下的手機若是密度是160,則自動加載drawable-hdpi這個目錄下的圖標,
若是720
1280密度是240的手機自動加載drawable-xhdpi這個目錄下的圖標。若是沒有這個文件夾,則查找和240最接近的對應密度文件夾。

有關我的的解決方法

我我的獲得的啓示就是我在設計過程當中儘可能使控件不是使用數值,也就是說我在xml文件所使用的基本都是layout_weight\android:gravity="center"等,若是迫不得得以使用的話,就先寫着,而後經過相應的代碼來適配動態佈局

代碼實現動態佈局

目前我所使用的方法呢就是本身寫個類,將view傳進去進行適配,同時注意了個人方案是能夠更改你原來所假設的屏幕寬度,而後一次性地進行適配!

package com.samuel.demosuguo;

import android.content.Context;
import android.util.DisplayMetrics;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
/**
 * Created by samuelwnb on 2015/3/14.
 */
public class Autosize {

    int screenwidth = 640;//默認屏幕寬度爲640

    /***
     * 獲得默認屏幕寬度
     * @return
     */
    public int getScreenwidth() {
        return screenwidth;
    }

    /***
     * 更改默認屏幕寬度
     * @param screenwidth
     */
    public void setScreenwidth(int screenwidth) {
        this.screenwidth = screenwidth;
    }

    //實際屏幕大小
    static int screensize = 0;
    public static void setScreensize(int screensize) {
        Autosize.screensize = screensize;
    }


    /**
     * 獲取屏幕的大小
     * @param context//爲activity
     * @return 實際屏幕的打下
     */
    public int Metricwidth(Context context){
        DisplayMetrics metric = new DisplayMetrics();
        metric = context.getResources().getDisplayMetrics();
        return metric.widthPixels;
    }
    //獲取直接獲取屏幕的實際寬度
    public void GetrealScreenwidth(Context context){
        DisplayMetrics metric = new DisplayMetrics();
        metric = context.getResources().getDisplayMetrics();
        setScreensize(metric.widthPixels);
    }
    //設置線性佈局下的線性高度
    public void llinearlayoutheight(int px, LinearLayout linearLayout) {
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) linearLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.height = px * screensize / screenwidth;
            linearLayout.setLayoutParams(layoutParams);
        }
    }

    /***********************
    控件設置
     */
    //自動設置設置字體的大小
    public int autosettextsize(int sp){
        if(screensize != 0) {
            return sp * screensize / screenwidth;
        }
        else {
            return sp;
        }

    }
    /**
     * 相對佈局中的不一樣設置高度
     */
    //設置相對佈局下的相對佈局高度
    public void relativeLayoutheight(int px, RelativeLayout relativeLayout) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.height = px * screensize / screenwidth;
            relativeLayout.setLayoutParams(layoutParams);
        }
    }
    //設置相對佈局中的相對高度帶Margintop設置
    public void relativeLayoutheightwithmargintop(int px,int margintop, RelativeLayout relativeLayout){
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.height = px * screensize / screenwidth;
            layoutParams.topMargin = margintop * screensize / screenwidth;
            relativeLayout.setLayoutParams(layoutParams);
        }
    }
    public void relativeLayoutheightmargintop(int margintop, RelativeLayout relativeLayout){
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.topMargin = margintop * screensize / screenwidth;
            relativeLayout.setLayoutParams(layoutParams);
        }
    }
    //設置相對佈局下的線性佈局高度
    public void rlinearlayoutheight(int px, LinearLayout linearLayout) {
        RelativeLayout.LayoutParams relativelayout = (RelativeLayout.LayoutParams) linearLayout.getLayoutParams();
        if(screensize != 0) {
            relativelayout.height = px * screensize / screenwidth;
            linearLayout.setLayoutParams(relativelayout);
        }
    }
    public void rlinearlayoutheightwithmargintop(int px,int margintop,LinearLayout linearLayout) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) linearLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.height = px * screensize / screenwidth;
            layoutParams.topMargin = margintop * screensize / screenwidth;
            linearLayout.setLayoutParams(layoutParams);
        }
    }
    public void rlinearlayoutheightmargintop(int margintop,LinearLayout linearLayout) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) linearLayout.getLayoutParams();
        if(screensize != 0) {
            layoutParams.topMargin = margintop * screensize / screenwidth;
            linearLayout.setLayoutParams(layoutParams);
        }
    }
   }

在這裏我來舉個例子:

Autosize autosize = new Autosize();
        autosize.GetrealScreenwidth(getActivity());
        RelativeLayout tophome = (RelativeLayout) findViewById(R.id.tophome);
        autosize.relativeLayoutheight(88,tophome);

步驟:

  • 先實例化我寫的類
  • 獲取屏幕寬度
  • 獲得RelativeLayout的ID
  • 直接送入適配,但注意這裏要知道你想在屏幕上顯示多大!

注意的地方

必定要注意你究竟是哪一個佈局下的一個佈局,必須找到父view纔可使用!若是想知道爲何的話,你們能夠去找layoutparams有關的內容!

給讀者的話

那個撒,你看我如此賣命地寫博客,並且仍是本身在攻克難點,就來關注個人博客唄!

相關文章
相關標籤/搜索