Skip to content

react-native笔记(八):主题

图片

今天配置app主题,是用的react的createContext方法

开始

新建theme.js文件

js
import {createContext} from 'react'

//配置了默认的light主题和dark黑夜主题
export const themeList = {
    light: {
        appColor: '#fc5531',
        bgColor: '#EDEDED',
        viewColor: '#ffffff',
        fontColor: '#333'
    },
    dark: {
        appColor: '#eee',
        bgColor: '#000',
        viewColor: '#151515',
        fontColor: '#f4f4f4'
    }


} 

//创建上下文
export const Themes = createContext({
    theme: '',//也可以默认给个值
    changeTheme: ()=>{}
})
import {createContext} from 'react'

//配置了默认的light主题和dark黑夜主题
export const themeList = {
    light: {
        appColor: '#fc5531',
        bgColor: '#EDEDED',
        viewColor: '#ffffff',
        fontColor: '#333'
    },
    dark: {
        appColor: '#eee',
        bgColor: '#000',
        viewColor: '#151515',
        fontColor: '#f4f4f4'
    }


} 

//创建上下文
export const Themes = createContext({
    theme: '',//也可以默认给个值
    changeTheme: ()=>{}
})

app.js使用

最关键的就是这一句:

每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。

图片

这样就可以在app组件根节点上使用,后面的的子节点就可以监听主题变量的变化及时更新视图

js
// 引入
import {Themes,themeList} from './themes'

class App extends Component{
    constructor(props){
        super(props);
         //改变主题事件
        this.changeTheme = () => {
            this.setState(state => ({
            theme:
              state.theme === themeList.dark
                ? themeList.light
                : themeList.dark,
          }));
        };

        // State 也包含了更新函数,因此它会被传递进 context provider。
        this.state = {
            theme: themeList.light,//设置默认为light主题
            changeTheme: this.changeTheme, //改变的方法
        };
    }
    render () {
        return (
            // 调用context的Provider组件,并把this.state赋值给组件
            <Themes.Provider value={this.state}>
                <SafeAreaView style={{width: '100%',height: '100%'}}>
                    <Router/>
                </SafeAreaView>
            </Themes.Provider>
        )
    }
    
};
// 引入
import {Themes,themeList} from './themes'

class App extends Component{
    constructor(props){
        super(props);
         //改变主题事件
        this.changeTheme = () => {
            this.setState(state => ({
            theme:
              state.theme === themeList.dark
                ? themeList.light
                : themeList.dark,
          }));
        };

        // State 也包含了更新函数,因此它会被传递进 context provider。
        this.state = {
            theme: themeList.light,//设置默认为light主题
            changeTheme: this.changeTheme, //改变的方法
        };
    }
    render () {
        return (
            // 调用context的Provider组件,并把this.state赋值给组件
            <Themes.Provider value={this.state}>
                <SafeAreaView style={{width: '100%',height: '100%'}}>
                    <Router/>
                </SafeAreaView>
            </Themes.Provider>
        )
    }
    
};

嵌套的组件使用

以个人中心页面为例

这时用context对象的Consumer组件,它可以获取当前最近的父节点provider提供的value值

图片

使用:

看代码中的注释文字

js
// 导入theme
import {Themes} from '../theme'

const Me = ()=> {
    return (
        //调用Consumer组件,包裹住元素
        <Themes.Consumer>
             // 以参数的方式传递theme参数和changeTheme方法
            {({theme,changeTheme})=>(
                       // 样式就可以用theme的样式设置
                <View style={{backgroundColor:theme.bgColor,width:'100%',height: '100%'}}>
                    <Statusbar bgColor={theme.bgColor}/>
                    <View style={[styles.meEntry,{backgroundColor: theme.viewColor}]}>
                        <TouchableOpacity 
                        activeOpacity={0.5}
                        underlayColor="#ffffff"
                        onPress={changeTheme}>  //点击切换主题事件,调用changeTheme方法
                            <View style={[styles.meEntryBox,styles.meEnterLine]}>
                                <Text style={[styles.meEntryTitle,{color: theme.fontColor}]}>主题</Text>
                                <Text><Icon name="angle-right" size={20} color="#ccc" /></Text>
                            </View>
                        </TouchableOpacity>
                    </View>
                </View>
            )}
        </Themes.Consumer>
    )
}
// 导入theme
import {Themes} from '../theme'

const Me = ()=> {
    return (
        //调用Consumer组件,包裹住元素
        <Themes.Consumer>
             // 以参数的方式传递theme参数和changeTheme方法
            {({theme,changeTheme})=>(
                       // 样式就可以用theme的样式设置
                <View style={{backgroundColor:theme.bgColor,width:'100%',height: '100%'}}>
                    <Statusbar bgColor={theme.bgColor}/>
                    <View style={[styles.meEntry,{backgroundColor: theme.viewColor}]}>
                        <TouchableOpacity 
                        activeOpacity={0.5}
                        underlayColor="#ffffff"
                        onPress={changeTheme}>  //点击切换主题事件,调用changeTheme方法
                            <View style={[styles.meEntryBox,styles.meEnterLine]}>
                                <Text style={[styles.meEntryTitle,{color: theme.fontColor}]}>主题</Text>
                                <Text><Icon name="angle-right" size={20} color="#ccc" /></Text>
                            </View>
                        </TouchableOpacity>
                    </View>
                </View>
            )}
        </Themes.Consumer>
    )
}

如果有其他组件也需要配置主题样式,就按照上面代码中的方式操作

到此就搞定了

本文到此结束。

反馈信息

INFO

邮箱: open_teams@163.com