rax自定义微信小程序导航栏 |
您所在的位置:网站首页 › 导航栏代码横版 › rax自定义微信小程序导航栏 |
一、导航栏样式
背景: 接到一个需求,需要自定义微信导航栏,并且展示如上图存在各种样式; 难点: 兼容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 |