首页 > 解决方案 > 如何使用 React-Native 在移动应用中实现类似 youtube 播放器的 Mini View

问题描述

我想在 React-Native 中实现一个迷你视图或浮动视图,它应该保持或打开,直到我们关闭它,如果我们导航到其他屏幕,它应该保持打开状态有什么想法吗? 在此处输入图像描述

标签: reactjsreact-nativereact-native-androidreact-navigationreact-native-ios

解决方案


有两种方法可以做。你可以按照这个文档 MiniView

或者您可以像这样制作自己的自定义组件

import React, { Component } from "react"
import { StatusBar, View, StyleSheet, Alert, FlatList, TextInput, Button, Image, SafeAreaView, Animated } from "react-native"
import { connect } from "react-redux"
import Alertable from "app/components/Alert/Alert"
import { AlertActions, NavigationActions, UserActions, OrderActions, } from "app/store/actions"
import Style from 'app/style'
import handShake from 'app/assets/img/handShake.png'
import route from 'app/assets/img/route.png'
import endDay from 'app/assets/img/end-day.png'
import { DashboardButton, Navigation } from 'app/components'
import FA from 'react-native-vector-icons/FontAwesome5'
const AnimatedIcon = Animated.createAnimatedComponent(FA)

let connectProps = {
  ...AlertActions,
  ...NavigationActions,
  ...UserActions,
  ...OrderActions,
}

let connectState = state => ({
  menuStatus: state.User.meta,
  StartDayStatus: state.User.current,
})

let enhancer = connect(
  connectState,
  connectProps
)

const buttonsArr = [
  {
    id: 1,
    img: handShake,
    title: 'Start Day'
  },
  {
    id: 2,
    img: route,
    title: 'Planned Route'
  },
  {
    id: 3,
    img: endDay,
    title: 'End Day'
  }
]

class DashboardScreen extends Component {

  animVal = new Animated.Value(0);
  // initialize animated value to use for animation, whereas initial value is zero


  interpolateHeight = this.animVal.interpolate({ outputRange: ['100%', '24%'], inputRange: [0, 1], })

  // initialize interpolation to control the output value that will be passed on styles
  // since we will animate both search bar and icon. we need to initialize both 
  // on icon we will animate the scale whereas outputRange starts at 0 end in 1
  // on search bar we will animate width. whereas outputRange starts at 100% end in 90%

  animatedTransition = Animated.spring(this.animVal, { toValue: 1 })
  // we use spring to make the animation bouncy . and it will animate to Value 1

  clickAnimate = () => {
    this.animatedTransition.start()
  }

  componentDidMount() {
    this.props.saveNavigation(this.props.navigation)
  }

  buttonPressed(title) {
    let startDayStatus = this.props.StartDayStatus.toJS().startUserDay

    switch (title) {
      case 'Planned Route':
        this.props.resetStates()
        if (!startDayStatus) {
          alert("Start your day first!")
          break
        }
        this.props.navigation.navigate("routeIndexScreen")
        break
      case 'Start Day':
        this.props.startUserDay(true)
        if (startDayStatus) break
        this.props.resetStates()
        this.props.navigation.navigate("routeIndexScreen")
        break
      case 'End Day':
        if (startDayStatus)
          this.askToEnd()
        break

      default:
        this.props.startUserDay(false)
    }
  }

  askToEnd() {
    Alert.alert(
      "Are you sure",
      `You want to "End day"`,
      [
        { text: "Yes", onPress: () => this.props.startUserDay(false) },
        {
          text: "No",
          style: "cancel"
        },
      ],
      { cancelable: false }
    );
  }

  renderItem({ item }) {
    let StartDayStatus = this.props.StartDayStatus.toJS().startUserDay
    return (
      <DashboardButton
        img={item.img}
        title={item.title}
        showOpacity={StartDayStatus && item.title === 'Start Day' || !StartDayStatus && item.title === 'End Day'}
        buttonPressed={this.buttonPressed.bind(this)}
      />
    )
  }

  render() {

    return (
      <Navigation navigation={this.props.navigation} style={{ backgroundColor: '#fff' }}>
        <StatusBar barStyle="light-content" />
        <Navigation.Top
          menu
          title={'Dashboard'}
          navigation={this.props.navigation}
        />
        <View style={styles.container}>
          <Button title='animate icon' onPress={this.clickAnimate} />


          <View style={styles.search}>


            <Animated.View style={{ height: this.interpolateHeight, }}>
              <View style={{ height: '100%', minHeight: 200, width: 400, backgroundColor: 'red', marginBottom: 200 }}>
                <Image
                  source={endDay}
                  style={{ height: '100%', width: '100%',resizeMode:'contain' }}
                />
              </View>
            </Animated.View>


          </View>







          {/* <View style={styles.buttonContainer}>
            <FlatList
              data={buttonsArr}
              showsVerticalScrollIndicator={false}
              renderItem={this.renderItem.bind(this)}
              keyExtractor={(item) => item.id.toString()}
              contentContainerStyle={{ paddingBottom: 50 }}
            />
          </View> */}

        </View>
      </Navigation>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'gray'
  },
  imageContainer: {
    width: Style.DEVICE_WIDTH,
    height: Style.DEVICE_HEIGHT / 3.6,
    position: 'absolute',
    top: 0,
    flex: 1,
    justifyContent: 'center',
    alignContent: 'center',
    alignItems: 'center',
  },
  menuButton: {
    height: 50,
    width: 50,
    position: 'absolute',
    top: 50,
    left: 20,
  },
  menuIconStyle: {
    height: 35,
    width: 35,
  },
  screenTitle: {
    position: 'absolute',
    top: 50,
    color: 'white',
    fontSize: 24,
  },
  buttonContainer: {
    position: 'absolute',
    top: '9%',
    zIndex: 2,
    width: '100%',
    justifyContent: 'center',
    alignItems: 'center',
    alignContent: 'center',
    backgroundColor: 'transparent',
  },

  ///////
  container: {
    backgroundColor: '#F79D42',
    // flex: 1,
    height: '100%',
    paddingTop: 20,
    flexDirection: 'column',
    // justifyContent: 'center',
    alignItems: 'center',
    flex: 1,
  },
  input: {
    width: '100%',
    height: '100%',
    backgroundColor: 'gray',
    textAlign: 'center'
  },
  search: {
    //flexDirection: 'row-reverse',
    width: '90%',
    //  height: 40,
    alignItems: 'center',
    justifyContent: 'flex-end',
    flex: 1,
    paddingBottom: 80
  }
})

export default enhancer(Alertable(DashboardScreen))

推荐阅读