日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【REACT NATIVE 系列教程之十三】利用LISTVIEW与TEXTINPUT制作聊天/对话框获取组件实例常用的两种方式...

發布時間:2023/12/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【REACT NATIVE 系列教程之十三】利用LISTVIEW与TEXTINPUT制作聊天/对话框获取组件实例常用的两种方式... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本站文章均為?李華明Himi?原創,轉載務必在明顯處注明:?
轉載自【黑米GameDev街區】 原文鏈接:?http://www.himigame.com/react-native/2346.html

補充說明:

一:很多童鞋問,鍵盤調出來被擋住了,那么下面給出三個解決方案:

1. 在render最外層包一個ScrollView,然后當鍵盤調出時,scrollTo即可實現。

2. 在底部添加一個可變化高度的view,根據鍵盤獲取、失去焦點時,進行處理實現

3. 使用插件:react-native-keyboard-spacer :https://github.com/Andr3wHur5t/react-native-keyboard-spacer

二:有的童鞋說對話框的背景沒有根據內容長短自適應,OK ,下面給出自動適應的樣式與修改:

先看效果圖:

1. 導入一個組件:Dimensions

2. 我們先將?renderEveryData 的函數改為如下:

????renderEveryData(eData)?{var?sWidth?=?Dimensions.get('window').widthreturn?(<View?style={eData.isMe==true?styles.everyRowRight:styles.everyRow}><Imagesource={eData.isMe==true??null:require('./res/headIcon/ox1.png')}style={eData.isMe==true?null:styles.talkImg}/><View?style={{width:sWidth?-?100}}><View?style={eData.isMe==true?styles.talkViewRight:styles.talkView}><Text?style={?eData.isMe==true?styles.talkTextRight:styles.talkText?}>{eData.talkContent}</Text></View></View><Imagesource={eData.isMe==true??require('./res/headIcon/ox2.png')?:null}style={eData.isMe==true?styles.talkImgRight:null}/></View>);}


3. 用到的樣式如下:

??everyRow:{flexDirection:'row',alignItems:?'center'},everyRowRight:{flexDirection:'row',alignItems:?'center',justifyContent:'flex-end'},talkView:?{backgroundColor:?'white',padding:?10,borderRadius:5,marginLeft:5,marginRight:55,marginBottom:10,alignSelf:'flex-start',},talkViewRight:?{backgroundColor:?'#90EE90',padding:?10,borderRadius:5,marginLeft:55,marginRight:5,marginBottom:10,alignSelf:'flex-end',},talkText:?{fontSize:?16,fontWeight:?'bold',},talkTextRight:?{fontSize:?16,fontWeight:?'bold',alignSelf:'flex-end',},talkImg:?{height:?40,width:?40,marginLeft:10,marginBottom:10},talkImgRight:?{height:?40,width:?40,marginRight:10,marginBottom:10},


width:sWidth – 100:這里是來限定Text每一行的最大寬度。

sWidth:是獲取的屏幕寬。

因此通過修改這里的值來指定你想要的每一行最大寬度吧。

——————————————–以上為補充內容,下面是正文——————————————–


本篇Himi來利用ListView和TextInput這兩種組件實現對話、聊天框。

首先需要準備的有幾點:(組件的學習就不贅述了,簡單且官方有文檔)

1. 學習下 ListView:

官方示例:http://reactnative.cn/docs/0.27/tutorial.html#content

官方文檔:http://reactnative.cn/docs/0.27/listview.html#content

2. 學習下:TextInput:

官方文檔:http://reactnative.cn/docs/0.27/textinput.html#content

3. ?獲取組件實例常用的兩種方式:

有時候,渲染出來的組件,我們需要拿到它的實例進行調用其函數等操作。假設有如下代碼段:

render()?{return?(<Text>Himi</Text>) }


如上,如果我們想要拿到這個Text組件的實例對象,有如下兩種形式:

第一種:

render()?{return?(<Text>Himi</Text>) }


使用時:this.refs._text ,通過this.refs進行獲取。

第二種:

render()?{var?_text;return?(<Text?ref={(text)?=>?{?_text?=?text;?}}>Himi</Text>) }


使用時:_text ,直接用這個變量即可。

如上都有了一定了解時,那么下面我們進行本篇的正題:

? 制作一個對話、聊天框,內容可滾動,且最新的消息永遠保持在最底部顯示!

一:首先我們先簡單布局一個聊天場景,布局+各種小組件的使用(代碼簡單,不多說):

import?React,?{Component }?from?'react'; import?{View,Text,TouchableHighlight,Image,PixelRatio,ListView,StyleSheet,TextInput,Alert,}?from?'react-native';var?datas?=[{isMe:false,talkContent:'最近在學習React?Native哦!',},{isMe:true,talkContent:'聽說是個跨平臺開發原生App的開源引擎',},{isMe:false,talkContent:'嗯啊,很不錯,可以嘗試下吧。過了這段時間繼續研究UE去了。唉~技術出身,就是放不下技術呀~',},{isMe:false,talkContent:'感覺編不下去對話了呀......感覺編不下去對話了呀......感覺編不下去對話了呀......感覺編不下去對話了呀......',},{isMe:true,talkContent:'無語!',},{isMe:false,talkContent:'自說自話,好難!隨便補充點字數吧,嗯?就醬紫?:)?',},{isMe:true,talkContent:'感覺編不下去對話了呀......感覺編不下去對話了呀..',},{isMe:false,talkContent:'GG,思密達編不下去了!',}, ];export?default?class?FarmChildView?extends?React.Component?{constructor(props)?{super(props);this.state?=?{inputContentText:'',dataSource:?new?ListView.DataSource({rowHasChanged:?(row1,?row2)?=>?row1?!==?row2,}),};this.listHeight?=?0;this.footerY?=?0;}componentDidMount()?{this.setState({dataSource:?this.state.dataSource.cloneWithRows(datas)});}renderEveryData(eData)?{return?(<View?style={{flexDirection:'row',alignItems:?'center'}}><Imagesource={eData.isMe==true??null:require('./res/headIcon/ox1.png')}style={eData.isMe==true?null:styles.talkImg}/><View?style={eData.isMe==true?styles.talkViewRight:styles.talkView}><Text?style={?styles.talkText?}>{eData.talkContent}</Text></View><Imagesource={eData.isMe==true??require('./res/headIcon/ox2.png')?:null}style={eData.isMe==true?styles.talkImgRight:null}/></View>);}myRenderFooter(e){}pressSendBtn(){}render()?{return?(<View?style={?styles.container?}><View?style={styles.topView}><Text?style={{fontSize:20,marginTop:15,color:'#f00'}}>Himi?React?Native?系列教程</Text></View><ListViewref='_listView'onLayout={(e)=>{this.listHeight?=?e.nativeEvent.layout.height;}}dataSource={this.state.dataSource}renderRow={this.renderEveryData.bind(this)}renderFooter={this.myRenderFooter.bind(this)}/><View?style={styles.bottomView}><View?style={styles.searchBox}><TextInputref='_textInput'onChangeText={(text)?=>{this.state.inputContentText=text}}placeholder='?請輸入對話內容'returnKeyType='done'style={styles.inputText}/></View><TouchableHighlightunderlayColor={'#AAAAAA'}activeOpacity={0.5}onPress={this.pressSendBtn.bind(this)}><View?style={styles.sendBtn}><Text?style={?styles.bottomBtnText?}>發送</Text></View></TouchableHighlight></View></View>);} }var?styles?=?StyleSheet.create({container:?{flex:?1,backgroundColor:?'#EEEEEE'},topView:{alignItems:?'center',backgroundColor:?'#DDDDDD',height:?52,padding:5},bottomView:{flexDirection:?'row',alignItems:?'center',backgroundColor:?'#DDDDDD',height:?52,padding:5},sendBtn:?{alignItems:?'center',backgroundColor:?'#FF88C2',padding:?10,borderRadius:5,height:40,},bottomBtnText:?{flex:?1,fontSize:?18,fontWeight:?'bold',},talkView:?{flex:?1,alignItems:?'center',backgroundColor:?'white',flexDirection:?'row',padding:?10,borderRadius:5,marginLeft:5,marginRight:55,marginBottom:10},talkImg:?{height:?40,width:?40,marginLeft:10,marginBottom:10},talkText:?{flex:?1,fontSize:?16,fontWeight:?'bold',},talkViewRight:?{flex:?1,alignItems:?'center',backgroundColor:?'#90EE90',flexDirection:?'row',justifyContent:?'flex-end',padding:?10,borderRadius:5,marginLeft:55,marginRight:5,marginBottom:10},talkImgRight:?{height:?40,width:?40,marginRight:10,marginBottom:10},searchBox:?{height:?40,flexDirection:?'row',flex:1,??//?類似于android中的layout_weight,設置為1即自動拉伸填充borderRadius:?5,??//?設置圓角邊backgroundColor:?'white',alignItems:?'center',marginLeft:5,marginRight:5,marginTop:10,marginBottom:10,},inputText:?{flex:1,backgroundColor:?'transparent',fontSize:?20,marginLeft:5}, });


以上一共做了這么幾件事:

  • 頂部添加一個標題

  • 添加一個ListView

  • 底部添加一個輸入框和發送按鈕

  • 以上代碼需要講解的有幾點:

    1.?inputContentText 這個state中的變量用于記錄用戶在TextInput輸入的內容

    2. ?this.listHeight = 0; 獲取到ListHeight的高度

    this.footerY = 0; 記錄ListView內容的最底部的Y位置。

    (作用后續講)

    3. ?myRenderFooter(e){} 這里是當ListView的 renderFooter 函數觸發時候調用的。(作用后續講)

    4.?pressSendBtn 是當當點擊發送按鈕后,調用我們的自定義函數。

    先看下布局后的效果圖(點擊查看動態效果):

    二:下面我們實現點擊發送后,將用戶在輸入框內輸入的內容添加到我們的ListView上,并重繪!

    主要處理邏輯,Himi已經設計好了,就是在?pressSendBtn 函數中處理即可,處理代碼段如下:

    pressSendBtn(){if(this.state.inputContentText.trim().length?<=?0){Alert.alert('提示',?'輸入的內容不能為空');return;}datas.push({isMe:false,talkContent:this.state.inputContentText,});this.refs._textInput.clear();this.setState({inputContentText:'',dataSource:?this.state.dataSource.cloneWithRows(datas)})}


    1. if( ?this.state.inputContentText.trim().length <= 0 )

    inputContentText用來記錄用戶在輸入框輸入的內容,因此這里我們先對內容是否為空進行判定!

    trim () 函數不多說了吧,去掉字符串首尾空格。純空格的內容也不允許發送~

    ? ?2. datas.push?

    這里是我們將新的數據添加到ListView中,其中文字內容就是我們記錄的用戶輸入的內容

    ? ?3. this.refs._textInput.clear()

    這里就是我們一開始準備工作介紹的小3節,通過this.refs._textInput()來獲取我們定義的TextInput組件實例。

    ? ?4. 最后我們調用了 this.setState函數來對其兩個變量進行修改:

    inputContentText :把記錄用戶剛才輸入在聊天框內的內容清空。

    dataSource:更新ListView的數據,因為我們剛添加了一條數據

    ?效果圖如下(點擊查看動態效果):

    三:讓新的數據永遠展示在ListView的底部,其實就是想要一個新數據添加后,自動從下滾上來的效果。

    Himi在做這一步的時候考慮過幾種方式,下面介紹兩種比較容易理解實現的方式:

    a) 通過計算每個ListView的每一行View的高度來計算出位置,然后與ListView的視圖高度進行對比,最后確定是否進行滾動操作(超出ListView的視圖才應該滾動)

    b) 根據官方ListView提供的renderFooter函數來完成!

    renderFooter:

    官方解釋:“頁頭與頁腳會在每次渲染過程中都重新渲染(如果提供了這些屬性)。如果它們重繪的性能開銷很大,把他們包裝到一個StaticContainer或者其它恰當的結構中。頁腳會永遠在列表的最底部,而頁頭會在最頂部。”

    粗糙的理解:每次繪制都會調用renderFooter這個繪制函數,而renderFooter就是繪制ListView最底部的位置。這里不是ListView視圖最底部,而且ListView內容高度的最底部位置!!

    因此我們通過ListView的renderFooter 繪制一個0高度的view,通過獲取其Y位置,其實就是獲取到了ListView內容高度底部的Y位置。

    這里我們來介紹b方案,簡單便捷。關于a方案,我想大家自己都很容易理解實現。

    其實通過上面布局這段代碼中,可以看到,Himi也已經對renderFooter的函數也綁到了自定義函數myRenderFooter上,所以我們只要在renderFooter中處理即可,如下代碼:

    ?myRenderFooter(e){return?<View?onLayout={(e)=>?{this.footerY=?e.nativeEvent.layout.y;if?(this.listHeight?&&?this.footerY?&&this.footerY>this.listHeight)?{var?scrollDistance?=?this.listHeight?-?this.footerY;this.refs._listView.scrollTo({y:-scrollDistance});}}}/>}

    1. 首先我們先繪制一個0高度的view :?return <View/>

    2. 通過ListView的onLayout函數來獲取并執行我們的滾動等邏輯。

    onLayout 函數官方說明:

    “當組件掛載或者布局變化的時候調用

    參數為:{nativeEvent: { layout: {x, y, width, height}}}

    這個事件會在布局計算完成后立即調用一次,不過收到此事件時新的布局可能還沒有在屏幕上呈現,尤其是一個布局動畫正在進行中的時候?!?/p>

    3. ?this.footerY= e.nativeEvent.layout.y;?

    this.footerY 一開始說過了,用來記錄0高度view的相對于ListView所在底部的Y位置。

    注:這里Himi定義成this.footerY,原因是Himi也嘗試了其他方式實現聊天滾動,為了方便使用。因此大家這里也可以定義var臨時的即可?;蛘咧苯拥玫绞褂枚紵o所謂啦~

    4. ?if( this.listHeight && this.footerY &&this.footerY>this.listHeight )

    this.listHeight:與第三步類似,Himi通過ListView的onLayout函數獲取到其高度記錄在此變量上。

    這里的判斷目的:當最新的內容高度大雨ListView視圖高度后,再開始執行滾動邏輯。

    5. 最后的滾動邏輯代碼段:

    var scrollDistance = this.listHeight – this.footerY;
    this.refs._listView.scrollTo({y:-scrollDistance});

    首先通過當前ListView的視圖高度-內容底部Y位置,獲取到相差的舉例?scrollDistance,這個距離就是我們需要ListView 滾動的舉例,且取反滾動!

    最后 _listView 是我們ListView的組件實例,因為ListView中也有ScrollView的特性,因此我們可以使用其:

    scrollTo({x: 0, y: 0, animated: true})

    對我們ListView進行動畫滾動操作!

    截此,我們的聊天、對話框完成,效果圖如下(點擊查看動態圖):

    ? ?備注:每一行數據中Himi都定義了一個?isMe 的字段,這里來表示說話是對方還是自己。

    isMe = true : ?頭像在右邊,說話底為綠色。

    ? ? isMe =false : 頭像放左側,說話底為白色。

    ? ? 其實這里Himi就是想做一些區分,模仿聊天的對話形式,所以加的變量。大家也可以各種自定義的啦~

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的【REACT NATIVE 系列教程之十三】利用LISTVIEW与TEXTINPUT制作聊天/对话框获取组件实例常用的两种方式...的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。