ReactNative ListView inconsistent separator lines
Asked Answered
C

7

12

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)

Casilde answered 24/6, 2016 at 11:28 Comment(4)
Is this a scaling issue? Does it happen on a real device? I've had this issue with the iOS simulator before.Soosoochow
This has been reported by a user (happens on device) and I have reproduced it on emulator..Casilde
I've gotten around the need to render a separate separator view buy setting the bottomBorderWidth of each row to 1px. Have you tried that?Soosoochow
Issue is still there with bottomBorderWidth. It looks like the spacing between row elements is not consistent.Casilde
F
7

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>
Feingold answered 12/10, 2018 at 20:49 Comment(1)
I fixed with the sames solution in my native-base ListItem component inside of FlatList, just added marginBottomWidth = borderBottomWidth, that was 1 / PixelRatio.getPixelSizeForLayoutSize(1) in my case. In react-native=0.57.8, android.Gymnosperm
N
2

Just give the height:hairlineWidth in style

Norahnorbert answered 2/11, 2016 at 13:13 Comment(3)
"StyleSheet.hairlineWidth" to be more specific.Mathias
This doesn't actually solve the issue. Neither does setting borders on the items themselves.Demote
Hi @Casilde did you find any solution?? I am also facing same issue, could you please help me if you got any solution?Blaney
T
2

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)' }} />
    );
}
Torn answered 16/11, 2018 at 16:7 Comment(0)
J
1

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.

Jibe answered 9/2, 2017 at 21:15 Comment(1)
Where can I get the more info about RN "render-canvas-bug"?Weaks
D
1

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

Disjoint answered 13/5, 2017 at 19:2 Comment(0)
S
0

This happens because you have empty rows in your data source. You can style your separators to see it

example

To avoid this just filter your data.

Stereoscope answered 25/4, 2017 at 14:43 Comment(1)
No this was a rendering issue.Casilde
A
0

I faced the same issue when trying to render a Divider with a width of 0.5.

It rendered properly on devices with pixel ratio of 2 (e.g. iPhone SE 2nd gen.) but rendered random width on devices with pixel ratio of 3 (e.g. iPhone 12).

As suggested by other answers, using Stylesheet.hairlineWidth fixes the random width issue but the problem was that the width was thinner than 0.5 on devices with pixel ratio of 3.

So this fixed my problem:

import { PixelRatio, View } from 'react-native';
...

export const Divider = () => {
  const width = PixelRatio.roundToNearestPixel(0.5);
  ...

  return <View style={{ width }} ... />
}
Aceves answered 25/5, 2021 at 7:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.