用 react-native
开发一个如下图所示的可滑动翻页的菜单集合:
export const menus = [
{
name: '用户管理', // 菜单名称
icon: assets.service_user, // 菜单图标
routerName: 'userManage', // 跳转页面name
},
{
name: '企业信息',
icon: assets.service_company,
routerName: 'company'
},
{
name: '产品信息',
icon: assets.service_product,
routerName: 'productInfo',
companyType: '13',
},
{
name: '财务中心',
icon: assets.service_finance,
routerName: 'financeCenter'
},
...
{
name: '更多',
icon: assets.more,
routerName: 'more'
}
]
我们用 ScrollView
横向滚动来实现:
<View>
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
onScroll={onScroll}>
{menuList.map((item, index) => {
return (
<Touchable
key={index}
onPress={() => {
_pressService(item, index);
}}>
<View style={styles.serviceItem}>
<Image source={item.icon} style={styles.serviceIcon} />
<Text style={styles.serviceName}>{item.name}</PFText>
</View>
</Touchable>
);
})}
</ScrollView>
</View>
这样呢我们的菜单全部拍成一排,并不能像图片那样分页处理,所以我们需要将我们的菜单数组做一点处理,首先我们将菜单数组按每页固定的数分布,比如按照图片中所示,按自己的需求分为每页10个,每页两行,多余的菜单滑动到下一页中,当然,如果你的菜单永远不会变,不会因为登录账号的不同让每个用户看到的菜单不相同的话,可以直接将你的菜单配置改成二维数组的格式:
const menuList = [
[
{
name: '企业信息',
icon: assets.service_company,
routerName: 'company'
},
{
name: '企业信息',
icon: assets.service_company,
routerName: 'company'
}
...
],
[
{
name: '企业信息',
icon: assets.service_company,
routerName: 'company'
},
]
]
return (
<View>
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
onScroll={onScroll}>
{menuList.map((item, index) => {
return (
<View key={item.name}>
{
item.map((_item, _index) => (
<Touchable
key={_index}
onPress={() => {
_pressService(_item, _index);
}}>
<View style={styles.serviceItem}>
<Image source={_item.uri} style={styles.serviceIcon} />
<Text style={styles.serviceName}>{_item.name}</PFText>
</View>
</Touchable>
))
}
</View>
);
})}
</ScrollView>
</View>
)
但是实际中我们的菜单一般都会涉及到权限,直接写成二位数修改删除一个菜单就需要全部修改整个二维数组,所以配置菜单我们只需要定义一个数组就可以了,思路就是先把我们的数组按每页几个来分我们的数组,一维数组个数作为渲染页数,二维数组的内容来渲染菜单,我们可以先处理我们的菜单数组,筛选我们有权限的菜单,再改造成二维数组,渲染到我们的组件中:
import React, { useState, useEffect } from 'react';
import {
View,
ScrollView,
Text,
Touchable,
} from 'react-native';
import menus from './menu.js';
import { chunk } from 'lodash';
const MenuView = props => {
// 活跃的指示器页数
const [activePage, setActivePage] = useState(0);
// 菜单列表
const [menuList, setMenuList] = useState(chunk(menus, 10));
// 处理我们的数组
useEffect(_ => {
...
} ,[])
// 当一帧滚动结束的时候调用
const onScroll = e => {
let currPage = Math.floor(e.nativeEvent.contentOffset.x / ...);
activePage !== currentPage && setActivePage(currentPage);
}
// 点击菜单跳转对应的路由页面
const _pressService = item => props.navigation.push(item.routerName);
// 渲染菜单页
const _renderScrollItems = item => {
return item.map((_item, _index) => {
return (
<Touchable
key={_index}
onPress={() => {
_pressService(_item, _index);
}}>
<View style={styles.serviceItem}>
<Image source={_item.uri} style={styles.serviceIcon} />
<Text style={styles.serviceName}>{_item.name}</PFText>
</View>
</Touchable>
);
});
}
// 渲染指示器
const _renderIndicator = () => {
let indicatorArr = [];
for (let i = 0; i < menuList.length; i++) {
let backgroundColor = i === activePage ? '#ffffff' : '#5B55A0';
indicatorArr.push(
<View key={i} style={[styles.indicator, {backgroundColor}]} />,
);
}
return indicatorArr;
};
return (
<View style={styles.service}>
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
onScroll={onScroll}>
{menuList.map((item, index) => {
return (
<View key={index} style={styles.servicePage}>
{_renderScrollItems(item)}
</View>
);
})}
</ScrollView>
{/*指示器*/}
<View style={styles.indicatorStyle}>{_renderIndicator()}</View>
</View>
);
}
当然这样也只是简单的分页滑动按钮,实际业务中菜单还可能支持用户使用习惯增加自定义的功能,比如拖拽排序等功能。