Android 屏幕適配全攻略(中)-從九宮格到矢量圖,揭秘Android多屏幕適配的正確打開方式


在移動互聯網時代,無論是小小的手機屏幕,還是大大的平板顯示器,Android 應用都必須做到完美適配,給用戶以極佳的體驗。本文將剖析 Android 多屏幕適配背后的種種技術細節,為您揭開最佳實踐的正確打開方式,讓您的應用在任何設備上都能呈現出最專業、最優雅的一面。


一、Android 布局適配


布局適配主要包括以下幾個方面:

  1. 使用合理的布局方式
    • 選擇合適的布局容器,如 LinearLayoutRelativeLayoutConstraintLayout 等。
    • 合理地使用 wrap_contentmatch_parent 等屬性來根據內容自適應布局大小。
    • 適當使用 weight 屬性來實現動態布局。
  2. 使用多尺寸資源
    • res/layout-* 目錄下提供不同屏幕尺寸的布局文件。
    • res/values-* 目錄下提供不同屏幕尺寸的尺寸資源。
    • res/drawable-* 目錄下提供不同屏幕尺寸的圖片資源。
  3. 動態適配布局
    • 在代碼中動態獲取屏幕尺寸和密度信息。
    • 根據獲取的信息動態調整 UI 元素的大小和位置。
  4. 適配不同屏幕方向
    • res/layout-land 目錄下提供橫屏布局文件。
    • 在代碼中監聽屏幕方向變化,動態切換布局。

下面示例,演示如何在 Java 代碼中動態適配布局:

public class MainActivity extends AppCompatActivity {private TextView textView;private FrameLayout.LayoutParams layoutParams;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textView = findViewById(R.id.text_view);layoutParams = (FrameLayout.LayoutParams) textView.getLayoutParams();// 獲取屏幕尺寸和密度信息DisplayMetrics displayMetrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);int screenWidth = displayMetrics.widthPixels;int screenHeight = displayMetrics.heightPixels;float density = displayMetrics.density;// 根據屏幕尺寸和密度動態調整 TextView 的大小和位置int textViewWidth = (int) (200 * density);int textViewHeight = (int) (100 * density);layoutParams.width = textViewWidth;layoutParams.height = textViewHeight;layoutParams.gravity = Gravity.CENTER;textView.setLayoutParams(layoutParams);}
}

在這個示例中,我們首先獲取了當前設備的屏幕尺寸和密度信息。然后,根據這些信息動態地調整了 TextView 的大小和位置,確保它在不同設備上顯示的效果一致。


二、使用限定符資源,輕松匹配不同屏幕尺寸


1、什么是限定符資源?

  • 限定符資源是 Android 用于支持多種設備屏幕尺寸和密度的一種機制。

  • 開發者可以在應用的資源目錄下創建多個不同的資源文件夾,每個文件夾都包含了針對特定設備特征的資源文件。

  • 當應用運行在某臺設備上時,Android 系統會根據該設備的特征,自動選擇最匹配的資源文件夾,并加載相應的資源。


2、常見的限定符

  • 屏幕尺寸: small, normal, large, xlarge

  • 屏幕密度: ldpi, mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi

  • 屏幕方向: port (portrait), land (landscape)

  • 語言和地區: en, fr, zh-rCN, zh-rTW 等

  • Android 版本: v21, v23, v26 等


3、如何使用限定符資源


(1)、在應用的res目錄下,創建不同的資源文件夾,并在文件夾名稱中添加相應的限定符:

  • res/layout/:默認布局文件

  • res/layout-large/:針對大屏幕設備的布局文件

  • res/layout-land/:針對橫屏設備的布局文件

  • res/drawable-hdpi/:針對高密度設備的圖片資源

  • res/values-zh-rCN/:針對中國大陸地區的字符串資源


(2)、在代碼中,直接引用這些資源文件即可

Android 系統會根據設備特征自動選擇合適的資源文件。

  • 假設我們有以下幾個資源文件:

    • res/layout/activity_main.xml
    • res/layout-large/activity_main.xml
    • res/layout-land/activity_main.xml
    • res/drawable-hdpi/my_image.png

  • 在 Java 代碼中,我們可以這樣使用這些資源:

    // 加載布局文件
    setContentView(R.layout.activity_main);// 獲取圖片資源
    ImageView imageView = findViewById(R.id.my_image);
    imageView.setImageResource(R.drawable.my_image);// 獲取字符串資源
    String myString = getString(R.string.my_string);
    

  • 當應用運行在不同的設備上時,Android 系統會自動選擇最合適的資源文件進行加載。例如:

    • 在小屏幕設備上,使用 res/layout/activity_main.xml
    • 在大屏幕設備上,使用 res/layout-large/activity_main.xml
    • 在橫屏設備上,使用 res/layout-land/activity_main.xml
    • 在高密度設備上,使用 res/drawable-hdpi/my_image.png

二、九宮格圖片適配


除了布局適配,圖片資源的適配同樣很關鍵。我們可以為不同分辨率提供對應分辨率的圖片:

res/drawable-mdpi/image.png
res/drawable-hdpi/image.png 
...

不過這種做法會使 APK 體積變大。從 Android 4.0 開始,就可以使用九宮格圖片 (.9.png) 來渲染可拉伸的資源。


1、什么是九宮格圖片資源?

九宮格圖片資源(Nine-Patch Images)是一種特殊的圖片格式,它可以根據圖片的內容自動拉伸或縮放,而不會造成圖片失真或模糊。它通常用于實現可伸縮的 UI 元素,如按鈕、對話框等。


九宮格圖片由以下9個區域組成:

  • 四個角落區域(不可拉伸)

  • 上下中間區域(只能水平拉伸)

  • 左右中間區域(只能垂直拉伸)

  • 中間區域(可以水平和垂直拉伸)


在這里插入圖片描述


2、如何使用九宮格圖片資源?


(1)、創建九宮格圖片

  • 在 Android Studio 的 drawable 文件夾中創建一個以 .9.png 結尾的文件,表示這是一個九宮格圖片。
  • 使用圖像編輯工具(如 GIMP、Photoshop 等)繪制圖像,并在圖像的左側和上側添加黑色像素邊框。這些額外的邊框將定義圖像的可拉伸區域。

(2)、在布局中使用九宮格圖片

  • 在 XML 布局文件中,將九宮格圖片資源設置為 View 的背景:

    <Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/my_nine_patch" />
    

(3)、在代碼中使用九宮格圖片

  • 可以使用NinePatchDrawable類動態創建和應用九宮格圖片:

    // 從資源文件中獲取九宮格圖片
    NinePatchDrawable drawable = (NinePatchDrawable) ContextCompat.getDrawable(context, R.drawable.my_nine_patch);// 設置九宮格圖片為 View 的背景
    view.setBackground(drawable);
    

下面示例,演示如何使用九宮格圖片資源:

import android.content.Context;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;public class NinePatchExampleActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_nine_patch_example);// 獲取 LinearLayoutLinearLayout container = findViewById(R.id.container);// 創建 3 個 Buttonfor (int i = 0; i < 3; i++) {Button button = createButton(this);container.addView(button);}}private Button createButton(Context context) {// 創建 ButtonButton button = new Button(context);button.setText("Nine-Patch Button");// 獲取九宮格圖片資源NinePatchDrawable drawable = (NinePatchDrawable) ContextCompat.getDrawable(context, R.drawable.my_nine_patch);// 設置九宮格圖片為 Button 的背景button.setBackground(drawable);// 設置 Button 的寬度和高度LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);button.setLayoutParams(params);return button;}
}

在這個示例中,我們創建了一個 NinePatchExampleActivity。在 onCreate() 方法中,我們獲取 LinearLayout 容器,并動態創建了 3 個 Button


createButton() 方法中,我們首先創建一個 Button 對象,并設置它的文本為"Nine-Patch Button"。然后,我們使用 ContextCompat.getDrawable() 獲取九宮格圖片資源,并使用 NinePatchDrawable 類將其設置為 Button 的背景。最后,我們設置 Button 的寬度和高度,并返回 Button 對象。


當你運行這個程序時,你會看到 3 個使用九宮格圖片資源作為背景的 Button。無論 Button 的大小如何變化,它們的外觀都不會失真。

通過這個示例,相信你已經掌握了如何在 Android 開發中使用九宮格圖片資源進行適配的基本方法。這種技術可以幫助你創建出更加美觀、適配性強的 UI 元素。


隨后 Android 5.0 又推出了矢量圖形式,可自動縮放且不失真,這成為圖片適配的最佳選擇。


四、矢量圖形式適配


1、為什么要使用矢量圖?


在 Android 開發中,我們通常會使用位圖圖像(如 PNG、JPEG 等)來作為應用程序的圖標和UI元素。但是,這種方式存在一些問題:


  • 圖像質量下降

    當位圖圖像在不同分辨率的設備上顯示時,可能會出現圖像質量下降的問題。這是因為位圖圖像是由固定大小的像素組成的,在進行縮放時會導致失真。


  • 文件體積增大

    為了適配不同分辨率的設備,開發者通常需要準備多套不同尺寸的圖像資源,這會大大增加應用程序的安裝包體積。


為了解決這些問題,Android 提供了矢量圖形式(Vector Drawable)作為一種新的圖像資源格式。矢量圖使用可縮放的數學公式來描述圖形,能夠在任何分辨率下保持優質的圖像質量,同時文件體積也相對較小。


2、如何使用矢量圖進行屏幕適配?


(1)、創建矢量圖資源

  • 您可以使用 Android Studio 自帶的 Vector Asset Studio 工具來創建矢量圖資源。

  • 也可以使用其他矢量圖編輯工具(如 Adobe Illustrator、Sketch 等)來創建 SVG 格式的矢量圖,然后導入到 Android Studio 項目中。


(2)、在布局中使用矢量圖

  • 在 XML 布局文件中,使用 <vector> 標簽來引用矢量圖資源:

    <ImageViewandroid:layout_width="48dp"android:layout_height="48dp"android:src="@drawable/my_vector_icon" />
    

(3)、在代碼中使用矢量圖

  • 在 Java 代碼中,可以使用 VectorDrawableCompat 類來加載和使用矢量圖資源:

    Drawable vectorDrawable = VectorDrawableCompat.create(getResources(), R.drawable.my_vector_icon, null);
    imageView.setImageDrawable(vectorDrawable);
    

(4)、適配不同屏幕密度

  • 矢量圖本身是可縮放的,因此不需要為不同屏幕密度準備多套圖像資源。

  • 但是,仍然需要為不同的屏幕密度提供合適的圖標尺寸,以確保在各種設備上都能夠正常顯示。

  • 可以使用 VectorDrawableCompat.create 方法,并傳入 DisplayMetrics 對象來動態調整圖標大小

    DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
    float density = displayMetrics.density;
    Drawable vectorDrawable = VectorDrawableCompat.create(getResources(), R.drawable.my_vector_icon, null);
    vectorDrawable.setBounds(0, 0, (int)(48 * density), (int)(48 * density));
    imageView.setImageDrawable(vectorDrawable);
    

(5)、使用矢量圖進行屏幕適配完整案例

下面是一個完整的 Java 代碼示例,演示如何在 Android 中使用矢量圖進行屏幕適配:

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.widget.ImageView;import androidx.appcompat.app.AppCompatActivity;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;public class VectorDrawableActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_vector_drawable);ImageView imageView = findViewById(R.id.image_view);loadVectorDrawable(this, imageView, R.drawable.my_vector_icon, 48);}private void loadVectorDrawable(Context context, ImageView imageView, int vectorDrawableId, int desiredSizeDp) {DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();float density = displayMetrics.density;int desiredSizePx = (int) (desiredSizeDp * density);Drawable vectorDrawable = VectorDrawableCompat.create(context.getResources(), vectorDrawableId, null);vectorDrawable.setBounds(0, 0, desiredSizePx, desiredSizePx);imageView.setImageDrawable(vectorDrawable);}
}

在這個示例中,我們首先在 onCreate() 方法中加載了一個矢量圖資源并將其設置到 ImageView 上。

然后,我們定義了一個 loadVectorDrawable() 方法,它接受四個參數:

  • context: 上下文對象

  • imageView: 要設置矢量圖的 `ImageView``

  • ``vectorDrawableId`: 矢量圖資源的 ID

  • desiredSizeDp: 期望的圖標尺寸(以 dp 為單位)


在方法內部,我們首先獲取設備的屏幕密度,并根據期望的尺寸計算出實際的像素尺寸。然后,我們使用 VectorDrawableCompat.create() 方法加載矢量圖資源,并設置其大小,最后將其設置到 ImageView 上。


通過這種方式,我們可以在不同的屏幕密度下都能正確、清晰地顯示矢量圖,同時也大大減少了應用程序的安裝包體積。

結語:

總之,隨著各種全面屏、異形屏和可折疊屏的出現,Android 屏幕適配也變得越發重要和復雜。相信通過本文的詳盡指導,您已經掌握了多屏幕適配的方方面面。不過在實際應用中屏幕適配永無止境, 還可能會遇到哪些其他問題和挑戰呢?就讓我們拭目以待,繼續在這方面的實戰中去探索和總結吧!


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/9915.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/9915.shtml
英文地址,請注明出處:http://en.pswp.cn/web/9915.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

速賣通ip地址會相互影響嗎?如何防止賬號關聯?

在跨境電商行業&#xff0c;大部分平臺都是不允許一個賣家操作多個店鋪的&#xff0c;如果被平臺檢測出賬戶關聯&#xff0c;可能會被封店。在速賣通平臺&#xff0c;會通過IP地址來判斷是否經營多個賬號嗎?IP地址會使店鋪相互影響嗎? 一、速賣通IP地址會關聯嗎? 首先各位賣…

解決mybatis的配置文件沒代碼提示的問題

1.將org.apache.ibatis.builder.xml包里的兩個dtd文件復制出來&#xff0c;jar包里復制 2.復制dtd的url地址&#xff1a; http://mybatis.org/dtd/mybatis-3-mapper.dtd 一樣的做法&#xff01; 3.關閉兩個配置文件&#xff0c;重新打開&#xff0c;就可以有代碼提示了&…

【智能優化算法】白鯊智能優化算法(White Shark Optimizer,WSO)

白鯊智能優化算法(White Shark Optimizer,WSO)是期刊“KNOWLEDGE-BASED SYSTEMS”&#xff08;中科院一區期刊 IF8.6&#xff09;的2022年智能優化算法 01.引言 白鯊智能優化算法(White Shark Optimizer,WSO)的核心理念和基礎靈感來自大白鯊的行為&#xff0c;包括它們在導航和…

從項目開始學習Vue——02(若依框架)

往期&#xff1a; 從項目開始學習Vue——01 目錄標題 一、基礎插件&#xff08;一&#xff09;路由Vue Router&#xff08;二&#xff09;導航守衛&#xff08;路由攔截器&#xff09;二、Vuex&#xff08;一&#xff09;什么是VuexVuex的部分介紹內容&#xff1a; &#xff08…

QQ超大文件共享(別用,傳進去后,壓縮都顯示不出來,LJ qq!)(共享文件)

文章目錄 需要共享雙方同時在線開啟方法第一次會提示設置默認共享目錄&#xff0c;默認是E:\QQFileShare\<qq號>\&#xff1a;然后新建共享會在其后創建共享目錄&#xff0c;共享目錄中只能共享文件。需要點擊添加文件&#xff0c;直接把文件拷貝到目錄里好像還不行&…

C語言/數據結構——(相交鏈表)

一.前言 今天在力扣上刷到了一道題&#xff0c;想著和大家一起分享一下這道題——相交鏈表https://leetcode.cn/problems/intersection-of-two-linked-lists廢話不多說&#xff0c;讓我們開始今天的分享吧。 二.正文 1.1題目描述 是不是感覺好長&#xff0c;我也這么覺得。哈…

網絡編程套接字和傳輸層tcp,udp協議

認識端口號 我們知道在網絡數據傳輸的時候&#xff0c;在IP數據包頭部有兩個IP地址&#xff0c;分別叫做源IP地址和目的IP地址。IP地址是幫助我們在網絡中確定最終發送的主機&#xff0c;但是實際上數據應該發送到主機上指定的進程上的&#xff0c;所以我們不僅要確定主機&…

OAuth 2.0 和 OAuth 2.1

OAuth 2.0 和 OAuth 2.1比較&#xff1a; OAuth 2.0 和 OAuth 2.1 是授權框架的不同版本&#xff0c;它們用于允許應用程序安全地訪問用戶在另一個服務上的數據。以下是它們之間的一些主要區別&#xff1a; 安全性增強&#xff1a;OAuth 2.1 旨在提高安全性&#xff0c;它整合…

什么是云原生架構,我們該如何做好云原生安全,引領云計算時代的應用程序革新

隨著云計算技術的飛速發展&#xff0c;企業面臨著前所未有的機遇和挑戰。在這個高度競爭的市場中&#xff0c;傳統的應用程序架構因其僵化、不易擴展和維護的特點&#xff0c;已難以滿足當今企業對靈活性、可伸縮性和高效性的追求。在這樣的背景下&#xff0c;云原生架構應運而…

git rebase 合并當前分支的多個commit記錄

git rebase 合并當前分支的多個commit記錄 git rebase 相關的選項和用法step1&#xff1a;找到想要合并的 commitstep2. 使用 rebase -istep3. 編輯提交歷史&#xff1a;step4.編輯合并后的提交信息step5.完成 rebase 過程&#xff1a;step6.**推送更新&#xff1a;**step6.**再…

使用ollama離線部署小模型

在有網的機器下載ollama和模型 啟動服務 docker run --rm -it -v ./ollama:/root/.ollama -p 8000:11434 --name ollama ollama/ollama下載模型 docker exec -it ollama ollama pull qwen:0.5b將鏡像和ollama目錄復制到離線的機器中 docker啟動ollama服務 驗證 curl ht…

FFmpeg常用API與示例(三)—— 音視頻解碼與編碼

編解碼層 1.解碼 (1) 注冊所有容器格式和 CODEC:av_register_all() (2) 打開文件:av_open_input_file() (3) 從文件中提取流信息:av_find_stream_info() (4) 窮舉所有的流&#xff0c;查找其中種類為 CODEC_TYPE_VIDEO (5) 查找對應的解碼器:avcodec_find_decoder() (6) …

C++ 實現以xml的格式寫入文件

C XML類 該類主要將xml中的標簽分為兩類&#xff0c;無內容標簽統一稱為父標簽&#xff0c;有內容的就以鍵值對的方式直接輸出。 后面可能會優化通過函數參數的方式管控層級關系&#xff0c;現在是通過類里自動記錄層級深度來表示的。 #include <fstream> #include <…

【QT教程】QT6硬件圖形界面編程 QT硬件編程

QT6硬件圖形界面編程 使用AI技術輔助生成 QT界面美化視頻課程 QT性能優化視頻課程 QT原理與源碼分析視頻課程 QT QML C擴展開發視頻課程 免費QT視頻課程 您可以看免費1000個QT技術視頻 免費QT視頻課程 QT統計圖和QT數據可視化視頻免費看 免費QT視頻課程 QT性能優化視頻免費看…

數據結構-二叉樹結尾+排序

一、二叉樹結尾 1、如何判斷一棵樹是完全二叉樹。 我們可以使用層序遍歷的思路&#xff0c;利用一個隊列&#xff0c;去完成層序遍歷&#xff0c;但是這里會有些許的不同&#xff0c;我們需要讓空也進隊列。如果隊列里到最后只剩下空那么這棵樹就是完全二叉樹。具體的實現如下…

js 數據格式轉換,對象轉數組,數組轉對象

1.對象轉數組 // 對象obj轉換成數組格式 let obj { orgCode:分局編碼, alertId:告警ID, name:告警名稱 } let arr [] for(let key in obj) { console.log(11,key,obj[key]); // 定義一個對象&#xff0c;賦值 let o { id: key, // key是obj對象的鍵值 label: obj[key] …

學習Vue 3.0中的onMounted和onUnmounted鉤子函數

學習Vue 3.0中的onMounted和onUnmounted鉤子函數 一、什么是onMounted和onUnmounted&#xff1f;二、如何使用onMounted和onUnmounted&#xff1f;1、使用onMounted2、使用onUnmounted 三、總結 一、什么是onMounted和onUnmounted&#xff1f; Vue 3.0帶來了許多令人興奮的新特…

Modal h函數寫法

Modal h函數寫法 if (res.data.flag) {const ocapWarn res.data.ocaplList;Modal.warning({title: "提示",content: h("div", {}, [ocapWarn.map((item, index) > {return h("div", {}, [h("p",${index 1}、${item.defectItem}(…

IntersectionObserver對象

IntersectionObserver對象 IntersectionObserver對象&#xff0c;從屬于Intersection Observer API&#xff0c;提供了一種異步觀察目標元素與其祖先元素或頂級文檔視窗viewport交叉狀態的方法&#xff0c;祖先元素與視窗viewport被稱為根root&#xff0c;也就是說Intersectio…

c#---多態

在 C#語言中體現多態有三種方式&#xff1a;虛方法&#xff0c;抽象類&#xff0c; 接口 一、虛方法 什么是虛方法&#xff1f; 在父類中使用 virtual 關鍵字修飾的方法&#xff0c; 就是虛方法。在子類中可以使用 override 關鍵字對該虛方法進行重寫。 class Animal {public…