Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactNative ListView inconsistent separator lines

On Android 4.4, ListView separator lines are inconsistent in thickness, and some do not render. I can't see how this can be a code issue, this is how I render them:

     separator: {
        height: 1,
        backgroundColor: 'grey',
      }
      ...
      <ListView
      renderSeparator={(sectionID, rowID) =>
        <View key={`${sectionID}-${rowID}`} style={styles.separator} />
      }
      .../>

Here is a screenshot of a View with this problem:

enter image description here

This issue does not happen on iOS or Android 6.

Anyone had this problem before?

Update

I did a test, this is not Android4 issue. It happens on all API version when running on Nexus One device (in android emulator)

like image 672
Giannis Avatar asked Jun 24 '16 11:06

Giannis


5 Answers

I had this issue on iOS and worked around it by adding a hairline margin, like so:

<View
    style={{
      ...styles,
      borderWidth: StyleSheet.hairlineWidth,
      margin: StyleSheet.hairlineWidth,
    }}
>
    {// ...row content}
</View>
like image 130
Julian K Avatar answered Nov 12 '22 03:11

Julian K


Just give the height:hairlineWidth in style

like image 35
Gopal Avatar answered Nov 12 '22 01:11

Gopal


I had the same issue and solved changing the view height from a number to StyleSheet.hairlineWidth as some folks said before. Trying to be more visual/specific:

Before:

renderItemSeparator() {
    return (
        <View style={{ height: .2, backgroundColor: 'rgba(0,0,0,0.3)' }} />
    );
}

After:

renderItemSeparator() {
    return (
        <View style={{ height: StyleSheet.hairlineWidth, backgroundColor: 'rgba(0,0,0,0.3)' }} />
    );
}
like image 2
Eddie Teixeira Avatar answered Nov 12 '22 03:11

Eddie Teixeira


Actually there is no fix. It's RN "render-canvas-bug". But I found hack solution.

<ListView
    style={Style.listView}
    dataSource={data}
    renderRow={(data) => this._renderRow(data)}
    />`

Style.listView: { backgroundColor: '#fff', }, // or another backgroundColor you need

Then:

_renderRow(goods) {

    return (
        <View key={'goods_' + goods.id} style={Style.listView_item}>
            <TouchableOpacity or View or ...
                style={[Style.flex, Style.flexRow, Style.separatorRow, Style.u_paddingVerticalS, Style.u_middle]}
                onPress={() => this._xyz(goods)}>
                <View>
                    <AppFont>{goods.name}</AppFont>
                </View>
            </TouchableOpacity or View or ...>
        </View>
    );
}

Only important TouchableOpacity style is Style.separatorRow to render your separator. This style should be inside listView_item, where you can use another styles.

listView: {
    backgroundColor: '#fff',
},
listView_item: {
    paddingHorizontal: em(1.5),
},
flex: {
    flex: 1,
},
flexRow: {
    flexDirection: 'row',
},
separatorRow: {
    marginBottom: 1,
    borderBottomWidth: 1,
    borderBottomColor: Colors.canvasColor,
},

You can use StyleSheet.hairlineWidth instead of 1 but it's not a must.

like image 1
Jonáš Krutil Avatar answered Nov 12 '22 01:11

Jonáš Krutil


I reported it on GitHub

My workaround was to style the containing view and text like this:

const styles = StyleSheet.create({
      rowViewContainer: {
        flex: 1,
        paddingRight: 15,
        paddingTop: 13,
        paddingBottom: 13,
        borderBottomWidth: 0.5,
        borderColor: '#c9c9c9',
        flexDirection: 'row',
        alignItems: 'center',
      },
      rowText: {
        marginLeft: 15,
      },
    });

This is the ListView:

<ListView
            dataSource={this.state.dataSource}
             renderRow={(data) => <View style={styles.rowViewContainer}>
               <Text style={styles.rowText}>
                 {data.bb_first_name}
               </Text>
             </View>}
          />

Looks nice:

enter image description here

like image 1
AdamG Avatar answered Nov 12 '22 02:11

AdamG