From b485273576aa6addb60bc104de9412a75b799d19 Mon Sep 17 00:00:00 2001 From: kdxcxs Date: Fri, 4 Dec 2020 23:27:45 +0800 Subject: [PATCH] feat: support go to detail view of a topic by pressing in the topic list view --- README.md | 2 + src/component/YooForumTopic.js | 14 ++++++ src/ui/YooForumTopicUI.js | 62 +++++++++++++++++++++---- src/ui/YooForumUI.js | 84 ++++++++++++++++++++++++++++++++-- 4 files changed, 149 insertions(+), 13 deletions(-) create mode 100644 src/component/YooForumTopic.js diff --git a/README.md b/README.md index 19cd3f6..6e14225 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,6 @@ - [ ] 在启动时检测是否已登录 - [ ] Splash 检测网络出错后在 Splash UI 中显示错误并不跳转 - [ ] Forum 初始化失败后 UI 显示错误信息 +- [ ] 当数据获取完成后通过动画转到话题列表 +- [ ] 解决当动画进行时点击话题标题动画会被打断的问题 diff --git a/src/component/YooForumTopic.js b/src/component/YooForumTopic.js new file mode 100644 index 0000000..04db5a5 --- /dev/null +++ b/src/component/YooForumTopic.js @@ -0,0 +1,14 @@ +import React, {Component} from 'react'; +import YooForumTopicUI from '../ui/YooForumTopicUI'; + +export default class YooForumTopic extends Component { + render() { + return ( + + ); + } +} diff --git a/src/ui/YooForumTopicUI.js b/src/ui/YooForumTopicUI.js index c43de2b..2e31704 100644 --- a/src/ui/YooForumTopicUI.js +++ b/src/ui/YooForumTopicUI.js @@ -1,25 +1,69 @@ -import React, {Component} from 'react'; -import {View, Text, StyleSheet} from 'react-native'; +import React, {Component, createRef} from 'react'; +import { + Animated, + View, + Text, + StyleSheet, + Pressable, + Dimensions, +} from 'react-native'; +const screenWidth = Dimensions.get('window').width; const styles = StyleSheet.create({ container: { - borderWidth: 1, + backgroundColor: 'mintcream', + borderRadius: 8, + padding: 16, + margin: 8, + width: screenWidth - 16, }, title: { - fontSize: 36, + fontSize: 24, }, owner: { - fontSize: 24, + fontSize: 16, }, }); +const AnimatedPressable = Animated.createAnimatedComponent(Pressable); export default class YooForumTopicUI extends Component { + constructor(props) { + super(props); + this.state = { + detailShowing: false, + layoutY: 0, + translate: new Animated.ValueXY({x: 0, y: 0}), + }; + this.topicHeaderRef = createRef(); + this.onPress = this.onPress.bind(this); + } + + onPress() { + if (!this.state.detailShowing) { + this.setState({detailShowing: true}); + this.props.showDetail(this); + } else { + this.setState({detailShowing: false}); + this.props.hideDetail(this); + } + } + render() { return ( - - {this.props.topic.title} - {this.props.topic.owner} - + { + this.setState({layoutY: event.nativeEvent.layout.y}); + }}> + + {this.props.topic.owner} + {this.props.topic.title} + + ); } } diff --git a/src/ui/YooForumUI.js b/src/ui/YooForumUI.js index 1b285a2..ac1200c 100644 --- a/src/ui/YooForumUI.js +++ b/src/ui/YooForumUI.js @@ -6,13 +6,21 @@ import { StyleSheet, ActivityIndicator, Image, + Animated, + Dimensions, } from 'react-native'; -import YooForumTopicUI from './YooForumTopicUI'; +import YooForumTopic from '../component/YooForumTopic'; +const screenWidth = Dimensions.get('window').width; +const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView); const styles = StyleSheet.create({ + container: { + width: screenWidth * 2, + }, hintContainer: { flex: 1, alignItems: 'center', + left: -screenWidth / 2, }, logo: { marginTop: 120, @@ -30,12 +38,80 @@ const styles = StyleSheet.create({ }); export default class YooForumUI extends Component { + constructor(props) { + super(props); + this.state = { + scrollEnabled: true, + currentPosition: 0, + translateX: new Animated.Value(0), + }; + this.showDetail = this.showDetail.bind(this); + this.hideDetail = this.hideDetail.bind(this); + } + + showDetail(topicRef) { + this.setState({scrollEnabled: false}); + Animated.parallel([ + Animated.timing(topicRef.state.translate, { + toValue: { + x: screenWidth, + y: this.state.currentPosition - topicRef.state.layoutY + 8, + }, + duration: 500, + useNativeDriver: true, + }), + Animated.timing(this.state.translateX, { + toValue: -screenWidth, + duration: 500, + useNativeDriver: true, + }), + ]).start(); + } + + hideDetail(topicRef) { + this.setState({scrollEnabled: true}); + Animated.parallel([ + Animated.timing(topicRef.state.translate, { + toValue: { + x: 0, + y: 0, + }, + duration: 500, + useNativeDriver: true, + }), + Animated.timing(this.state.translateX, { + toValue: 0, + duration: 500, + useNativeDriver: true, + }), + ]).start(); + } + render() { return ( - + + this.setState({currentPosition: event.nativeEvent.contentOffset.y}) + }> {this.props.hint === '' ? ( this.props.topics.map((topic, key) => ( - + )) ) : ( @@ -51,7 +127,7 @@ export default class YooForumUI extends Component { /> )} - + ); } }