rax自定义微信小程序导航栏

您所在的位置:网站首页 导航栏代码横版 rax自定义微信小程序导航栏

rax自定义微信小程序导航栏

2023-03-23 22:41| 来源: 网络整理| 查看: 265

一、导航栏样式

背景: 接到一个需求,需要自定义微信导航栏,并且展示如上图存在各种样式;

难点: 兼容IOS刘海屏,IOS药丸屏,安卓无框屏、H5正常屏幕、小程序退出后台不随页面滚动;

navigationBar相信大家都不陌生把?今天我们就来说说自定义navigationBar,把它改变成我们想要的样子。

二、开发思路

隐藏原生样式

获取胶囊按钮、状态栏相关数据以供后续计算

根据不同机型计算出该机型的导航栏高度,进行适配

编写新的导航栏

引用到页面

(1)隐藏原生的navigationBar

window全局配置里有个参数:navigationStyle(导航栏样式),default=默认样式,custom=自定义样式。

"window": { "navigationStyle": "custom" }

让我们看看隐藏后的效果

可以看到原生的navigationBar已经消失了,剩下孤零零的胶囊按钮,胶囊按钮是无法隐藏的。

获取胶囊按钮的布局位置信息

const menuButtonInfo = wx.getMenuButtonBoundingClientRect();

(2)获取系统信息

用wx.getSystemInfoSync() 【官方文档】 获取系统信息,里面有个参数:statusBarHeight(状态栏高度),是我们后面计算整个导航栏的高度需要用到的。

const systemInfo = wx.getSystemInfoSync();

我们先要知道导航栏高度是怎么组成的

计算公式: 导航栏高度 = 状态栏到胶囊的间距(胶囊距上距离-状态栏高度) * 2 + 胶囊高度 + 状态栏高度 。 三、代码实践

mock数据

{ "contType": "textAndIcons", "title": "导航标题", "alignment": "left", "pic": "https://gw.baidu.com/i4/O1CN01RhTdXv1Y8SWGy1Phi_!!6000000003014-2-tps-120-108.png" } import { createElement, useEffect as UseEffect, useState as UseState } from 'rax'; import View from 'rax-view'; import Navigation from './Navigation/index'; interface NavInfo { contType?: string; title: string; alignment?: string; pic?: string; } const Alltype = [ { type: 'separateTitle', id: 1, alignment: 'left', }, { type: 'separateTitle', id: 2, alignment: 'center', }, { type: 'individualIcon', id: 3, alignment: 'center', }, { type: 'individualIcon', id: 4, alignment: 'left', }, { type: 'textAndIcons', id: 5, alignment: 'center', }, { type: 'textAndIcons', id: 6, alignment: 'left', }, ]; // mock的数据传递给props 进行验证 export default function Mod(props) { const [type, setType] = UseState(0); const [navInfo, setNavInfo] = UseState(null); UseEffect(() => { getType(props || {}); }, []); const getType = ({ contType, title, alignment, pic }) => { Alltype.forEach((v) => { if (contType === v.type && alignment === v.alignment) { setType(v.id); setNavInfo({ title, pic, }); } }); }; return ( ); }

Navigation文件夹

index.tsx

import { createElement, useMemo } from 'rax'; import View from 'rax-view'; import { getSystemInfo } from '../../wxUtils'; import Picture from 'rax-image'; import styles from './index.module.less'; interface INavigationBarProps { extClass?: string; backgroundColorTop?: string; background?: string; color?: string; back?: boolean; home?: boolean; iconTheme?: string; title?: string; renderLeft?: string; renderRight?: string; pic?: string; type?: string | number; } interface ICapsulePosition { bottom: number; height: number; left: number; right: number; top: number; width: number; } interface IStyle { navigationbarinnerStyle?: string; navBarLeft?: string; navBarHeight?: number; capsulePosition?: ICapsulePosition; navBarExtendHeight?: number; ios?: boolean; rightDistance?: number; } function setStyle(systemInfo, props): IStyle | null { if (systemInfo.ios == null) { return null; } const { statusBarHeight, navBarHeight, capsulePosition, navBarExtendHeight, ios, windowWidth, } = systemInfo; const { back, home, title, color } = props; const rightDistance = windowWidth - capsulePosition.right; // 胶囊按钮右侧到屏幕右侧的边距 const leftWidth = windowWidth - capsulePosition.left; // 胶囊按钮左侧到屏幕右侧的边距 const navigationbarinnerStyle = [ `color:${color}`, // `background:${background}`, `height:${navBarHeight + navBarExtendHeight}px`, // `padding-top:${statusBarHeight + 5}px`, `padding-top:${statusBarHeight}px`, `padding-right:${leftWidth}px`, `padding-bottom:${navBarExtendHeight}px`, ].join(';'); let navBarLeft = ''; if ((back && !home) || (!back && home)) { navBarLeft = [ `width:${capsulePosition.width}px`, `height:${capsulePosition.height}px`, 'margin-left:0px', `margin-right:${rightDistance}px`, ].join(';'); } else if ((back && home) || title) { navBarLeft = [ `width:${capsulePosition.width}px`, `height:${capsulePosition.height}px`, `margin-left:${rightDistance}px`, ].join(';'); } else { navBarLeft = ['width:auto', 'margin-left:0px'].join(';'); } return { navigationbarinnerStyle, navBarLeft, navBarHeight, capsulePosition, navBarExtendHeight, ios, rightDistance, }; } function NavigationBar(this: any, props: INavigationBarProps): JSX.Element | null { const { backgroundColorTop, background, back, home, title, pic, type, } = props; const configStyle = useMemo(() => { const isWX = typeof wx !== 'undefined' && wx !== null && (typeof wx?.request !== 'undefined' || typeof wx?.miniProgram !== 'undefined'); const systemInfo = (isWX && getSystemInfo()) || { windowWidth: 0, capsulePosition: { left: 0 }, ios: false, navBarLeft: 0, navBarHeight: 80, navBarExtendHeight: 0, }; return setStyle(systemInfo, props); }, []); return configStyle ? ( { paddingTop: `${configStyle.navBarHeight + configStyle.navBarExtendHeight}px` }} /> { paddingLeft: `${configStyle.navBarLeft}px` }}> {title} { paddingLeft: `${configStyle.rightDistance}px` }}> { paddingLeft: `${configStyle.navBarLeft}px` }}> { paddingLeft: `${configStyle.rightDistance}px` }} > {title} {type === 6 && ( { uri: pic, }} resizeMode="contain" className={styles.onlyImageWrap} /> {title} )} ) : null; } export default NavigationBar;

index.module.less

.ios { /* prettier-ignore */ --height: 44PX; /* 4*2+32 */ /* prettier-ignore */ --right: 97PX; /* 10+87 */ /* prettier-ignore */ --navBarExtendHeight: 4PX; box-sizing: border-box; margin-bottom: 48Px; background-color: #fff; } .android { /* prettier-ignore */ --height: 48PX; /* 8*2+32 */ /* prettier-ignore */ --right: 96PX; /* 10+87 */ /* prettier-ignore */ --navBarExtendHeight: 4PX; box-sizing: border-box; margin-bottom: 52Px; background-color: #fff; } .onlyImageWrap { height: 54Px; width: 52PX; object-fit: contain; } .onlyImageWrapRandom { height: 54Px; object-fit: contain; } .devtools { /* prettier-ignore */ --height: 42PX; /* 5*2+32 */ /* prettier-ignore */ --right: 88PX; /* 10+87 */ /* prettier-ignore */ --navBarExtendHeight: 4PX; box-sizing: border-box; } .tpNavBarInner { position: fixed; top: 0; left: 0; z-index: 5001; /* prettier-ignore */ height: var(--navBarHeight); display: flex; align-items: center; padding-right: var(--right); width: 100%; /* prettier-ignore */ padding-top: 20PX; /* prettier-ignore */ padding-bottom: 4PX; flex-direction: unset; .placeholder { position: absolute; top: 0; left: 0; width: 100%; } } .textAndIcon { display: flex; flex-direction: row; } .tpNavBarLeft { position: relative; width: var(--right); /* prettier-ignore */ height: 32PX; line-height: 32PX; /* padding-left: 10PX; */ /* prettier-ignore */ margin-left: 10PX; display: flex; align-items: center; } .tpNavBarLeftX { position: relative; // width: var(--right); /* prettier-ignore */ height: 32PX; line-height: 32PX; /* padding-left: 10PX; */ /* prettier-ignore */ margin-left: 10PX; display: flex; align-items: center; flex-direction: row; } .tpNavBarButtons { height: 100%; width: 100%; display: flex; align-items: center; /* prettier-ignore */ border-radius: 16PX; border: 1px solid rgba(204, 204, 204, 0.6); position: relative; flex-direction: row; } .tpNavBarButtons.android { border: 1px solid rgba(234, 234, 234, 0.6); } .tpNavBarButtons::after { position: absolute; content: ''; width: 1px; /* prettier-ignore */ height: 18.4PX; background: rgba(204, 204, 204, 0.6); left: 50%; top: 50%; transform: translate(-50%, -50%); } .tpNavBarButtons.android::after { background: rgba(234, 234, 234, 0.6); } .tpNavBarButton { width: 50%; height: 100%; display: flex; /* prettier-ignore */ font-size: 17PX; background-repeat: no-repeat; background-position: center center; background-size: 1em 2em; } .tpNavBarButtonM { height: 100%; display: flex; /* prettier-ignore */ font-size: 17PX; background-repeat: no-repeat; background-position: center center; background-size: 1em 2em; } .tpNavBarButtonX { // width: 50%; height: 100%; display: flex; /* prettier-ignore */ font-size: 17PX; background-repeat: no-repeat; background-position: center center; background-size: 1em 2em; margin-left: 10PX; } .tpNavBarInner .tpNavBarLeft .tpNavBarBtnGoback:active, .tpNavBarInner .tpNavBarLeft .tpNavBarBtnGohome:active { opacity: 0.5; } .tpNavBarInner .tpNavBarCenter { /* prettier-ignore */ font-size: 17PX; /* prettier-ignore */ line-height: 17PX; text-align: center; position: relative; flex: 1; display: -webkit-box; display: -webkit-flex; display: flex; align-items: center; justify-content: center; /* prettier-ignore */ padding-left: 10PX; text { margin-top: -2px; } } .tpNavBarInner .tpNavBarRight { /* prettier-ignore */ margin-right: 10PX; } .tpNavBarPlaceholder { height: var(--navBarHeight); background: #f8f8f8; position: relative; z-index: 50; visibility: hidden; } .tpNavBarSearch { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; width: 100%; /* prettier-ignore */ height: 32PX; /* prettier-ignore */ border-radius: 16PX; position: relative; background: #f6f6f6; } .tpNavBarSearchInput { height: 100%; display: flex; align-items: center; color: #999; /* prettier-ignore */ font-size: 15PX; /* prettier-ignore */ line-height: 15PX; } .tpNavBarInner .tpNavBarLeft .tpNavBarBtnGohome { background-size: 20PX 20PX; } .tpNavBarInner .tpNavBarLeft .tpNavBarBtnGohome.white { background-size: 20PX 20PX; } .onePx { position: absolute; bottom: 0; left: 0; right: 0; height: 1px; border: none; border-bottom: 1px solid #ECEDEE; transform: scaleY(0.5); transform-origin: 0 0; }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3