ScrollView: content image is cropped when phone is in landscape mode

Viewed 684

I'm trying to make a book reading experience using some images wrapped in scrollViews inside a FlatList.

everything is ok in 'portrait' mode but in 'landscape' the images are cropped, I want to be able to scroll vertically when in 'landscape' so the user can explore the whole image which becomes larger than screen height in 'landscape'

I've tried to modify the dimensions of the image depending on the orientation but the result is not good.

Here is my code: states

widthImage:Dimensions.get('window').width,
heightImage: Dimensions.get('window').height,

the content:

const QuranImage = [];
const scrollIsEnabled =  this.state.heightImage > this.state.height;
QuranImage.push(
    <ScrollView
        scrollEnabled = {scrollIsEnabled}
        onContentSizeChange = {this.manageScreenFlip}
        nestedScrollEnabled={true}
    >
        <Image style={{
                tintColor:'black',
                width:this.state.widthImage,
                height:this.state.heightImage,
            }}
            source={require('../Resources/page002.png')}
        />

     </ScrollView>
);

QuranImage.push(
    <ScrollView>
        <Image style={{
                tintColor:'black',
                width:this.state.width,
                height:this.state.height
        }}
        source={require('../Resources/page003.png')}/>
    </ScrollView>
)
this.setState({
    pdfViewer:(
        <FlatList
            horizontal={true}
            nestedScrollEnabled={true}
            pagingEnabled={true}
            data={QuranImage}
            keyExtractor={(item, index) => index.toString()}
            renderItem={({item,index}) =>item}
        />
     )
});

orientation listener fired in another place of the code:

_orientationDidChange = (orientation) => {
    if (orientation === 'LANDSCAPE') {
        this.setState({
            height: Dimensions.get('window').height,
            width: Dimensions.get('window').width,
            heightImage:1000,
            widthImage:1000
        },() => {
            this.renderPdfViewer();
            console.log(Dimensions.get('window').height);
            console.log(Dimensions.get('window').width);
        });
    } else {
        console.log(orientation);
    }
}

portrait with image fully displayed portrait with image fully displayed

landscape mode here I want to be able to scroll vertically to see the entire image landscape mode here I want to be able to scroll vertically to see the entire image

2 Answers

Add key prop in your flatlist as given below.

You can store the current orientation in a redux store and use it in your component as

const {orientation}= this.props

then

<FlatList
        horizontal={true}
        nestedScrollEnabled={true}
        pagingEnabled={true}
        data={QuranImage}
        keyExtractor={(item, index) => index.toString()}
        renderItem={({item,index}) =>item}
        key= { orientation =='PORTRAIT' || 
         orientation =='PORTRAITUPSIDEDOWN'?'portrait':'landscape' }
/>

modify your _orientationDidChange function as

_orientationDidChange = (orientation) => {
    if (orientation === 'PORTRAIT' || orientation== 
'PORTRAITUPSIDEDOWN') {
        this.setState({
            height: Dimensions.get('window').height, 
            width: Dimensions.get('window').width,
            heightImage:1000,
            widthImage:1000
        },() => {
            this.renderPdfViewer();
            console.log(Dimensions.get('window').height);
            console.log(Dimensions.get('window').width);
        });
    } else {
        this.setState({
            height: Dimensions.get('window').width, 
            width: Dimensions.get('window').height,
            heightImage:1000,
            widthImage:1000
        },() => {
            this.renderPdfViewer();
            console.log(Dimensions.get('window').height);
            console.log(Dimensions.get('window').width);
        });
    }
}

I found a solution to my issue by basically rerendering the FlatList every time i change orientation plus modifying height making it higher than screen high to enable scrolling.

  1. here is the orientation function:
_orientationDidChange = (orientation) => {
    const $this = this;
    setTimeout(function() {
      let width = Dimensions.get('window').width;
      let height = Dimensions.get('window').height;

      if (orientation == 'LANDSCAPE') {
        // if LANDSCAPE make image height bigger than screen height to force vertical scroll
        // 2.7 is a value chosen after visual testing 
        height = height * 2.7;
      } else if (orientation == 'PORTRAIT' || orientation == 'PORTRAITUPSIDEDOWN') {
        // if PORTRAIT make image height smaller than screen height so we can have some marges 
        height = height * 0.98;
      }
      $this.setState({renderFlat: null, itemLayout: width,width: width, height: height}, () => {
        $this.renderFlat();
      });
    }, 50);
  }
  1. the function that render the Flatlist:
renderFlat() {
    this.setState({
      renderFlat:
        (
          <FlatList
            horizontal={true}
            pagingEnabled={true}
            data={QuranImagePathList}
            keyExtractor={(item, index) => index.toString()}
            renderItem={this._renderItem}
            viewabilityConfig={this.state.viewabilityConfig}
            initialScrollIndex={this.state.currentPage}
            onViewableItemsChanged={this.handlePageChange}
            showsHorizontalScrollIndicator={false}
            getItemLayout={this.getItemLayout}
            removeClippedSubviews={true}
          />
        )
    })
  }
Related