如果感覺我寫的不錯,關(guān)注我垃僚,給個star哦闺鲸!項目地址
如果遇到什么問題可以在評論區(qū)回復(fù),或者加QQ群397885169討論
前言
經(jīng)過前兩篇文章的積累赊舶,已經(jīng)大體上將項目結(jié)構(gòu)完成了,接下來就是對內(nèi)容的填充赶诊,自定義啦笼平。今天就來說一下項目中Cell的規(guī)劃。
使用React-Native寫百思不得姐(一)
使用React-Native寫百思不得姐(二)
自定義Cell
上回說到要自定義Cell舔痪,但具體該怎么定義寓调,如何定義卻沒有說明,接下來我會說明一下我是如何定義的锄码。
拆分
通過上面三張圖夺英,可以明顯發(fā)現(xiàn)整個Cell是分為三部分的晌涕。
我們將一個Cell分開,分拆成頭部痛悯,中間余黎,底部。我們逐個完成载萌。
頂部Cell自定義
通過圖片會發(fā)現(xiàn)左邊是一個圖片驯耻,右邊是兩端文字。
listItem.js
// Cell頂部布局
userInfo(){
return(
<View style={styles.userInfoStyle}>
<Image source={{uri:this.props.itemData.profile_image}} style={styles.iconStyle}/>
<View style={styles.userDetailStyle}>
<Text style={styles.userTextStyle}>{this.props.itemData.name}</Text>
<Text style={styles.userTimeStyle}>{this.props.itemData.passtime}</Text>
</View>
</View>
)
}
Cell底部布局
仔細看一下會發(fā)現(xiàn)是4個按鈕炒考,每個按鈕都左邊是一個圖片可缚,右邊是文字,每個按鈕之間還有個分界線斋枢。
// Cell底部布局
bottomInfo(){
return(
<View style={styles.bottomStyle}>
{this.createBtn()}
</View>
)
}
// 創(chuàng)建Button
createBtn(){
let btnArr = [];
for(let i = 0 ; i < this.state.btnData.length ; i ++){
let btnData = this.state.btnData;
btnArr.push(
<TouchableOpacity key={i} onPress={()=>{this.btnPress(i)}} activeOpacity={1}>
<View style={styles.btnStyle}>
{
btnData[i].selected ?
<Icon name={btnData[i].icon} size={20} color='red'/>
:
<Icon name={btnData[i].icon} size={20} color='orange'/>
}
<Text style={styles.btnTextStyle}>{btnData[i].title}</Text>
<View style={styles.btnLineStyle} />
</View>
</TouchableOpacity>
);
}
return btnArr;
}
Cell中間布局
接下來就是最重要的Cell中間的布局了
上面兩張圖的共同點就是頂部都有一段文字帘靡,而下面可能是圖片,視頻瓤帚,聲音或者什么都沒有描姚。所以我們要將這里再細分一下。分為視頻戈次,圖片轩勘,聲音,段子怯邪。
// 圖片
if (this.props.itemData.type == '10'){
return(
<PictureItem pictureData={this.props.itemData}
picturePress={this.props.picturePress}
satinPress={this.props.satinPress}
/>
)
}
// 段子
if (this.props.itemData.type == '29'){
return(
<SatinItem satinData={this.props.itemData.text}
satinPress={this.props.satinPress}
/>
)
}
// 聲音
if (this.props.itemData.type == '31'){
return(
<View>
<Text>{this.props.itemData.text}</Text>
</View>
)
}
// 視頻
if (this.props.itemData.type == '41'){
return(
<View>
<VideoItem videoData={this.props.itemData}/>
</View>
)
}
段子
通過上面的找規(guī)律發(fā)現(xiàn)绊寻,基本每個Cell都是有一段話的,可能是段子也可能是別的悬秉。但它們都是通過同一個接口獲取的澄步,所以我們將它們歸于一類。
// 段子
class SatinItem extends Component{
static defaultProps = {
satinData: React.PropTypes.string,
satinPress:null,
};
render(){
return(
<TouchableOpacity activeOpacity={0.8} onPress={this.props.satinPress}>
<View style={styles.satinViewStyle}>
<Text style={styles.satinStyle}>
{this.props.satinData}
</Text>
</View>
</TouchableOpacity>
)
}
}
通過上面的代碼和泌,將段子的數(shù)據(jù)源和點擊事件就設(shè)置好了村缸。在之后的項目中會有很多地方用到段子的點擊事件。
圖片
在百思不得姐中圖片有三種武氓,普通配圖梯皿,gif圖,長圖县恕,對于普通配圖只要設(shè)置好圖片的寬高就好了东羹;對于gif圖,iOS端也是只要設(shè)置好寬高就可以了弱睦,但對于安卓平臺需要引用一些其他的東西百姓;而對于長圖就要進行判斷了渊额,根據(jù)判斷來展示需要的圖片况木。
// 圖片
class PictureItem extends Component{
static defaultProps = {
pictureData: React.PropTypes.string,
picturePress: null,
satinPress: null,
};
constructor(props){
super(props);
let imageHeight = (width - 20) * this.props.pictureData.height / this.props.pictureData.width;
this.state={
imageHeight:imageHeight
};
// console.log('屏幕高度' + height);
// console.log('圖片展示高度'+this.state.imageHeight);
}
renderPicture(){
// gif圖
if (this.props.pictureData.is_gif == '1'){
// console.log('gif圖' + this.props.pictureData.height);
return(
<Image source={{uri:this.props.pictureData.cdn_img}} style={{width:width-20,height:this.state.imageHeight}}
indicator={ProgressBar}
/>
)
}
// 長圖
if (this.state.imageHeight > height){
// console.log('長圖'+this.props.pictureData.height);
return(
<Image source={{uri:this.props.pictureData.image0}} style={{width:width-20,height:height}} resizeMode='contain'
indicator={ProgressBar}
>
<View style={styles.longImageViewStyle}>
<Text style={styles.longImageTextStyle}>點擊查看全圖</Text>
</View>
</Image>
)
}
return(
<Image source={{uri:this.props.pictureData.cdn_img}} style={{width:width-20,height:this.state.imageHeight}}
indicator={ProgressBar}
/>
)
}
// 普通圖片
render(){
return(
<View style={styles.imageViewStyle}>
<SatinItem satinData={this.props.pictureData.text} satinPress={this.props.satinPress}/>
<TouchableOpacity onPress={this.props.picturePress} activeOpacity={0.8}>
{this.renderPicture()}
</TouchableOpacity>
</View>
)
}
}
我在這個里面將圖片的數(shù)據(jù)源和點擊事件都做好了垒拢,之后可以通過這個點擊事件來查看圖片和長圖。
遇到的坑
在react-native上Image有三種模式使用resizeMode來改變
cover
:這個是默認的模式火惊,在某些情況下求类,會導(dǎo)致長圖加載出現(xiàn)問題。
stretch
:這個模式會是長圖完全填充Cell屹耐,很難看尸疆。
contain
:最終選擇了這個模式,雖然也不太好看惶岭,但起碼不會出現(xiàn)問題寿弱。
安卓gif圖加載
在 android/app/build.gradle 中需要添加以下內(nèi)容
dependencies {
// If your app supports Android versions before Ice Cream Sandwich (API level 14)
compile 'com.facebook.fresco:animated-base-support:0.11.0'
// For animated GIF support
compile 'com.facebook.fresco:animated-gif:0.11.0'
// For WebP support, including animated WebP
compile 'com.facebook.fresco:animated-webp:0.11.0'
compile 'com.facebook.fresco:webpsupport:0.11.0'
// For WebP support, without animations
compile 'com.facebook.fresco:webpsupport:0.11.0'
}
視頻
我只是完成了基本頁面的搭建,這個在之后會做一下視頻播放按灶。
展示圖片
在圖片組件里面症革,我實現(xiàn)了圖片的點擊事件,所以可以在首頁中通過點擊跳轉(zhuǎn)到另一個頁面來展示gif和長圖鸯旁。
render() {
return (
<ScrollView
// 橫向滾動
horizontal={false}
// 隱藏滾動條
showsHorizontalScrollIndicator={false}
// 彈簧效果
alwaysBounceHorizontal={false}
alwaysBounceVertical={false}
// 滾動效果
scrollEnabled={true}
style={styles.container}
>
{this.renderPicture()}
</ScrollView>
);
}
因為圖片是長圖噪矛,所以底部最好的選擇就是放一個ScrollView。而又因為有的圖片是長圖铺罢,有的圖片是gif艇挨,普通圖片,所以最好也做一下判斷韭赘。
renderPicture(){
if (this.state.imageHeight > height){
// console.log('長圖'+this.props.pictureData.height);
return(
<TouchableOpacity onPress={()=>{this.popPress()}} activeOpacity={0.9}>
<Image source={{uri:this.props.pictureData.cdn_img}}
style={[styles.imageStyle,{height:this.state.imageHeight}]}
resizeMode='contain'
/>
</TouchableOpacity>
)
}
return(
<TouchableOpacity onPress={()=>{this.popPress()}} activeOpacity={0.9}>
<Image source={{uri:this.props.pictureData.image0}}
style={[styles.imageNormalStyle,
{height:this.state.imageHeight,marginTop:(height-this.state.imageHeight) / 2}]}
/>
</TouchableOpacity>
)
}
如果點擊圖片就會返回到上一級缩滨,所以,我們給圖片加了個點擊事件泉瞻。
popPress(){
let {navigator} = this.props;
if (navigator) {
InteractionManager.runAfterInteractions(()=> {
navigator.pop();
});
}
}
導(dǎo)入組件
react-native-image-progress
:因為react-native加載圖片是沒有展位圖的(iOS有楷怒,安卓沒有),所以導(dǎo)入這個組件用來做一個圖片加載的動畫瓦灶。
react-native-progress/Bar
:進度條鸠删,這個組件和上面組件是配套使用的,因為它們是同一個人寫的贼陶。當然也可以獨立使用刃泡,但我還沒有引入ART,所以還沒有真正的利用這個組件碉怔。
總結(jié)
因為現(xiàn)在用的電腦很卡烘贴,所以對于安卓的運行效果我沒有去測試,等新電腦到了撮胧,我會將兩端的適配完成桨踪。
如果在使用中遇到什么問題,歡迎私信和評論哦芹啥!
如果喜歡我的文章锻离,關(guān)注我铺峭,給個star哦!