Reagiere auf Native FlatList mit Spalten, Letzte Artikelbreite

76

Ich verwende eine FlatList, um eine Liste von Elementen in zwei Spalten anzuzeigen

<FlatList style={{margin:5}}
  data={this.state.items}
  numColumns={2}
  keyExtractor={(item, index) => item.id }
  renderItem={(item) => <Card image={item.item.gallery_image_url} text={item.item.name}/> }
/>

Die Kartenkomponente ist nur eine Ansicht mit einigen Stilen:

<View style={{ flex: 1, margin: 5, backgroundColor: '#ddd', height: 130}} ></View>

Es funktioniert einwandfrei, aber wenn die Anzahl der Elemente ungerade ist, enthält die letzte Zeile nur ein Element und dieses Element erstreckt sich über die gesamte Breite des Bildschirms.

Wie kann ich den Artikel auf die gleiche Breite wie die anderen einstellen?

Geben Sie hier die Bildbeschreibung ein

Escobar5
quelle

Antworten:

35

Es gibt ein paar Dinge, die Sie hier ausprobieren können.

A) Festlegen einer vordefinierten Breite für die Karte (möglicherweise gleich der von Ihnen festgelegten Höhe?). Dann können Sie verwenden alignItems, um die Karte in der Mitte oder links zu positionieren - Unsicher, welche Sie hier wollten.

B) Wenn es eine gerade Anzahl von Karten gibt, können Sie am Ende eine leere Ansicht hinzufügen, um diesen Platz zu füllen. Ich finde diese Methode ziemlich klobig, aber nützlich, wenn ich versuche, Platz für zukünftige Elemente zu lassen.

C) Einfach verwenden alignItems: 'space-between, ich möchte dies verwenden, um Elemente zu zentrieren, aber Sie müssten die Breite definieren oder etwas wie verwendenflex:0.5

Ich schlage vor, mehr über Flexbox zu recherchieren, um Ihnen dabei zu helfen, da es schwierig ist, den Kontext dieser Situation zu bestimmen. Ich gehe davon aus, dass die oben genannten Methoden helfen werden, aber wenn nicht, sind hier einige Links, die Sie sich ansehen können -

Erster Link

Zweiter Link

Dritter Link Link gebrochen

Hoffe das hilft. Wenn Sie weitere Erläuterungen benötigen, fragen Sie einfach

Ryan Turnbull
quelle
1
B ist ein vernünftiger Hack. Option A ist redundant. Sie können einfach festlegen, dass sie wie diese ausgerichtet werden, indem Sie flexWrap hinzufügen. Was ist der Zweck von numColumns in diesem Fall?
eden
Ich habe mich für B entschieden, aber ich habe es getan, und obwohl es ein Hack ist, funktioniert es einwandfrei, und ich muss die Breite der Elemente nicht angeben (ich möchte, dass sie sich an die verfügbare Breite anpassen)
Escobar5
@ Ryan: Ich möchte die erste Zelle voll dehnen und mit 3 Spalten, was soll ich tun?
Abhishek Thapliyal
Option C: Flex einstellen: 0.5 Funktioniert für mich.
Aman Goyal
47

Verwenden Sie für Ihren Fall flex: 1/2

Deshalb: Ihr Artikel sollte einen Flex von 1 / (Anzahl der Spalten) haben. Wenn Sie 3 Spalten haben, sollte Ihr Artikel einen Flex von 1/3 haben

Emilius Mfuruki
quelle
2
Ich bin mir nicht sicher, warum dies nicht als Antwort markiert ist. Dies ist die einfachste und richtige Lösung!
tnort173
8
wenn ich flex gebe: 1/2, die Breite des letzten Elements größer als die vorherigen Elemente, Wie können wir diese Idee bitte beheben
iOSDev
Geniussss !!! das hat funktioniert! beste Problemumgehung aller Zeiten. Danke Mann, Sie verdienen die richtige Antwort
msqar
Ich habe dies versucht und wie "iOSDev" sagte, ist das einzelne Element in der letzten Zeile etwas breiter als das erste Element der vorherigen Zeile. Daher funktioniert diese Lösung bei mir nicht
22.
@ tnort173 weil das nicht funktioniert; Der letzte Artikel ist noch größer als andere.
Abdul Sadik Yalcin
18

Sie können versuchen, die aktuelle Breite des Geräts über Bemaßungen abzurufen, anhand der Anzahl der zu rendernden Spalten abzüglich der Ränder zu rechnen und diese als minWidth und maxWidth festzulegen.

Zum Beispiel:

const {height, width} = Dimensions.get('window');
const itemWidth = (width - 15) / 2;

<View style={{ flex: 1, margin: 5, backgroundColor: '#ddd', minWidth: {this.itemWidth}, maxWidth: {this.itemWidth}, height: 130}} ></View>
Skyplor
quelle
Bin in die gleiche Situation geraten und ich bevorzuge definitiv diese Lösung. Es ist nicht nur einfacher, sondern auch sinnvoller, da wir letztendlich flex:1den Fall mit einer ungeraden Spalte begrenzen wollen
Arnaud Moret
Sehr schön. Vielen Dank!
Mark
Fehler erhalten: Arten von Eigenschaften 'Stil' sind nicht kompatibel
Ghost
@ Ghost Verwenden Sie Typescript? Wenn ja, könnte dieser Fehler stattdessen mit Typescript zusammenhängen
skyplor
10

Dies ist die sauberste Art, ein FlatListmit Spalten und gleichmäßigem Abstand zu gestalten:

    <FlatList style={{margin:5}}
        numColumns={2}                  // set number of columns 
        columnWrapperStyle={style.row}  // space them out evenly
        
        data={this.state.items}
        keyExtractor={(item, index) => item.id }
        renderItem={(item) => <Card image={item.item.gallery_image_url} text={item.item.name}/> }
    />       

    const style = StyleSheet.create({
        row: {
            flex: 1,
            justifyContent: "space-around"
        }
    });
jasonleonhard
quelle
6

Der Grund dafür ist, dass Ihre Karte Stil hat flex: 1und daher versucht, den gesamten verbleibenden Speicherplatz zu erweitern. Sie können das Problem beheben, indem Sie maxWidth: '50%'es Ihrem Kartenstil hinzufügen

<View style={{ flex: 1, margin: 5, backgroundColor: '#ddd', height: 130, maxWidth: '50%'}} ></View>
Tùng Nguyễn
quelle
einfachste Lösung aller Zeiten
Muhammad Ashfaq
0

@ Emilius Mfuruki Vorschlag ist gut. Aber wenn Sie Text mit unterschiedlicher Länge haben, funktioniert er nicht perfekt.

Dann const {height, width} = Dimensions.get ('window'); const itemWidth = (width - (MarginFromTheSide * 2 + MarginInBetween * (n-1))) / n;

Verwenden Sie diese Breite in Ihrer Ansicht.

Verwenden Sie in FlatList columnWrapperStyle = {{flex: 1, rechtfertigen Sie den Inhalt: 'Leerzeichen',}}

Funktioniert perfekt.

Amit
quelle
0

Sie können ListFooterComponent = {this.renderFooter} verwenden

Clapa Lucian
quelle
0

benutze einfach flex: 0.5 und width: '50% '

Jagdish Suryawanshi
quelle