10-4 类别页面的布局和样式

201 阅读2分钟

在本节中,我们将完成类别页面的布局和样式设计。以下是详细的实现步骤:

一、创建类别页面

1. 创建文件夹和文件

pages 文件夹下创建 Category 文件夹,并在其中创建 index.tsx 文件。

2. 添加到导航器

navigator/index.tsx 中导入 Category 页面,并添加到导航器中:

import Category from '@/pages/Category';

export type RootStackParamList = {
  BottomTabs: {
    screen?: string;
  };
  Category: undefined;
};

<RootStack.Screen
  name="Category"
  component={Category}
  options={{
    headerTitle: '分类',
  }}
/>

3. 添加分类按钮事件

pages/views/TopTabBarWrapper.tsx 中,给分类按钮添加跳转事件:

goCategory = () => {
  const { navigation } = this.props;
  navigation.navigate('Category');
};

<Touchable onPress={this.goCategory} style={styles.sortBtn}>
  <Text style={textStyle}>分类</Text>
</Touchable>

二、实现类别页面布局

1. 创建 Category 页面

pages/Category/index.tsx 中实现类别页面的布局:

import React, { Component } from 'react';
import { View, Text, StyleSheet, ScrollView } from 'react-native';
import _ from 'lodash';
import Touchable from '@/components/Touchable';
import { connect, ConnectedProps } from 'react-redux';
import { viewportWidth } from '@/utils/index';
import { RootState } from '../models';
import { ICategory } from '@/models/category';
import { RootStackNavigation } from '@/navigator/index';

const marginHorizontal = 5;
const itemWidth = (viewportWidth - marginHorizontal * 2) / 4;

const mapStateToProps = ({ category }: RootState) => ({
  categorys: category.categorys,
  myCategorys: category.myCategorys,
});

const connector = connect(mapStateToProps);

type ModelState = ConnectedProps<typeof connector>;

interface IProps extends ModelState {
  navigation: RootStackNavigation;
}

interface IState {
  myCategorys: ICategory[];
}

class Category extends Component<IProps, IState> {
  state = {
    myCategorys: this.props.myCategorys,
  };

  renderItem = (item: ICategory, selected: boolean) => {
    return (
      <View key={item.id} style={styles.item}>
        <Text>{item.name}</Text>
      </View>
    );
  };

  render() {
    const { myCategorys } = this.state;
    const { categorys } = this.props;
    const classifyGroup = _.groupBy(categorys, (item: ICategory) => item.classify);

    return (
      <ScrollView style={styles.container}>
        <View>
          <Text style={styles.classifyName}>
            我的分类<Text style={styles.tips}>长按可拖动顺序</Text>
          </Text>
          <View style={styles.classifyView}>
            {myCategorys.map((item) => this.renderItem(item, true))}
          </View>
        </View>
        {Object.keys(classifyGroup).map((classify) => (
          <View key={classify}>
            <Text style={styles.classifyName}>{classify}</Text>
            <View style={styles.classifyView}>
              {classifyGroup[classify].map((item) => this.renderItem(item, false))}
            </View>
          </View>
        ))}
      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f3f6f6',
  },
  classifyName: {
    fontSize: 16,
    marginBottom: 8,
    marginTop: 14,
  },
  classifyView: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    padding: 5,
  },
  item: {
    width: itemWidth,
    marginHorizontal: marginHorizontal,
    backgroundColor: '#fff',
    borderRadius: 3,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 10,
  },
  tips: {
    color: '#666',
  },
});

export default connector(Category);

2. 创建 Item 组件

pages/Category/Item.tsx 中创建 Item 组件:

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { ICategory } from '@/models/category';
import { viewportWidth } from '@/utils/index';

export const parentWidth = viewportWidth - 10;
export const itemWidth = parentWidth / 4;
export const itemHeight = 48;
export const margin = 5;

interface IProps {
  data: ICategory;
}

class Item extends React.Component<IProps> {
  render() {
    const { data } = this.props;

    return (
      <View style={styles.itemWrapper}>
        <View style={styles.item}>
          <Text>{data.name}</Text>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  itemWrapper: {
    width: itemWidth,
    height: itemHeight,
  },
  item: {
    flex: 1,
    margin: margin,
    backgroundColor: '#fff',
    borderRadius: 3,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default Item;

三、总结

在本节中,我们完成了类别页面的布局和样式设计。通过使用 ScrollViewTouchable 组件,我们实现了分类列表的展示和交互。下一节,我们将学习如何在标题栏添加右上角按钮,并实现编辑状态的切换。