Для приложения, похожего на чат, я хочу, чтобы ScrollViewкомпонент был прокручен вниз, потому что самые новые сообщения появляются под старыми. Можем ли мы отрегулировать положение прокрутки a ScrollView?
Для приложения, похожего на чат, я хочу, чтобы ScrollViewкомпонент был прокручен вниз, потому что самые новые сообщения появляются под старыми. Можем ли мы отрегулировать положение прокрутки a ScrollView?
Ответы:
Для React Native 0.41 и новее вы можете сделать это с помощью встроенного scrollToEndметода:
<ScrollView
ref={ref => {this.scrollView = ref}}
onContentSizeChange={() => this.scrollView.scrollToEnd({animated: true})}>
</ScrollView>
rootиначе scrollToEnd не определено. т.е.this.scrollView.root.scrollToEnd
rootфактически вызывает неопределенную ошибку.
ref={ref => {this.scrollView = ref}}если вы не хотите возвращать задание
Используйте onContentSizeChange, чтобы отслеживать нижнюю часть Y прокрутки (высота)
https://facebook.github.io/react-native/docs/scrollview.html#oncontentsizechange
var _scrollToBottomY
<ScrollView
onContentSizeChange={(contentWidth, contentHeight)=>{
_scrollToBottomY = contentHeight;
}}>
</ScrollView>
затем используйте имя ссылки для просмотра прокрутки, например
this.refs.scrollView.scrollTo(_scrollToBottomY);
Вот простейшее решение, которое я смог найти:
<ListView
ref={ref => (this.listView = ref)}
onLayout={event => {
this.listViewHeight = event.nativeEvent.layout.height;
}}
onContentSizeChange={() => {
this.listView.scrollTo({
y: this.listView.getMetrics().contentLength - this.listViewHeight
});
}}
/>;
Для тех, кто пишет функциональный компонент, который может использовать ловушку,
import React, { useRef } from 'react';
import { ScrollView } from 'react-native';
const ScreenComponent = (props) => {
const scrollViewRef = useRef();
return (
<ScrollView
ref={scrollViewRef}
onContentSizeChange={() => scrollViewRef.current.scrollToEnd({ animated: true })}
/>
);
};
попробуйте это решение
xcode 10.0
РН: 56.0.0
<ScrollView ref="scrollView"
onContentSizeChange={(width,height) => this.refs.scrollView.scrollTo({y:height})}> </ScrollView> // OR height - width
ref=? похоже на реликвию веб-разработчиков
Если кто-то в 2020 году или позже задается вопросом, как добиться этого с помощью функциональных компонентов. Вот как я это сделал:
ref={ref => scrollView = ref }
onContentSizeChange={() => scrollView.scrollToEnd({ animated: true })}>
Вы можете инвертировать вид прокрутки / списка с помощью react-native-invertible-scroll-viewмодуля , а затем просто вызвать ref.scrollTo(0)прокрутку вниз.
Установите модуль:
npm install --save react-native-invertible-scroll-view
Затем импортируйте компонент:
import InvertibleScrollView from 'react-native-invertible-scroll-view';
Затем используйте следующий JSX вместо ScrollView:
<InvertibleScrollView inverted
ref={ref => { this.scrollView = ref; }}
onContentSizeChange={() => {
this.scrollView.scrollTo({y: 0, animated: true});
}}
>
{ /* content */ }
</InvertibleScrollView>
Это работает, потому что react-native-invertible-scroll-viewпереворачивает все содержимое представления. Обратите внимание, что дочерние элементы представления также будут отображаться в порядке, обратном нормальному виду - первый дочерний элемент будет отображаться внизу .
На самом деле ответ @Aniruddha не сработал для меня, потому что я использую, "react-native": "0.59.8"а this.scrollView.root.scrollToEndтакже не определен
но я понял это, и это работает this.scrollView.scrollResponderScrollToEnd({animated: true});
Если вы используете 0.59.8это, будет работать ИЛИ если вы используете более позднюю версию, и это работает для вас. пожалуйста, добавьте версии в этот ответ, чтобы у других не было проблем.
Полный код здесь
<ScrollView
ref={ref => this.scrollView = ref}
onContentSizeChange={(contentWidth, contentHeight)=>{
this.scrollView.scrollResponderScrollToEnd({animated: true});
}}>
</ScrollView>
Этот метод немного взломан, но я не мог найти лучшего способа
var footerY; //Y position of the dummy view
render() {
return (
<View>
<ScrollView
ref='_scrollView'>
// This is where all the things that you want to display in the scroll view goes
// Below is the dummy View
<View onLayout={(e)=> {
footerY = e.nativeEvent.layout.y;
}}/>
</ScrollView>
//Below is the button to scroll to the bottom
<TouchableHighlight
onPress={() => { this.refs._scrollView.scrollTo(footerY); }}>
<Text>Scroll to Bottom</Text>
</TouchableHighlight>
</View>
);
}
scrollToBottomделает такие подходы устаревшими в новых версиях React Native.
Это отвечает на ваш вопрос: https://stackoverflow.com/a/39563100/1917250
Вам нужно постоянно прокручивать страницу вниз, вычисляя высоту содержимого за вычетом высоты его scrollView.
Если вы используете TypeScript, вам нужно сделать это
interface Props extends TextInputProps {
scrollRef?: any;
}
export class Input extends React.Component<Props, any> {
scrollRef;
constructor(props) {
this.scrollRef = React.createRef();
}
<ScrollView
ref={ref => (this.scrollRef = ref)}
onContentSizeChange={() => {
this.scrollRef.scrollToEnd();
}}
>
</ScrollView>
Я боролся с этим некоторое время и, наконец, придумал что-то, что действительно хорошо и гладко для меня работало. Как и многие, я безуспешно пытался .scrollToEnd. Решение , которое работало для меня было сочетание onContentSizeChange, onLayoutреквизита и немного больше думать визуально «что прокрутка вниз» на самом деле означает. Последняя часть кажется мне сейчас тривиальной, но мне потребовалась целая вечность, чтобы понять.
Учитывая, что ScrollViewимеет фиксированную высоту, когда высота содержимого превышает высоту контейнера, я рассчитал смещение, вычитая prevHeight(фиксированную высоту ScrollView) для currHeight(высота содержимого). Если вы можете визуально представить это, прокрутка до этой разницы по оси Y перемещает высоту содержимого по своему контейнеру на это смещение. Я увеличил смещение и сделал мою текущую высоту содержимого моей предыдущей высотой и продолжал вычислять новое смещение.
Вот код. Надеюсь, это кому-то поможет.
class ChatRoomCorrespondence extends PureComponent {
currHeight = 0;
prevHeight = 0;
scrollHeight = 0;
scrollToBottom = () => {
this.refs.scrollView.getScrollResponder().scrollResponderScrollTo({
x: 0,
y: this.scrollHeight,
animated: true
});
};
render() {
return (
<ScrollView
style={Styles.container}
ref="scrollView"
onContentSizeChange={(w, h) => {
this.currHeight = h;
if (
this.prevHeight > 0 &&
this.currHeight - this.scrollHeight > this.prevHeight
) {
this.scrollHeight += this.currHeight - this.prevHeight;
console.log("--------------------------------------------");
console.log("Curr: ", this.currHeight);
console.log("Prev: ", this.prevHeight);
console.log("Scroll: ", this.scrollHeight);
this.prevHeight = this.currHeight;
console.log("PREV: ", this.prevHeight);
console.log("--------------------------------------------");
this.scrollToBottom();
}
}}
onLayout={ev => {
// Fires once
const fixedContentHeight = ev.nativeEvent.layout.height;
this.prevHeight = fixedContentHeight;
}}
>
<FlatList
data={this.props.messages}
renderItem={({ item }) => (
<ChatMessage
text={item.text}
sender={item.sender}
time={item.time}
username={this.props.username}
/>
)}
keyExtractor={(item, index) => index.toString()}
/>
</ScrollView>
);
}
}
Думаю, еще слишком поздно отвечать, но у меня есть одна хитрость! Если вы используете FlatListвы можете включить invertedсвойство , которое возвращается к установке transform scaleна -1(что является приемлемым для других компонентов , таких как список ScrollView...). При рендеринге FlatListс данными он всегда будет внизу!
Попробуйте установить для свойства contentOffset представления прокрутки текущую высоту содержимого.
Чтобы выполнить то, что вам нужно, вы можете сделать это как часть события onScroll. Однако это может ухудшить взаимодействие с пользователем, поэтому может оказаться более удобным делать это только при добавлении нового сообщения.
ScrollViewвниз к ниже все его содержание, а не просто прокрутка вниз.
У меня была аналогичная проблема, но после прочтения этой страницы (которая вызывает у меня головную боль!) Я нахожу этот очень хороший пакет npm, который просто инвертирует ListView и упрощает работу приложения чата !!
ScrollView, а не ListView).
Немного поздно ... но посмотрите на этот вопрос. Прокрутите вверх ScrollView
ScrollView имеет метод scrollTo.