简体   繁体   English

在ScrollView中使用react-native-collapsible呈现每行两个项目

[英]render two items per row with react-native-collapsible within ScrollView

I'm trying to put two headers (and their respective collapsed content) per row. 我正在尝试每行放置两个标题(以及它们各自的折叠内容)。 The problem is that contentContainerStyle = { {flexDirection: 'row', flexWrap: 'wrap'} } and then making the cards half the width of the screen (found in styles.card) doesn't work. 问题在于contentContainerStyle = {{flexDirection:'row',flexWrap:'wrap'}},然后使卡片的宽度为屏幕宽度的一半(在styles.card中可以找到)不起作用。 As in, it won't force two cards to come onto the same row. 就像这样,它不会强制两张卡进入同一行。 I'm a noob at CSS and styles in general, so any help would be greatly appreciated. 我对CSS和样式一无所知,因此任何帮助将不胜感激。 I've attached two images to show what I currently have. 我已附加了两个图像以显示当前的图像。 Image showing headers Image showing content 显示标题的 图像显示内容的图像

This stackoverflow helped me put my cards on the left half of the screen. 这个堆栈溢出帮助我将卡片放在屏幕的左半部分。 But the right half is still whitespace and I just can't seem to force two 'cards' (for lack of a better term) on the same row. 但是右半部分仍然是空白,我似乎无法在同一行上强制使用两张“卡片”(由于缺乏更好的用词)。

Here's relevant code if you feel like perusing through this. 如果您想仔细阅读下面的相关代码。

 import React, { Component } from 'react' import { Dimensions, View, Image, StyleSheet, ScrollView, RefreshControl, TouchableOpacity, TouchableHighlight } from 'react-native'; import {withNavigation, StackNavigator} from 'react-navigation'; // Version can be specified in package.json import { Container, Header, Content, Card, CardItem, Thumbnail, Text, Left, Body } from 'native-base'; import {Button} from 'react-native-elements' import Icon from 'react-native-vector-icons/FontAwesome' import firebase from '../cloud/firebase.js'; import {database, p} from '../cloud/database'; import {storage} from '../cloud/storage'; import * as Animatable from 'react-native-animatable'; import Collapsible from 'react-native-collapsible'; import Accordion from 'react-native-collapsible/Accordion'; var {height, width} = Dimensions.get('window'); class MarketPlace extends Component { constructor(props) { super(props); this.state = { refreshing: false, isGetting: true, activeSection: false, collapsed: true, }; //this.navToChat = this.navToChat.bind(this); } componentWillMount() { setTimeout(() => { this.getProducts(); }, 4); } findRoom(rooms, key) { for(var room of rooms ) { if(room.name === key) {return room.id} } } navToChat(key) { console.log(key); //create separate Chats branch const CHATKIT_USER_NAME = firebase.auth().currentUser.uid; const tokenProvider = new Chatkit.TokenProvider({ url: CHATKIT_TOKEN_PROVIDER_ENDPOINT }); // This will instantiate a `chatManager` object. This object can be used to subscribe to any number of rooms and users and corresponding messages. // For the purpose of this example we will use single room-user pair. const chatManager = new Chatkit.ChatManager({ instanceLocator: CHATKIT_INSTANCE_LOCATOR, userId: CHATKIT_USER_NAME, tokenProvider: tokenProvider }); chatManager.connect().then(currentUser => { this.currentUser = currentUser; setTimeout(() => { if(this.currentUser.rooms.length > 0) { //first check if you've already subscribed to this room for(var room of this.currentUser.rooms) { var {name} = room; console.log(name); if(name === key) { console.log('navigating to room') this.props.navigation.navigate( 'CustomChat', {key: key, id: this.findRoom(this.currentUser.rooms, key)} ) } } //subscribe to room and navigate to it } else { //subscribe to at least the room for this product console.log('subscribe to your very first product chat room') this.currentUser.getJoinableRooms().then( (rooms) => { this.currentUser.joinRoom( { roomId: this.findRoom(rooms, key) }) setTimeout(() => { this.props.navigation.navigate( 'CustomChat', {key: key, id: this.findRoom(rooms, key)} ) }, 1000); //this.setState({id: this.findRoom(rooms, key) }); } ) } }, 3000); //first find roomId from key }); } //switch between collapsed and expanded states toggleExpanded = () => { this.setState({ collapsed: !this.state.collapsed }); }; setSection = section => { this.setState({ activeSection: section }); }; renderHeader = (section, _, isActive) => { return ( <Animatable.View duration={400} style={[styles.card, isActive ? styles.active : styles.inactive]} transition="backgroundColor" > <Image source={{uri: section.uri}} style={{height: 200, width: 100}}/> </Animatable.View> ); }; renderContent = (section, _, isActive) => { return ( <Animatable.View duration={400} style={[styles.card, isActive ? styles.active : styles.inactive]} transition="backgroundColor" > <Animatable.Text animation={isActive ? 'bounceIn' : undefined}> {section.text.name} </Animatable.Text> <Animatable.Text animation={isActive ? 'fadeInDownBig' : undefined}> {section.text.brand} </Animatable.Text> <Animatable.Text animation={isActive ? 'fadeInUpBig' : undefined}> {section.text.description} </Animatable.Text> <Animatable.Text animation={isActive ? 'slideInLeft' : undefined}> {section.text.gender} </Animatable.Text> <Animatable.Text animation={isActive ? 'slideInRight' : undefined}> {section.text.type} </Animatable.Text> <Animatable.Text animation={isActive ? 'bounceIn' : undefined}> {section.text.condition} </Animatable.Text> <Animatable.Text animation={isActive ? 'bounceRight' : undefined}> {section.text.size} </Animatable.Text> <Animatable.Text animation={isActive ? 'bounceLeft' : undefined}> ${section.text.price} </Animatable.Text> <Button buttonStyle={{ backgroundColor: "#000", width: 40, height: 40, borderColor: "transparent", borderWidth: 0, borderRadius: 5 }} icon={{name: 'credit-card', type: 'font-awesome'}} title='BUY' onPress = { () => { console.log('going to chat'); //subscribe to room key this.navToChat(section.key); } } /> </Animatable.View> ); } getProducts() { const keys = []; database.then( (d) => { //get list of uids for all users var p = d.Products; console.log(p); this.setState({ p }); }) .then( () => { this.setState( {isGetting: false} ); } ) .catch( (err) => {console.log(err) }) } // componentWillMount() { // var products = this.getProducts(); // return products; // } render() { if(this.state.isGetting) { return ( <View> <Text>Loading...</Text> </View> ) } return ( <ScrollView contentContainerStyle={styles.contentContainerStyle} > <Collapsible collapsed={this.state.collapsed} style={styles.contentContainerStyle}> <View style={styles.content}> <Text> Bacon ipsum dolor amet chuck turducken landjaeger tongue spare ribs </Text> </View> </Collapsible> <Accordion activeSection={this.state.activeSection} sections={this.state.p} touchableComponent={TouchableOpacity} renderHeader={this.renderHeader} renderContent={this.renderContent} duration={400} onChange={this.setSection} /> </ScrollView> ) } } export default withNavigation(MarketPlace); const styles = StyleSheet.create({ contentContainerStyle: { flexGrow: 1, flexDirection: 'row', flexWrap: 'wrap' }, mainContainer:{ marginTop:15, marginLeft:20, marginRight:20 }, container: { flex: 1, justifyContent: 'center', backgroundColor: '#F5FCFF', }, title: { textAlign: 'center', fontSize: 22, fontWeight: '300', marginBottom: 20, }, header: { backgroundColor: '#F5FCFF', padding: 10, }, headerText: { textAlign: 'center', fontSize: 16, fontWeight: '500', }, content: { padding: 20, backgroundColor: '#fff', }, card: { backgroundColor: '#fff', width: (width / 2) - 15, height: (height / 2) - 10, marginLeft: 10, marginTop: 10 } , active: { backgroundColor: '#8cdbab', }, inactive: { backgroundColor: '#fff', }, selectors: { marginBottom: 10, flexDirection: 'row', justifyContent: 'center', }, selector: { backgroundColor: '#F5FCFF', padding: 10, }, activeSelector: { fontWeight: 'bold', }, selectTitle: { fontSize: 14, fontWeight: '500', padding: 10, }, }); 

弄清楚了,使用Component两次(通常是n次),contentContainerStyle将强制每行两个项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM