014:动态设置标题栏背景&&TabView使用

请添加图片描述

动态设置标题栏背景

    // 关联dva
    const mapStateToProps = ({ album }: RootState) => {
        return {
            datas: album.albumDatas,//这里的home就是model中的namespace
        }
    }
    //这里需要connect对象
    const connector = connect(mapStateToProps)
    //自动推导dva中的state类型
    type ModelState = ConnectedProps<typeof connector>
    
    
    // 这里需要继承ModelState ,区别于antd pro中的umi.js  umi不需要
    // antd umi.js中使用dva:https://huangxiaoguo.blog.csdn.net/article/details/114890454
    interface IProps extends ModelState {
        navigation: RootStackNavigation,
        headerHeight: number,
        route: RouteProp<RootStackParamList, 'Album'>
    }

    
    componentDidMount() {
        const { navigation, dispatch, route: { params: { item: { id, image, title } } } } = this.props;
        navigation.setOptions({
            headerTitle: title,
            headerTransparent: true,//导航栏透明
            headerTitleStyle: {
                // opacity: 0
            },
            // headerBackground: () => {
            //     return (
            //         <Animated.View style={styles.headerBackground} />
            //     )
            // }
        })

TabView使用

请添加图片描述

models/album.ts:数据类
pages/home/album:分类模块
pages/home/album/index.tsx:分类页面
pages/home/album/data.d.ts:分类数据类型
pages/home/album/service.ts:分类数据请求
pages/home/album/components/tab:tab分类
pages/home/album/list:节目分类
pages/home/album/introdution:简介分类

  • models/album.ts:数据类
import { Model, Effect } from 'dva-core-ts'
import { Reducer } from 'redux'

//导入service远端数据请求
import { getAlbumData } from '@/pages/home/album/service'
import type { AlbumType } from '@/pages/home/album/data'
import { RootState } from '.'
import { pageCurrent, perpage } from '@/config/contant'

type AlbumState = {
    albumDatas: AlbumType
}

interface AlbumModelType extends Model {
    namespace: string
    state: AlbumState;//封装后台返回的数据
    effects: {
        asyncAlbumData: Effect;

    };
    reducers: {
        setStates: Reducer<AlbumState>,
    };
}

const AlbumModel: AlbumModelType = {
    namespace: 'album',
    state: {
        albumDatas: {
            id: '',
            introduction: '',
            summary: '',
            thumbnailUrl: '',
            title: '',
            author: {
                name: '',
                avatar: ''
            },
            list: []
        }

    },
    //异步
    effects: {
        *asyncAlbumData({ payload }, { call, put }) {
            const response = yield call(getAlbumData, { ...payload })
            if (response && response instanceof Object) {
                const { data } = response
                yield put({
                    type: 'setStates',
                    payload: {
                        albumDatas: { ...data }
                    }
                })
            }
        },

    },
    //同步
    reducers: {
        setStates(state, action) {
            return {
                ...state,
                ...action.payload,
            };
        },
    }
}

export default AlbumModel

  • pages/home/album/index.tsx:分类页面
import React, { Component } from 'react';
import { View, Text, Image, Animated, StyleSheet } from 'react-native';
import { RootState } from '@/models/index';
import { connect, ConnectedProps } from 'react-redux';
import { RootStackNavigation, RootStackParamList } from '@/navigator/index';
import { RouteProp } from '@react-navigation/native';
import { useHeaderHeight } from '@react-navigation/elements';
import { BlurView } from '@react-native-community/blur'
import Tab from './components/tab'

// 关联dva
const mapStateToProps = ({ album }: RootState) => {
    return {
        datas: album.albumDatas,//这里的home就是model中的namespace
    }
}
//这里需要connect对象
const connector = connect(mapStateToProps)
//自动推导dva中的state类型
type ModelState = ConnectedProps<typeof connector>


// 这里需要继承ModelState ,区别于antd pro中的umi.js  umi不需要
// antd umi.js中使用dva:https://huangxiaoguo.blog.csdn.net/article/details/114890454
interface IProps extends ModelState {
    navigation: RootStackNavigation,
    headerHeight: number,
    route: RouteProp<RootStackParamList, 'Album'>
}

class Album extends Component<IProps> {
    componentDidMount() {
        const { navigation, dispatch, route: { params: { item: { id, image, title } } } } = this.props;
        navigation.setOptions({
            headerTitle: title,
            headerTransparent: true,//导航栏透明
            headerTitleStyle: {
                opacity: 0
            },
            headerBackground: () => {
                return (
                    <Animated.View style={styles.headerBackground} />
                )
            }
        })

        dispatch({
            type: 'album/asyncAlbumData',
            payload: {
                id
            }
        })
    }
    render() {
        const { headerHeight, route: { params: { item: { id, image, title } } }, datas } = this.props
        return (
            <View style={styles.container}>
                <View style={[styles.header, { paddingTop: headerHeight }]}>
                    <Image source={{ uri: image }} style={styles.backgroud} />
                    <BlurView blurType='light' blurAmount={10} style={StyleSheet.absoluteFillObject} />
                    <View style={styles.leftView}>
                        <Image source={{ uri: image }} style={styles.thumbNail} />
                        <Image source={require('@/assets/images/cover-right.png')} style={styles.coverRight} />
                    </View>
                    <View style={styles.rightView}>
                        <Text style={styles.title}>{datas.title}</Text>
                        <View style={styles.summary}>
                            <Text numberOfLines={1} style={styles.summaryText}>{datas.summary}</Text>
                        </View>
                        {
                            datas.author?.avatar ? (
                                <View style={styles.author}>
                                    <Image source={{ uri: datas.author?.avatar }} style={styles.avatar} />
                                    <Text style={styles.name}>{datas.author.name}</Text>
                                </View>
                            ) : null
                        }

                    </View>
                </View>
                {/* 标签页面 */}
                <Tab />
            </View>

        );
    }
}

//获取标题栏高度
function Wrapper(props: IProps) {
    const headerHeight = useHeaderHeight()
    return <Album  {...props} headerHeight={headerHeight} />
}

const styles = StyleSheet.create({
    headerBackground: {
        flex: 1,
    },
    container: {
        flex: 1
    },
    header: {
        height: 260,
        flexDirection: 'row',
        paddingHorizontal: 20,
        alignItems: 'center'
    },
    backgroud: {
        ...StyleSheet.absoluteFillObject,
    },
    leftView: {
        marginRight: 26
    },
    thumbNail: {
        width: 98,
        height: 98,
        borderColor: '#fff',
        borderWidth: StyleSheet.hairlineWidth,
        borderRadius: 8,
        backgroundColor: '#fff'
    },
    coverRight: {
        height: 98,
        position: 'absolute',
        right: -25,
        resizeMode: 'contain'
    },
    rightView: {
        flex: 1,
    },
    title: {
        color: '#fff',
        fontSize: 18,
        fontWeight: '700'
    },
    summary: {
        backgroundColor: 'rgba(0,0,0,0.3)',
        padding: 10,
        marginVertical: 10,
        borderRadius: 4
    },
    author: {
        flexDirection: 'row',
        alignItems: 'center',
        marginBottom: 10,
    },
    avatar: {
        borderRadius: 13,
        height: 26,
        width: 26,
        marginRight: 8,
    },
    name: {
        color: '#fff',
        fontSize: 12,
    },
    summaryText: {
        color: '#fff'
    }
});

// export default Album;
export default connector(Wrapper)
  • pages/home/album/data.d.ts:分类数据类型
/**
 * 获取Item
 */
export type ListType = {
    date?: string,
    duration?: string,
    id: string,
    playVolume: number,
    title?: string
}
/**
 * 获取作者
 */
export type AuthorType = {
    avatar?: string,
    name?: string,
}

/**
 * 频道模块
 */
export type AlbumType = {
    id: string,
    introduction: string,
    summary: string,
    thumbnailUrl: string,
    title: string,
    author: AuthorType,
    list: ListType[]
}

  • pages/home/album/service.ts:分类数据请求
import request from '@/config/request';
import type { ListParamsType } from '@/models/data'
/**
 * 数据
 * @param params 
 * @returns 
 */
export async function getAlbumData(params: { id: number }): Promise<any> {
    return request({
        url: '/album/list',
        method: 'GET',
        params: { ...params }
    });
}

  • pages/home/album/components/tab:tab分类
import React, { Component } from 'react'
import { SceneRendererProps, TabBar, TabView } from 'react-native-tab-view'

import Introdution from '@/pages/home/album/introdution'
import List from '@/pages/home/album/list'
import { Platform, StyleSheet } from 'react-native'
type IRoute = {
    key: string,
    title: string
}

type IState = {
    index: number
    routes: IRoute[],
}

type IProps = {}

class Tab extends Component<IProps, IState>{
    state = {
        routes: [
            { key: 'introdution', title: '简介' },
            { key: 'albums', title: '节目' }
        ],
        index: 0
    }
    render() {
        const { routes, index } = this.state
        return (
            <TabView
                navigationState={{
                    routes: [...routes],
                    index: index,
                }}
                onIndexChange={(index: number) => {
                    //切换标签
                    this.setState({
                        index
                    })
                }}
                renderScene={({ route }: { route: IRoute }) => {
                    //标签对应的页面
                    switch (route.key) {
                        case 'introdution':
                            return <Introdution />;
                        case 'albums':
                            return <List />;
                        default:
                            break;
                    }
                    return null
                }}
                //修改tab样式
                renderTabBar={(props: SceneRendererProps & { navigationState: IState }) => {
                    return <TabBar {...props}
                        scrollEnabled={true}
                        tabStyle={styles.tabStyle}
                        labelStyle={styles.label}
                        style={styles.tabbar}
                        indicatorStyle={styles.indicator} />
                }} />
        )
    }
}
const styles = StyleSheet.create({
    tabStyle: {
        width: 80
    },
    label: {
        color: '#333'
    },
    tabbar: {
        backgroundColor: '#fff',
        ...Platform.select({
            android: {
                elevation: 0,
                borderBottomColor: '#e3e3e3',
                borderBottomWidth: StyleSheet.hairlineWidth
            }
        })
    },
    indicator: {
        backgroundColor: '#eb6d48',
        borderLeftWidth: 20,
        borderRightWidth: 20,
        borderColor: '#fff'
    }
})
export default Tab
  • pages/home/album/list:节目分类


import { RootState } from '@/models/index';
import React, { Component } from 'react';
import { FlatList, ListRenderItemInfo, StyleSheet, Text, View } from 'react-native';
import { connect, ConnectedProps } from 'react-redux';
import Touchable from '@/components/touchable/index'
import IconFont from '@/assets/iconfont';
import { ListType } from '../data';
// 关联dva
const mapStateToProps = ({ album }: RootState) => {
    return {
        datas: album,//这里的home就是model中的namespace
    }
}

//这里需要connect对象
const connector = connect(mapStateToProps)
//自动推导dva中的state类型
type ModelState = ConnectedProps<typeof connector>


// 这里需要继承ModelState ,区别于antd pro中的umi.js  umi不需要
// antd umi.js中使用dva:https://huangxiaoguo.blog.csdn.net/article/details/114890454
interface IProps extends ModelState {
}

class List extends Component<IProps> {
    //每个item数据
    renderItem = ({ item, index }: ListRenderItemInfo<ListType>) => {
        return (
            <Touchable style={styles.item} >
                <View style={styles.left}>
                    <Text style={styles.serial}>{index + 1}</Text>
                </View>
                <View style={styles.centerView}>
                    <Text style={styles.title}>{item.title}</Text>
                    <View style={styles.centerRight}>
                        <View style={styles.volumeView}>
                            <IconFont name="icon24gf-headphones" color="#939393" />
                            <Text style={styles.otherText}>{item.playVolume}</Text>
                        </View>
                        <View style={styles.duration}>
                            <IconFont name="iconshijian" color="#939393" />
                            <Text style={styles.otherText}>{item.duration}</Text>
                        </View>
                    </View>
                </View>
                <View>
                    <Text style={styles.date}>{item.date}</Text>
                </View>
            </Touchable>
        )
    }
    render() {
        const { datas: { albumDatas: { list } } } = this.props
        return (
            <FlatList
                style={styles.container}
                data={list}
                renderItem={this.renderItem}
                keyExtractor={(item, index) => index + ''} //默认是以id来区分的,可以省略改设置,当无id字段的时候可以通过keyExtractor创建 keys
            // keyExtractor={(item, index) => item.id} //默认是以id来区分的,可以省略改设置,当无id字段的时候可以通过keyExtractor创建 keys
            />
        );
    }
}
const styles = StyleSheet.create({
    container: {
        backgroundColor: '#fff'
    },
    item: {
        flexDirection: 'row',
        padding: 20,
        borderBottomWidth: StyleSheet.hairlineWidth,
        borderBottomColor: '#dedede',
    },
    left: {
        justifyContent: 'center',
        alignItems: 'center',
    },
    serial: {
        color: '#838383',
        fontWeight: '800',
    },
    title: {
        fontWeight: '500',
        color: '#333',
        marginBottom: 15,
    },
    centerView: {
        flex: 1,
        marginHorizontal: 25,
    },
    centerRight: {
        flexDirection: 'row',
    },
    volumeView: {
        flexDirection: 'row',
        marginRight: 10,
    },
    duration: { flexDirection: 'row' },
    otherText: {
        marginHorizontal: 5,
        color: '#939393',
        fontWeight: '100',
    },
    date: {
        color: '#939393',
        fontWeight: '100',
    },
});

// export default List;
export default connector(List);
  • pages/home/album/introdution:简介分类


import { RootState } from '@/models/index';
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { connect, ConnectedProps } from 'react-redux';
// 关联dva
const mapStateToProps = ({ album }: RootState) => {
    return {
        datas: album,//这里的home就是model中的namespace
    }
}

//这里需要connect对象
const connector = connect(mapStateToProps)
//自动推导dva中的state类型
type ModelState = ConnectedProps<typeof connector>


// 这里需要继承ModelState ,区别于antd pro中的umi.js  umi不需要
// antd umi.js中使用dva:https://huangxiaoguo.blog.csdn.net/article/details/114890454
interface IProps extends ModelState {
}


class Introdution extends Component<IProps>{
    render() {
        const { datas } = this.props
        return (
            <View style={styles.container}>
                <Text>{datas.albumDatas.introduction}</Text>
            </View>
        );
    }
}
const styles = StyleSheet.create({
    container: {
        padding: 10
    }
})
// export default Introdution;
export default connector(Introdution);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值