ScrollView를 아래쪽으로 스크롤 할 수 있습니까?


87

채팅과 같은 앱의 경우 ScrollView최신 메시지가 이전 메시지 아래에 표시되기 때문에 구성 요소를 맨 아래로 스크롤 하고 싶습니다 . 스크롤 위치를 조정할 수 있습니까 ScrollView?


3
react-native에 대해 아무것도 모르지만 사용자가 채팅 기록을보기 위해 스크롤을 올리는 경우가 있습니다. 새 메시지가 도착했을 때 채팅이 이미 맨 아래까지 스크롤 된 경우에만 채팅을 스크롤해야합니다.
David

이것은 좋은 생각입니다. 우리는 여기서이 문제를 추적하는 : github.com/facebook/react-native/issues/107
에릭 Vicenti

난 그냥 비슷한 질문에 대답, 여기를 확인하시기 바랍니다 - stackoverflow.com/a/32652967/1541508
Kohver

이것이 귀하의 질문에 대답합니까? React Native ListView의 맨 아래로 스크롤하는 방법
TripleM

답변:


165

대한 기본 0.41 반응 이후 , 당신이 할 수있는 내장 scrollToEnd방법 :

<ScrollView
    ref={ref => {this.scrollView = ref}}
    onContentSizeChange={() => this.scrollView.scrollToEnd({animated: true})}>
</ScrollView>

3
반응 네이티브 0.55.4 이상부터는 root그렇지 않으면 scrollToEnd가 정의되지 않았습니다. 즉this.scrollView.root.scrollToEnd
Simon

4
현재 반응 네이티브 0.58.6을 사용하고 root실제로 사용 하면 정의되지 않은 오류가 발생합니다.
Jose Bernhardt

1
이 경우 : ref={ref => {this.scrollView = ref}}과제를 반환하고 싶지 않기 때문에
Hampycalc

25

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);

2
이렇게하면 뷰가 완전히 맨 아래로 스크롤되므로 뷰가 본질적으로 표시되지 않습니다 (측정 후에 무언가를 추가하지 않는 한). 이것은 코드가 스크롤 가능 영역을 오버플로하는 자식의 높이가 아니라 스크롤 가능 영역의 높이로 스크롤되기 때문에 의미가 있습니다 (아마 OP가 원하는 것이 아님). 대신 stackoverflow.com/a/39563193/1526986 을 참조하십시오 .
xixixao

20

다음은 내가 모을 수있는 가장 간단한 해결책입니다.

 <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
    });
}}
/>;

1
이 답변이나 다른 유사한 답변을 사용하면 목록의 항목이 사라지게됩니다 ( 너무 많이 스크롤되는 것처럼 보이지만 확신 할 수 없습니다). 조금만 스크롤하면 모든 것이 다시 나타나고보기로 다시 미끄러지는 것처럼 보입니다 (따라서 스크롤링이 너무 먼 이론). 왜 그럴 수 있는지 분명한 생각이 있습니까?
tscizzle

11

후크를 사용할 수있는 함수 컴포넌트를 작성하는 모든 사람을 위해

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 })}
    />
  );
};

5

이 해결책을 시도하십시오

xcode 10.0

RN : 56.0.0

<ScrollView ref="scrollView"
             onContentSizeChange={(width,height) => this.refs.scrollView.scrollTo({y:height})}>  </ScrollView> // OR height -  width

ref=? 웹 개발 유물처럼 보인다
YungGun

5

2020 년 이후의 누군가가 기능 구성 요소로이를 달성하는 방법을 궁금해하는 경우. 이것이 내가 한 방법입니다.

ref={ref => scrollView = ref }
onContentSizeChange={() => scrollView.scrollToEnd({ animated: true })}>

참고 : useref를 사용하고 있음을 언급 할 수 있습니다. 대부분의 ppl은 후크와 함께 ref를 사용하는 방법을 모릅니다.
ʎzɐɹƆ

예. 문제는 useRef 후크를 사용하지 않을 때도 해결된다는 것입니다. 그러나 올바른 방법은 그것을 사용하는 것입니다! 당신이 맞아요
Marlon Englemam

4

react-native-invertible-scroll-view모듈을 사용하여 스크롤 / 목록보기를 반전 한 다음 간단히 호출 ref.scrollTo(0)하여 하단으로 스크롤 할 수 있습니다.

모듈 설치 :

npm install --save react-native-invertible-scroll-view

그런 다음 구성 요소를 가져옵니다.

import InvertibleScrollView from 'react-native-invertible-scroll-view';

그런 다음 a 대신 다음 JSX를 사용하십시오 ScrollView.

<InvertibleScrollView inverted
    ref={ref => { this.scrollView = ref; }}
    onContentSizeChange={() => {
        this.scrollView.scrollTo({y: 0, animated: true});
    }}
>
    { /* content */ }
</InvertibleScrollView>

이것은 react-native-invertible-scroll-view전체보기의 내용을 뒤집기 때문에 작동 합니다. 뷰의 자식도 일반 뷰와 반대 순서로 렌더링됩니다. 첫 번째 자식이 맨 아래에 나타납니다 .


3

실제로 @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>

1

이 방법은 약간 엉망이지만 더 나은 방법을 찾지 못했습니다.

  1. 먼저 ScrollView에 참조를 추가하십시오.
  2. 둘째, ScrollView 태그를 닫기 전에 더미보기를 추가합니다.
  3. 해당 더미 뷰의 y 위치 가져 오기
  4. 하단으로 스크롤하고 싶을 때마다 더미 뷰의 위치로 스크롤합니다.

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>
    );
  }


이없는 아주 요청이 있었는지; 콘텐츠가 추가 될 때 스크롤 뷰를 하단으로 스크롤하는 대신 탭시 하단으로 스크롤합니다. 어쨌든, scrollToBottomReact Native의 최신 버전에서는 이와 같은 접근 방식을 쓸모 없게 만듭니다.
Mark Amery

1

이것은 귀하의 질문에 대한 답변 : https://stackoverflow.com/a/39563100/1917250

콘텐츠의 높이에서 scrollView의 높이를 뺀 값을 계산하여 페이지 하단으로 계속 스크롤해야합니다.


이것은 질문에 대한 정답입니다. 스크롤을 수행 할시기에 대해 현명 할 수 있습니다. 링크의 답변은 필요한 번호를 얻는 방법을 보여줍니다. 특히 목록에 구성 요소를 추가하는 경우 componentDidUpdate가 호출 될 때 콘텐츠 높이에 구성 요소가 포함되지 않으므로 대신 onContentSizeChange에서 스크롤하고 스크롤해야한다는 점을 기억해야합니다.
xixixao

1

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>

0

나는 이것으로 잠시 싸웠고 마침내 나를 위해 정말 잘 작동하고 부드러운 것을 생각해 냈습니다. 많은 사람들처럼 나는 .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>
    );
  }
}

0

대답하기에는 너무 늦었 나봐요.하지만 해킹이 하나 있어요! 사용하는 경우 ( ... 와 같은 다른 목록 구성 요소에 허용되는) 설정 으로 돌아가는 속성을 FlatList활성화 할 수 있습니다 . 데이터로 렌더링 하면 항상 맨 아래에 있습니다!invertedtransform scale-1ScrollViewFlatList


-1

스크롤 뷰 의 contentOffset 속성을 현재 콘텐츠 높이로 설정해보십시오 .

필요한 작업을 수행하려면 onScroll 이벤트의 일부로이를 수행 할 수 있습니다. 그러나 이것은 나쁜 사용자 경험을 만들 수 있으므로 새 메시지가 추가 될 때만이 작업을 수행하는 것이 더 사용자 친화적 인 것으로 입증 될 수 있습니다.


-1; 아니. 여기에있는 많은 답변과 마찬가지로, ScrollView아래로 스크롤하는 것이 아니라 모든 콘텐츠 아래 로 스크롤하는 효과가 있습니다.
Mark Amery


-3

조금 늦었지만이 질문을보세요. ScrollView의 맨 위로 스크롤

ScrollView에는 "scrollTo"메서드가 있습니다.


1
예, ScrollView에 scrollTo 메서드가 있지만 질문은 구체적으로 하단으로 스크롤하는 것에 대해 묻고 있으며 이는 간단하지 않습니다.
Southerneer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.