1. 程式人生 > >開源,安卓自動縮放佈局,解決螢幕適配問題

開源,安卓自動縮放佈局,解決螢幕適配問題

2015.8.4 更新

增加引數custom:autoScaleType 設定縮放模式,可以設為“fitWidth”,"fitHeigth" 和 "fitInside"。分別代表縮放至寬度匹配,縮放至高度匹配以及縮放至適合容器內部,預設為"fitInside"。

做過安卓開發的都知道,螢幕適配是一件非常困難的事情。

Google官方的解決方案:screens_support 需要寫多個layout檔案以及dimens.xml,工作量大不說,維護也麻煩。

其實很多時候我們的需求很簡單,就是要求不同的螢幕看上去效果一樣就可以了。這樣就需要我們佈局的時候採用百分比來定位。
說到百分比,我們第一時間想到的是layout_weight,但是layout_weight實際使用效果並不是很好,特別是一些複雜情況下需要層層巢狀。也無法解決所有問題,比如文字大小。

我想到的解決方案是根據螢幕大小重新對佈局以及佈局內部物件的大小進行調整。之前做過的一些專案裡面的自定義view也用過這種方法。
我在網上也搜到了一些相關資料,比如
Vanteon Electronic Design  
。說明這種方法是可行的。剩下的問題就是怎麼把這種方式封裝成一個通用的解決方案,能以最簡便的方式融入到開發中來。

經過一番實驗,我初步開發出來了AutoScalingLayout
原始碼:https://github.com/Junhua102/AutoScalingLayout

實現原理:

原理類似我們用播放器看視訊的時候,無論怎麼調整視窗大小,播放器都可以自動調整視訊大小適合視窗大小。因為視訊有一個原始解析度,播放器會根據視窗實際大小對視訊進行縮放。

我們寫佈局的時候一般是根據某個基準解析度來(比如UI給的原型圖),自動縮放佈局的作用就是將這個基準佈局乘以一個縮放比例,達到適配所有解析度的目的。

計算縮放比例公式: 實際大小 / 設計大小 = 縮放比例
只需要給定一個設計大小,就可以計算出縮放比例,然後將佈局內部所有元素的尺寸都乘以這個縮放比例,就可以適配實際螢幕了。


使用方法:
studio使用者使用release/AutoScalingLayout.aar
eclipse使用者使用release/AutoScalingLayout.jar,並將attr.xml複製到value目錄

替換佈局:

只需要替換需要縮放的根佈局即可,內部子佈局會自動縮放

原佈局 自動縮放佈局
RelativeLayout  ASRelativeLayout
LinearLayout  ASLinearLayout
FrameLayout  ASFrameLayout
目前只支援以上3種佈局

新增屬性:
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    custom:designWidth="384dp"
    custom:designHeight="575dp"
    custom:autoScaleEnable="true"
    custom:autoScaleType="fitInside"

designWidth和designHeight就是你在視覺化編輯xml時使用的螢幕大小。比如我使用的是Nexus 4,螢幕尺換算成dp就是384dp和575dp(減去狀態列和操作欄)

autoScaleEnable 用來開啟和關閉自動縮放,預設開啟

autoScaleType 設定縮放模式,可以設為“fitWidth”,"fitHeigth" 和 "fitInside"。分別代表縮放至寬度匹配,縮放至高度匹配以及縮放至適合容器內部,預設為"fitInside"。

注意事項

1.designWidth和designHeight非常重要,千萬不要填錯,否則縮放出來就不是你想要的效果了。
2.如果designWidth和designHeight的單位是dp,那麼所有內部子view的單位都必須是dp,不能寫px、pt等其他單位。文字大小也不能用sp。如果你想無腦照抄UI給出的畫素值,就全部單位用px就可以了。

3.AutoScalingLayout縮放時會保持deginWidth和designHeight的縱橫比,不用擔心正方形變矩形。

以sample中的 activity_login_dp.xml 為例

<me.dreamheart.autoscalinglayout.ASRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    custom:designWidth="384dp"
    custom:designHeight="575dp"
    custom:autoScaleEnable="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".LoginActivity"
    android:background="@drawable/login_bg"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:text="Title"
        android:textSize="30dp"
        android:textColor="#fff"
        android:layout_centerHorizontal="true"
        />

    <View android:id="@+id/login_input_form"
        android:layout_width="270dp"
        android:layout_height="100dp"
        android:layout_marginTop="125dp"
        android:layout_centerHorizontal="true"
        android:background="@drawable/login_input_form"
        />

    <TextView android:id="@+id/user_name_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="140dp"
        android:layout_marginLeft="16dp"
        android:layout_alignLeft="@+id/login_input_form"
        android:text="@string/user_name"
        android:textSize="15dp"
        android:textColor="#666"
        />

    <TextView android:id="@+id/password_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="190dp"
        android:layout_alignLeft="@+id/user_name_tv"
        android:text="@string/password"
        android:textSize="15dp"
        android:textColor="#666"
        />

    <EditText android:id="@+id/user_name"
        android:layout_toRightOf="@+id/user_name_tv"
        android:layout_marginLeft="10dp"
        android:layout_alignBaseline="@+id/user_name_tv"
        android:layout_height="wrap_content"
        android:layout_width="190dp"
        android:textSize="15dp"
        android:textColor="#444"
        android:hint="@string/prompt_name"
        android:inputType="text"
        android:maxLines="1"
        android:singleLine="true" />

    <EditText android:id="@+id/password"
        android:layout_toRightOf="@+id/user_name_tv"
        android:layout_marginLeft="10dp"
        android:layout_alignBaseline="@+id/password_tv"
        android:layout_height="wrap_content"
        android:layout_width="190dp"
        android:textSize="15dp"
        android:textColor="#444"
        android:hint="@string/prompt_password"
        android:inputType="textPassword"
        android:maxLines="1" android:singleLine="true" />

    <Button android:id="@+id/email_sign_in_button"
        android:background="@drawable/login_btn_selector"
        android:layout_marginTop="260dp"
        android:layout_centerHorizontal="true"
        android:layout_width="270dp"
        android:layout_height="40dp"
        android:text="@string/action_sign_in"
        android:textSize="20dp"
        android:textColor="#444"
        android:textStyle="bold" />

</me.dreamheart.autoscalinglayout.ASRelativeLayout>


未使用AutoScalingLayout


使用AutoScalingLayout