一. 簡介 一個用於顯示多種不同類型圖片的React組件,包括網路圖片、靜態資源、臨時的本地圖片、以及本地磁碟上的圖片(如相冊)等。從0.14版本開始,React Native提供了一個統一的方式來管理iOS和Android應用中的圖片。要往App中添加一個靜態圖片,只需把圖片文件放在代碼文件夾比如 ...
一. 簡介
一個用於顯示多種不同類型圖片的React組件,包括網路圖片、靜態資源、臨時的本地圖片、以及本地磁碟上的圖片(如相冊)等。
從0.14版本開始,React Native提供了一個統一的方式來管理iOS和Android應用中的圖片。要往App中添加一個靜態圖片,只需把圖片文件放在代碼文件夾比如img中某處,然後像下麵這樣去引用它:<Image source={require('./img/check.png')} />
如果你有my-icon.ios.png和my-icon.android.png,Packager就會根據平臺而選擇不同的文件。
你還可以使用@2x,@3x這樣的文件名尾碼,來為不同的屏幕精度提供圖片。比如下麵這樣的代碼結構:
------ button.js
------ img
------ |-------- [email protected]
------ |-------- [email protected]
Packager會打包所有的圖片並且依據屏幕精度提供對應的資源。譬如說,iPhone 5s會使用[email protected],而Nexus 5上則會使用[email protected]。如果沒有圖片恰好滿足屏幕解析度,則會自動選中最接近的一個圖片。
【註意】如果你添加圖片的時候packager正在運行,可能需要重啟packager以便能正確引入新添加的圖片。為了使新的圖片資源機制正常工作,require中的圖片名字必須是一個靜態字元串,不能在require中進行拼接。
//正確<Image source={require('./my-icon.png')} />
錯誤var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
<Image source={require('./' + icon + '.png')} />
使用混合App的圖片資源
如果你在編寫一個混合App(一部分UI使用React Native,而另一部分使用平臺原生代碼),也可以使用已經打包到App中的圖片資源(通過Xcode的asset類目或者Android的drawable文件夾打包):<Image source={{uri: 'app_icon'}} style={{width: 40, height: 40}} />
註意:這一做法並沒有任何安全檢查。你需要自己確保圖片在應用中確實存在,而且還需要指定尺寸。
載入網路圖片
與靜態資源不同的是,你需要手動指定圖片的尺寸。
//正確<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
style={{width: 400, height: 400}} />
//錯誤<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}} />
為什麼不在所有情況下都指定尺寸呢
在瀏覽器中,如果你不給圖片指定尺寸,那麼瀏覽器會首先渲染一個0x0大小的元素占位,然後下載圖片,在下載完成後再基於正確的尺寸來渲染圖片。這樣做的最大問題是UI會在圖片載入的過程中上下跳動,使得用戶體驗非常糟糕。
在React
Native中有意避免了這一行為。如此一來開發者就需要做更多工作來提前知曉遠程圖片的尺寸(或寬高比),但我們相信這樣可以帶來更好的用戶體驗。然而,從已經打包好的應用資源文件中讀取圖片(使用require('image!x')語法)則無需指定尺寸,因為它們的尺寸在載入時就可以立刻知道。
比如這樣一個引用require('image!logo')的實際輸出結果可能是:{"__packager_asset":true,"isStatic":true,"path":"/Users/react/HelloWorld/iOS/Images.xcassets/react.imageset/logo.png","uri":"logo","width":591,"height":573}
通過嵌套實現背景圖片
類似web中的背景圖(background-image),只需簡單地創建一個<Image>組件,然後把需要背景圖的子組件嵌入其中即可return (
<Image source={...}>
<Text>Inside</Text>
</Image>
);
在Android 上支持GIF和WebP格式的圖片
dependencies {
// 如果你需要支持Android4.0(API level 14)之前的版本
compile 'com.facebook.fresco:animated-base-support:0.11.0'
// 如果你需要支持GIF動圖
compile 'com.facebook.fresco:animated-gif:0.11.0'
// 如果你需要支持WebP格式,包括WebP動圖
compile 'com.facebook.fresco:animated-webp:0.11.0'
compile 'com.facebook.fresco:webpsupport:0.11.0'
// 如果只需要支持WebP格式而不需要動圖
compile 'com.facebook.fresco:webpsupport:0.11.0'
}
如果你在使用GIF的同時還使用了ProGuard,那麼需要在proguard-rules.pro中添加如下規則 :-keep class com.facebook.imagepipeline.animated.factory.AnimatedFactoryImpl { public AnimatedFactoryImpl(com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory, com.facebook.imagepipeline.core.ExecutorSupplier);
}
二. 屬性
1.onLayout (function) 當Image佈局發生改變的,會進行調用該方法,調用的代碼為:
{nativeEvent: {layout: {x, y, width, height}}}.
2.onLoad (function):當圖片載入成功之後,回調該方法
3.onLoadEnd (function):當圖片載入失敗回調該方法,不會管圖片載入成功還是失敗
4.onLoadStart (fcuntion):當圖片開始載入的時候調用該方法
5.resizeMode 縮放比例,可選參數('cover', 'contain', 'stretch') 當圖片的尺寸超過佈局的尺寸的時候,會根據設置Mode進行縮放或者裁剪圖片
cover: 在保持圖片寬高比的前提下縮放圖片,直到寬度和高度都大於等於容器視圖的尺寸(如果容器有padding內襯的話,則相應減去)。譯註:這樣圖片完全覆蓋甚至超出容器,容器中不留任何空白。
contain: 在保持圖片寬高比的前提下縮放圖片,直到寬度和高度都小於等於容器視圖的尺寸(如果容器有padding內襯的話,則相應減去)。譯註:這樣圖片完全被包裹在容器中,容器中可能留有空白
stretch: 拉伸圖片且不維持寬高比,直到寬高都剛好填滿容器。
repeat: 重覆平鋪圖片直到填滿容器。圖片會維持原始尺寸。僅iOS可用。
center: 居中不拉伸。
6.source {uri:string} 進行標記圖片的引用,該參數可以為一個網路url地址或者一個本地(使用require(相對路徑)來引用)的路徑
三. 樣式風格
1.FlexBox 支持彈性盒子風格
2.Transforms 支持屬性動畫 3.resizeMode 設置縮放模式
4.backgroundColor 背景顏色
5.borderColor 邊框顏色 6.borderWidth 邊框寬度
7.borderRadius 邊框圓角
8.overflow 設置圖片尺寸超過容器可以設置顯示或者隱藏('visible','hidden')
9.tintColor 顏色設置 10.opacity 設置不透明度0.0(透明)-1.0(完全不透明)
四. 示例
載入網路圖片的例子class MyImageDemo extends Component {
render() {
return (
<View style={[styles.flex,{marginTop:45}]}>
<MyImage imgs={imgs}> </MyImage>
</View>
);
}
}
class MyImage extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,//圖片索引
imgs: this.props.imgs,
};
}
render() {
return (
<View style={[styles.flex,{alignItems:'center'}]}>
<View style={styles.image}>
<Image style={styles.img}
resizeMode='contain'
source={{uri:this.state.imgs[this.state.count]}}/>
</View>
<View style={styles.btns}>
<TouchableOpacity onPress={this.onPrevious.bind(this)}><View
style={styles.btn}><Text>上一張</Text></View></TouchableOpacity>
<TouchableOpacity onPress={this.onNext.bind(this)}><View style={styles.btn}><Text>下一張</Text></View></TouchableOpacity>
</View>
</View>
);
}
onPrevious() {
var count = this.state.count;
count--;
if (count >= 0) {
this.setState({
count: count,
});
}
}
onNext() {
var count = this.state.count;
count++;
if (count < this.state.imgs.length) {
this.setState({
count: count,
});
}
}
}
const styles = StyleSheet.create({
flex: {
flex: 1,
},
image: {
width: 300,
height: 200,
borderWidth: 1,
justifyContent: 'center',
alignItems: 'center',
borderColor: '#ccc',
borderRadius: 5,
},
img: {
width: 200,
height: 150,
},
btn: {
width: 60,
height: 35,
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 3,
justifyContent: 'center',
alignItems: 'center',
marginRight: 30,
},
btns: {
flexDirection: 'row',
marginTop: 20,
justifyContent: 'center'
}
}
);
效果
Image_first.jpeg
點擊下一張
Image_second.jpeg
點擊下一張
Image_third.jpeg
記錄我自己的RN學習之路,純屬自己增值,有什麼不對的地方,一起討論進步