1.背景
本文使用的RN(使用RN表示React Native)的版本為0.44版本。在應(yīng)用的開發(fā)過程射窒,可能會遇到這么一種場景霹崎,就是在圖片的拉伸過程中蕾各,需要保持部分區(qū)域不被拉伸,而部分區(qū)域需要進行拉伸袱箱。比如IM中聊天的背景氣泡等遏乔。那么這個時候我們就可能需要使用到點9圖片。那么在RN中发笔,該如何使用點9圖片呢盟萨?
2.RN上顯示點9圖片的思路
首先既然是圖片,那么在RN中肯定是需要在組件Image中進行顯示了讨,那么RN的Image可以同時支持Android和ios平臺的點9圖片的制作和顯示嗎捻激?我們?nèi)ス俜降腁pi文檔上找找看。在RN的文檔上我們看到了這樣的介紹
ios
capInsets {top: number, left: number, bottom: number, right: number}
當(dāng)圖片被縮放的時候前计,capInsets指定的角上的尺寸會被固定而不進行縮放胞谭,而中間和邊上其他的部分則會被拉伸。這在制作一些可變大小的圓角按鈕男杈、陰影丈屹、以及其它資源的時候非常有用(譯注:這就是常說的九宮格或者.9圖。了解更多信息伶棒,可以參見[蘋果官方文檔]
可以看到RN的Image組件是可以直接支持capInsets屬性旺垒,對我們需要的圖片進行對應(yīng)的拉伸操作,這與ios原生的使用是一樣的苞冯,那么在Android平臺上該如何使用呢袖牙?很遺憾,在RN上并沒有這方面的介紹舅锄。
??做過Android原生開發(fā)的可能知道鞭达,在Android平臺上是可以通過工具制作點9圖片司忱,然后作為背景圖片直接使用,那么按照這個思路畴蹭,我們可以在Android封裝對應(yīng)的組件坦仍,然后在Android平臺上要使用的時候就直接使用制作好的點9圖片,而在ios平臺上我們使用capInsets屬性叨襟。
3.React Native 9patch image
在這里繁扎,我們找到了一個封裝好的開源組件,Github地址:https://github.com/rusfearuth/react-native-9patch-image 我們來看下它在Android平臺下的封裝思路
public class RCTImageCapInsetManager extends SimpleViewManager<RCTImageCapInsetView> {
@Override
public String getName() {
return "RCTImageCapInset";
}
@Override
protected RCTImageCapInsetView createViewInstance(ThemedReactContext reactContext) {
return new RCTImageCapInsetView(reactContext);
}
@ReactProp(name = "source")
public void setSource(final RCTImageCapInsetView view, ReadableMap source) {
String uri = source.getString("uri");
view.setSource(uri);
}
}
首先從source中獲取uri的地址糊闽,然后將其賦值給這里的RCTImageCapInsetView梳玫,而對于RCTImageCapInsetView
public class RCTImageCapInsetView extends ImageView {
private String mUri;
public RCTImageCapInsetView(Context context) {
super(context);
}
public void setSource(String uri) {
mUri = uri;
reload();
}
public void reload() {
Integer resId = null;
if (getImageCache().has(mUri)) {
resId = getImageCache().get(mUri);
if (resId == null) {
getImageCache().remove(mUri);
}
}
if (resId == null) {
resId = getResourceDrawableId(mUri);
getImageCache().put(mUri, resId);
}
setBackgroundResource(resId);
}
private @NonNull Integer getResourceDrawableId(@NonNull final String aName) {
if (aName == null || aName.isEmpty()) {
return 0;
}
final String name = aName.toLowerCase().replace("-", "_");
return getResources().getIdentifier(
name,
"drawable",
getContext().getPackageName()
);
}
private RCTImageCache getImageCache()
{
return RCTImageCache.getInstance();
}
}
RCTImageCapInsetView的本質(zhì)是一個ImageView,獲取到uri的名稱右犹,然后在drawable之中查找到對應(yīng)的id名稱提澎,最后得到圖片資源作為ImageView背景,跟我們在Android原生上使用點9圖片的方式是一樣的念链。
4.制作點9圖片
4.1 Android平臺下制作
在這里我們用到的是Android上默認(rèn)的logo圖片
??將其賦值到res/drawable目錄下盼忌,并將其改名為image.9.png,在android studio中雙擊打開它掂墓,選擇9-patch模式
??這個時候我們就可以直接在android studio直接進行點9圖片的制作谦纱,當(dāng)然我們也可以打開android sdk中提供的點9圖片制作工具進行制作,工具路徑為:/Users/hzl/Library/Android/sdk/tools/draw9patch 至于如何點9圖片的上下左右邊界代表的意思君编,這里不作過多的闡述跨嘉,可以通過百度,Google等去搜索相關(guān)的介紹啦粹。這樣Android平臺上的點9圖片就制作完成了偿荷。
4.2 ios平臺下制作
在上面我們制作了Android平臺下的點9圖片,那么在ios平臺上唠椭,對應(yīng)的capInsets屬性是多少呢跳纳?我們把鼠標(biāo)懸停在邊界上
可以看到Horizontal Patch:29-66px,那么對應(yīng)的capInsets屬性中的left和right就是29和29(95-66=29贪嫂,其中95是原始圖片的寬)寺庄,同理根據(jù)Vertical Patch:40-86px,可以知道capInsets屬性中的top和bottom就是40和9
5.RN上顯示點9圖片
在上面中我們制作好了對應(yīng)的點9圖片力崇,那么我們分別在Android和ios平臺上看下效果如果斗塘。
import React, {Component} from 'react';
import {View, Platform} from 'react-native';
import NinePatchView from 'react-native-9patch-image';
export default class Main extends Component {
render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<NinePatchView
style={{width: 200, height: 200}}
source={Platform.OS === 'android' ? {uri: 'image'} : require('./image.png')}
capInsets={{top: 40, left: 29, bottom: 9, right: 29}}/>
</View>)
}
}
這里要特別注意的是Android平臺要使用Release版本的apk才可以看到效果,至于如何打包Android Release版本apk亮靴,可以去看下RN官方文檔上的介紹,http://reactnative.cn/docs/0.43/signed-apk-android.html#content
??可以看到馍盟,兩個平臺上的顯示效果是一致的。
6.最后
文章中使用的例子已經(jīng)上傳了Github:https://github.com/hzl123456/NinePatchView