- React Native By Example
- Richard Kho
- 668字
- 2021-07-09 18:21:34
Basic ExpandableCell implementation
This is how we can start building ExpandableCell:
// Tasks/app/components/ExpandableCell/index.js
import React, { Component, PropTypes } from 'react';
import {
LayoutAnimation,
Text,
TouchableHighlight,
View
} from 'react-native';
import styles from './styles';
export default class ExpandableCell extends Component {
This sets the title as an expected string PropTypes for the component:
static propTypes = {
title: PropTypes.string.isRequired
}
Now we track a Boolean named expanded in the component state. By default, our child components should not be visible:
constructor (props) {
super (props);
this.state = {
expanded: false
}
}
Set the LayoutAnimation style for whenever this component changes:
componentWillUpdate () {
LayoutAnimation.linear();
}
Wrap a TouchableHighlight component around the Text of the ExpandableCell. It calls _onExpand when pressed:
render () {
return (
<View style={ styles.expandableCellContainer }>
<View>
<TouchableHighlight
onPress={ () => this._expandCell() }
underlayColor={ '#D3D3D3' }
>
Add a ternary operator to add a maxHeight property to the styling of this View in the event that the component is not expanded:
<Text style={ styles.visibleContent }>
{ this.props.title}</Text>
</TouchableHighlight>
</View>
<View style={ [styles.hiddenContent,
this.state.expanded ? {} : {maxHeight: 0}]}>
This renders any children nested within the component itself:
{ this.props.children }
</View>
</View>
)
}
The following is a callback to toggle the expanded Boolean in the component state:
_expandCell () {
this.setState({
expanded: !this.state.expanded
});
}
}
This is the styling for ExpandableCell:
// Tasks/app/components/ExpandableCell/styles.js
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
expandableCellContainer: {
flex: 1,
padding: 10,
paddingTop: 0
},
hiddenContent: {
overflow: 'hidden'
},
visibleContent: {
fontSize: 24
}
})
A basic implementation of this in EditTask will look like this:
// Tasks/app/components/EditTask/index.js
...
import ExpandableCell from '../ExpandableCell';
export default class EditTask extends Component {
...
Render an ExpandableCell component with a title:
render () {
return (
<View style={ styles.editTaskContainer }>
<ExpandableCell title={ 'Due On' }>
Nest DatePickerIOS within ExpandableCell so that it initially stays hidden:
<DatePickerIOS
...
/>
</ExpandableCell>
</View>
);
}
...
}
Ideally, this component will show one of the following:
- The due date of the selected task, if it exists
- A blank placeholder to select a date if a due date does not exist
We'll worry about things such as clearing the due date later but, for now, we should modify EditTask so that the title prop it passes to ExpandableCell is dependent on whether the task has a due date assigned to it or not. This is how the component should currently look:
Here is how I solved the problem. The only file changed since the last example is the EditTask component:
// Tasks/app/components/EditTask/index.js
...
import moment from 'moment';
...
export default class EditTask extends Component {
...
render () {
const noDueDateTitle = 'Set Reminder';
const dueDateSetTitle = 'Due On ' + this.state.formattedDate;
Set two strings to show the title prop for ExpandableCell.
return (
<View style={ styles.editTaskContainer }>
<ExpandableCell
title={ this.state.dateSelected ?
dueDateSetTitle : noDueDateTitle }>
Use a ternary operator to decide which string to pass in to ExpandableCell.
...
</ExpandableCell>
</View>
);
}
_formatDate (date) {
return moment(date).format('lll');
}
I also imported moment from npm to use its powerful date formatting capabilities. Moment is a very popular, widely-used library that allows us to manipulate dates with JavaScript. Installing it was as simple as opening the Terminal to the project's root folder and typing as follows:
npm install --save moment
The MomentJS library is well documented and its main page, found at https:// momentjs.com, will show you all the ways you can utilize it. For this file, I used Moment's the format method and set the formatting to show an abbreviated month name, followed by the day and year in numbers and the time.
A sample Moment date formatted with the 'lll' flag will appear like this:
Dec 25, 2016 12:01 AM
There are different ways to format your dates with Moment, and I would encourage you to play around with the library to find a date format that works best for you.
Set dateSelected to true and add the Moment-formatted version of the date to state, which in turn fires the render method of this component again to update the title string passed into ExpandableCell:
_onDateChange (date) {
this.setState({
...
dateSelected: true,
formattedDate: this._formatDate(date)
});
}
}
By the end of this section, your app should look something like the following screenshot:
- The Android Game Developer's Handbook
- Python for Secret Agents:Volume II
- Learning Data Mining with Python
- PyTorch自然語言處理入門與實戰
- 三維圖形化C++趣味編程
- 深入淺出Windows API程序設計:編程基礎篇
- 數據結構與算法JavaScript描述
- 游戲程序設計教程
- Mastering Google App Engine
- Python漫游數學王國:高等數學、線性代數、數理統計及運籌學
- Access 2010數據庫應用技術(第2版)
- 編程改變生活:用Python提升你的能力(進階篇·微課視頻版)
- Natural Language Processing with Python Quick Start Guide
- Python 3快速入門與實戰
- Deep Learning for Natural Language Processing