跳到主要內容

圖片

靜態圖片資源

React Native 提供了一種統一的方式來管理您的 Android 和 iOS 應用程式中的圖片和其他媒體資源。若要將靜態圖片新增到您的應用程式,請將其放置在程式碼樹狀結構中的某處,並像這樣參考它

tsx
<Image source={require('./my-icon.png')} />

圖片名稱的解析方式與 JS 模組的解析方式相同。在上面的範例中,打包器將在與需要它的組件相同的資料夾中尋找 my-icon.png

您可以使用 @2x@3x 後綴來為不同的螢幕密度提供圖片。如果您有以下檔案結構

.
├── button.js
└── img
├── check.png
├── check@2x.png
└── check@3x.png

...以及 button.js 程式碼包含

tsx
<Image source={require('./img/check.png')} />

...打包器將會打包並提供與裝置螢幕密度相對應的圖片。例如,check@2x.png 將在 iPhone 7 上使用,而 check@3x.png 將在 iPhone 7 Plus 或 Nexus 5 上使用。如果沒有與螢幕密度相符的圖片,將會選擇最接近的最佳選項。

在 Windows 上,如果您將新圖片新增到專案中,可能需要重新啟動打包器。

以下是您獲得的一些好處

  1. Android 和 iOS 上相同的系統。
  2. 圖片與您的 JavaScript 程式碼位於相同的資料夾中。組件是獨立的。
  3. 沒有全域命名空間,也就是說,您不必擔心名稱衝突。
  4. 只有實際使用的圖片才會被打包到您的應用程式中。
  5. 新增和變更圖片不需要重新編譯應用程式,您可以像平常一樣重新整理模擬器。
  6. 打包器知道圖片尺寸,無需在程式碼中重複。
  7. 圖片可以透過 npm 套件發佈。

為了使此功能正常運作,require 中的圖片名稱必須是靜態已知的。

tsx
// GOOD
<Image source={require('./my-icon.png')} />;

// BAD
const icon = this.props.active
? 'my-icon-active'
: 'my-icon-inactive';
<Image source={require('./' + icon + '.png')} />;

// GOOD
const icon = this.props.active
? require('./my-icon-active.png')
: require('./my-icon-inactive.png');
<Image source={icon} />;

請注意,以此方式要求的圖片來源包含圖片的大小(寬度、高度)資訊。如果您需要動態縮放圖片(例如透過 flex),您可能需要在樣式屬性上手動設定 {width: undefined, height: undefined}

靜態非圖片資源

上面描述的 require 語法也可用於靜態地將音訊、視訊或文件檔案包含在您的專案中。支援大多數常見的檔案類型,包括 .mp3.wav.mp4.mov.html.pdf。請參閱 打包器預設值 以取得完整清單。

您可以透過在您的 Metro 設定 中新增 assetExts 解析器選項 來新增對其他類型的支援。

一個需要注意的事項是,視訊必須使用絕對定位而不是 flexGrow,因為目前未傳遞非圖片資源的大小資訊。直接連結到 Xcode 或 Android 的 Assets 資料夾的視訊不會發生此限制。

來自混合應用程式資源的圖片

如果您正在建置混合應用程式(一些 UI 在 React Native 中,一些 UI 在平台程式碼中),您仍然可以使用已經捆綁到應用程式中的圖片。

對於透過 Xcode 資產目錄或 Android drawable 資料夾包含的圖片,請使用不含副檔名的圖片名稱

tsx
<Image
source={{uri: 'app_icon'}}
style={{width: 40, height: 40}}
/>

對於 Android assets 資料夾中的圖片,請使用 asset:/ 方案

tsx
<Image
source={{uri: 'asset:/app_icon.png'}}
style={{width: 40, height: 40}}
/>

這些方法不提供安全檢查。您有責任保證這些圖片在應用程式中可用。此外,您必須手動指定圖片尺寸。

網路圖片

您將在應用程式中顯示的許多圖片在編譯時可能不可用,或者您可能希望動態載入一些圖片以縮減二進制檔案大小。與靜態資源不同,您需要手動指定圖片的尺寸。強烈建議您也使用 https,以滿足 iOS 上的 App Transport Security 要求。

tsx
// GOOD
<Image source={{uri: 'https://react.dev.org.tw/logo-og.png'}}
style={{width: 400, height: 400}} />

// BAD
<Image source={{uri: 'https://react.dev.org.tw/logo-og.png'}} />

圖片的網路請求

如果您想要設定 HTTP-Verb、Headers 或 Body 等項目以及圖片請求,您可以透過在來源物件上定義這些屬性來完成

tsx
<Image
source={{
uri: 'https://react.dev.org.tw/logo-og.png',
method: 'POST',
headers: {
Pragma: 'no-cache',
},
body: 'Your Body goes here',
}}
style={{width: 400, height: 400}}
/>

URI 資料圖片

有時,您可能會從 REST API 呼叫中取得編碼的圖片資料。您可以使用 'data:' URI 方案來使用這些圖片。與網路資源相同,您需要手動指定圖片的尺寸

資訊

建議僅用於非常小且動態的圖片,例如來自 DB 列表中的圖示。

tsx
// include at least width and height!
<Image
style={{
width: 51,
height: 51,
resizeMode: 'contain',
}}
source={{
uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==',
}}
/>

快取控制

在某些情況下,您可能只想在圖片已在本地快取中時才顯示圖片,例如低解析度佔位符,直到有更高解析度可用。在其他情況下,您不介意圖片是否已過時,並且願意顯示過時的圖片以節省頻寬。cache 來源屬性可讓您控制網路層與快取互動的方式。

  • default:使用原生平台的預設策略。
  • reload:URL 的資料將從原始來源載入。不應使用現有的快取資料來滿足 URL 載入請求。
  • force-cache:現有的快取資料將用於滿足請求,無論其存在時間或到期日為何。如果快取中沒有與請求對應的現有資料,則資料會從原始來源載入。
  • only-if-cached:現有的快取資料將用於滿足請求,無論其存在時間或到期日為何。如果快取中沒有與 URL 載入請求對應的現有資料,則不會嘗試從原始來源載入資料,並且載入會被視為失敗。
tsx
<Image
source={{
uri: 'https://react.dev.org.tw/logo-og.png',
cache: 'only-if-cached',
}}
style={{width: 400, height: 400}}
/>

本機檔案系統圖片

請參閱 CameraRoll 以取得使用 Images.xcassets 外部本機資源的範例。

Drawable 資源

Android 支援透過 xml 檔案類型載入 drawable 資源。這表示您可以使用 向量繪圖 來渲染圖示,或使用 形狀繪圖 來繪製形狀!您可以像任何其他 靜態資源混合資源 一樣匯入和使用這些資源類型。您必須手動指定圖片尺寸。

對於與您的 JS 程式碼並存的靜態 drawable,請使用 requireimport 語法(兩者效果相同)

tsx
<Image
source={require('./img/my_icon.xml')}
style={{width: 40, height: 40}}
/>

對於包含在 Android drawable 資料夾(即 res/drawable)中的 drawable,請使用不含副檔名的資源名稱

tsx
<Image
source={{uri: 'my_icon'}}
style={{width: 40, height: 40}}
/>

drawable 資源與其他圖片類型之間的一個主要區別在於,資源必須在 Android 應用程式的編譯時參考,因為 Android 需要執行 Android Asset Packaging Tool (AAPT) 來打包資源。AAPT 建立的檔案格式 Binary XML 無法透過 Metro 在網路上載入。如果您變更資源的目錄或名稱,您每次都需要重建 Android 應用程式。

建立 XML drawable 資源

Android 在其 Drawable 資源 指南中提供了關於每個支援的 drawable 資源類型的完整文件,以及原始 XML 檔案的範例。您可以使用 Android Studio 中的工具,例如 Vector Asset Studio,從可縮放向量圖形 (SVG) 和 Adobe Photoshop 文件 (PSD) 檔案建立向量繪圖。

資訊

如果您想將 XML 檔案視為靜態圖片資源(即使用 importrequire 語句),您應該盡量避免在您建立的 XML 檔案中參考其他資源。如果您希望利用對其他 drawable 或屬性的參考,例如 顏色狀態列表尺寸資源,您應該將您的 drawable 作為 混合資源 包含並依名稱匯入。

最佳相機膠卷圖片

iOS 會在您的相機膠卷中儲存同一張圖片的多種尺寸,基於效能考量,選擇最接近的尺寸非常重要。當顯示 200x200 的縮圖時,您不會想使用全尺寸 3264x2448 的圖片作為來源。如果存在完全符合的尺寸,React Native 將會選擇它,否則它將使用第一個至少大 50% 的尺寸,以避免從接近的尺寸調整大小時產生模糊。所有這些都是預設完成的,因此您不必擔心編寫繁瑣(且容易出錯)的程式碼來自行完成。

為什麼不自動調整所有尺寸?

在瀏覽器中,如果您沒有為圖片指定尺寸,瀏覽器將會渲染一個 0x0 元素,下載圖片,然後根據正確的尺寸渲染圖片。這種行為的最大問題是,當圖片載入時,您的 UI 會到處跳動,這會造成非常糟糕的使用者體驗。這稱為 累計版面配置偏移

在 React Native 中,此行為有意未實作。開發人員需要事先知道遠端圖片的尺寸(或長寬比)會比較麻煩,但我們相信這會帶來更好的使用者體驗。透過 require('./my-icon.png') 語法從應用程式套件載入的靜態圖片可以自動調整大小,因為它們的尺寸在掛載時立即可用。

例如,require('./my-icon.png') 的結果可能是

tsx
{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573}

來源作為物件

在 React Native 中,一個有趣的決定是 src 屬性被命名為 source,並且不接受字串,而是接受具有 uri 屬性的物件。

tsx
<Image source={{uri: 'something.jpg'}} />

在基礎架構方面,原因是它允許我們將元資料附加到此物件。例如,如果您使用 require('./my-icon.png'),那麼我們會新增有關其實際位置和大小的資訊(不要依賴此事實,它將來可能會變更!)。這也是面向未來的,例如,我們可能希望在某些時候支援 sprites,而不是輸出 {uri: ...},我們可以輸出 {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}} 並透明地支援所有現有呼叫站點上的 spriting。

在使用者方面,這可讓您使用有用的屬性(例如圖片的尺寸)註解物件,以便計算其將顯示的大小。隨時將其用作您的資料結構,以儲存有關圖片的更多資訊。

透過巢狀結構的背景圖片

來自熟悉 Web 的開發人員的常見功能請求是 background-image。為了處理此用例,您可以使用 <ImageBackground> 組件,該組件具有與 <Image> 相同的 props,並將您想要圖層疊在其上的任何子項新增到其中。

在某些情況下,您可能不想使用 <ImageBackground>,因為實作很基本。請參閱 <ImageBackground>文件 以獲得更多見解,並在需要時建立您自己的自訂組件。

tsx
return (
<ImageBackground source={...} style={{width: '100%', height: '100%'}}>
<Text>Inside</Text>
</ImageBackground>
);

請注意,您必須指定一些寬度和高度樣式屬性。

iOS 邊框圓角樣式

請注意,iOS 的圖片組件可能會忽略以下角落特定的邊框圓角樣式屬性

  • borderTopLeftRadius
  • borderTopRightRadius
  • borderBottomLeftRadius
  • borderBottomRightRadius

Off-thread 解碼

圖片解碼可能需要超過一個 frame 的時間。這是網頁上 frame 掉幀的主要來源之一,因為解碼是在主執行緒中完成的。在 React Native 中,圖片解碼是在不同的執行緒中完成的。實際上,您已經需要處理圖片尚未下載的情況,因此在解碼時顯示佔位符多幾個 frame 不需要任何程式碼變更。

設定 iOS 圖片快取限制

在 iOS 上,我們公開了一個 API 來覆寫 React Native 的預設圖片快取限制。這應該從您的原生 AppDelegate 程式碼中呼叫(例如在 didFinishLaunchingWithOptions 中)。

objectivec
RCTSetImageCacheLimits(4*1024*1024, 200*1024*1024);

參數

名稱類型必要描述
imageSizeLimitnumber圖片快取大小限制。
totalCostLimitnumber總快取成本限制。

在上面的程式碼範例中,圖片大小限制設定為 4 MB,總成本限制設定為 200 MB。