首页 > 编程语言 >微信小程序开发自定义tabbar

微信小程序开发自定义tabbar

时间:2023-04-19 15:40:51浏览次数:45  
标签:index center 自定义 flex 微信 100% 程序开发 height width

问题背景

自定义 tabBar 可以让开发者更加灵活地设置 tabBar 样式,以满足更多个性化的场景。本文将介绍微信小程序开发中如何自定义tabbar。

问题分析

微信小程序中,自定义tabbar的流程如下:

  1. 配置信息 在 app.json 中的 tabBar 项指定 custom 字段,同时其余 tabBar 相关配置也补充完整。 所有 tab 页的 json 里需声明 usingComponents 项,也可以在 app.json 全局开启。demo代码如下:
{
  "tabBar": {
    "custom": true,
    "color": "#000000",
    "selectedColor": "#000000",
    "backgroundColor": "#000000",
    "list": [{
      "pagePath": "page/component/index",
      "text": "组件"
    }, {
      "pagePath": "page/API/index",
      "text": "接口"
    }]
  },
  "usingComponents": {}
}
  1. 添加 tabBar 代码文件,在代码根目录下新建custom-tab-bar目录,添加入口文件:
custom-tab-bar/index.js
custom-tab-bar/index.json
custom-tab-bar/index.wxml
custom-tab-bar/index.wxss
  1. 编写 tabBar 代码

问题解决

话不多说,直接上代码。 (1)项目app.json文件,代码如下:

{
  "pages": [
    "pages/index/index",
    "pages/login/index",
    "pages/logs/logs",
    "pages/lll"
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle": "black"
  },
  "tabBar": {
    "custom": true,
    "color": "#626262",
    "selectedColor": "#062da9",
    "borderStyle": "black",
    "list": [
      {
        "pagePath": "pages/index/index",
        "iconPath": "static/img/icon-admin.png",
        "selectedIconPath": "static/img/icon-admin.png",
        "text": "首页"
      },
      {
        "pagePath": "pages/login/index",
        "iconPath": "static/img/icon-admin.png",
        "selectedIconPath": "static/img/icon-admin.png",
        "text": "企业诉求"
      }
    ]
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json",
  "usingComponents": {}
}

(2)项目根目录下新建的custom-tab-bar文件夹中,文件内容如下。 index.js文件,代码如下:

let app = getApp();

Component({
  data: {
    selected: 0,
    color: "#626262",
    selectedColor: "#062da9",
    list: [{
      "pagePath": "/pages/index/index",
      "iconPath": "/static/img/icon-admin.png",
      "selectedIconPath": "/static/img/icon-admin.png",
      "text": "首页"
    }, {
      "pagePath": "/pages/login/index",
      "iconPath": "/static/img/icon-admin.png",
      "selectedIconPath": "/static/img/icon-admin.png",
      "text": "分类"
    },{
      "pagePath": "/pages/my/my",
      "iconPath": "/static/img/icon-admin.png",
      "selectedIconPath": "/static/img/icon-admin.png",
      "text": "我的"
    }]
  },
  ready() {
  },
  attached() {
  },
  methods: {
    switchTab(e) {
      const data = e.currentTarget.dataset
      const url = data.path
      wx.switchTab({url})
      this.setData({
        selected: data.index
      })
    }
  }
})

index.json文件,代码如下:

{
  "component": true
}

index.wxml文件,代码如下:

<view class="navigation-container" style="{{'height: ' + navigationBarAndStatusBarHeight}}">
  <!--空白来占位状态栏-->
  <view style="{{'height: ' + statusBarHeight}}"></view>
  <!--自定义导航栏-->
  <view class="navigation-bar" style="{{'height:' + navigationBarHeight}}">
    <view class="navigation-title" style="{{'line-height: ' + navigationBarHeight}}">测试首页</view>
  </view>
</view>
<!--空白占位fixed空出的位置-->
<view style="{{'height: ' + navigationBarAndStatusBarHeight}}; background: #ffffff"></view>

<scroll-view scroll-y="{{true}}"  class="pageWrapper" style="height:calc(100% - {{navigationBarAndStatusBarHeight }} - {{tabbarAndBottomSafeHeight + 'px'}});">
  <view class="index-bg">
    <image src="../../static/img/bg_guanggu.png" style="width:100%;height:100%"></image>
  </view>

  <swiper class="swiper-block"  circular="true" duration="1000" autoplay="true" interval="3000" previous-margin="60rpx" next-margin="60rpx" bindchange="swiperChange" current="{{adIndexIndex}}">
    <block wx:for="{{homeBannerList}}"  wx:key="id" wx:index="{{index}}">
      <swiper-item class="swiper-item">
        <view class="slide-image {{adIndexIndex == index ? 'active' : ''}}" style="position:relative">
          <image mode="scaleToFill" style="width:100%;height:100%" src="{{item}}" />
          <!-- <view class="bannerdesc">{{item.imgName}}</view> -->
        </view>
      </swiper-item>
    </block>
  </swiper>
  <view class="swiper-nav">
    <view wx:for="{{homeBannerList}}" wx:key="id" wx:index="{{index}}" class='navclass' bindtap="navtap" data-index="{{index}}">
      <image style="width:90%;height:100%" wx:if="{{index==adIndexIndex}}" src="../../static/img/nav2.png"></image>
      <image style="width:46%;height:100%" wx:else src="../../static/img/nav.png"></image>
    </view>
  </view>

  <view class="firstTitle">
    中心简介
  </view>
  <view style="margin-left: 30rpx; width:690rpx;height:140rpx" bindtap="goServiceCenter">
    <image src="../../static/img/banner.png" mode="scaleToFill" style="width:100%;height:100%"></image>
  </view>

  <view class="firstTitle">
    公告资讯
  </view>
  <view class='cont-title flexbetween'>
    <scroll-view style="width:70%" scroll-x="true">
      <view class='menutabbox1'>
        <block wx:for="{{categorys}}" wx:for-item="item" wx:key="index">
          <view class="menuitem {{item.active? 'itemactive': ''}}" bind:tap="changetype" data-id="{{item.id}}" data-index="{{index}}">
            <text class="label-title">{{item.name}}</text>
            <!-- <view></view> -->
          </view>
        </block>
      </view>
    </scroll-view>
    <view style="margin:0 10rpx" style="color:#000000">|</view>
    <view style="position:relative;">
      <text bindtap='getAllNotice' style="color:#999999">查看全部</text>
    </view>
  </view>
  <swiper snap-to-edge="true" previous-margin="20rpx" next-margin="20rpx" style="margin-left: 15rpx; width:720rpx;height:450rpx" current="{{publishCurr}}" wx:if="{{publishInfoList.length > 0}}">
    <swiper-item class="" wx:for="{{ publishInfoList }}" wx:for-item="item" wx:key="index">
      <view style="height:90%;box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);margin:20rpx 20rpx;">
        <view class='infobox'>
          <view style="width:100%;height: 50%;border-bottom: 1rpx solid #f0f0f0;" class="flexbetween" data-title="资讯详情" data-id="{{item.id}}" bindtap='goDetail'>
            <view style='width:calc(100% - 236rpx);'>
              <view class='info-title'>{{item.name}}</view>
              <view class='itemflex'>
                <image src="../../static/img/icon-admin.png" mode="widthFix" class='icon1'></image>
                <text class='info-text'>{{item.lat}}</text>
                <image src="../../static/img/icon-eye.png" mode="widthFix" class='icon2'></image>
                <text class='info-text'>{{item.lon}}</text>
              </view>
            </view>
            <view class="info-img" style="display:flex; align-items:center;overflow-y:hidden;background-color:#f5f5f5;border-radius: 10rpx">
              <image wx:if="{{item.adm1}}" style="width:100%;height:100%" src="../../static/img/icon-admin.png" mode="scaleToFill"></image>
              <image wx:else style="width:100%;height:100%" src="../../static/img/default_pic.jpg" mode="scaleToFill"></image>
            </view>
          </view>

          <view wx:if="{{item.length > 1}}" style="width:100%;height: 50%;" class="flexbetween" data-title="资讯详情" data-id="{{item.id}}" bindtap='goDetail'>
            <view style='width:calc(100% - 236rpx);'>
              <view class='info-title'>{{item.name}}</view>
              <view class='itemflex'>
                <image src="../../static/img/icon-admin.png" mode="widthFix" class='icon1'></image>
                <text class='info-text'>{{item.lat}}</text>
                <image src="../../static/img/icon-eye.png" mode="widthFix" class='icon2'></image>
                <text class='info-text'>{{item.lon}}</text>
              </view>
            </view>
            <view class="info-img" style="display:flex; align-items:center;overflow-y:hidden;background-color:#f5f5f5;border-radius: 10rpx">
              <image wx:if="{{item.name}}" style="width:100%;height:100%" src="../../static/img/icon-eye.png" mode="scaleToFill"></image>
              <image wx:else style="width:100%;height:100%" src="../../static/img/default_pic.jpg" mode="scaleToFill"></image>
            </view>
          </view>
        </view>
      </view>
    </swiper-item>
  </swiper>
  <view style="width:95%;height:200rpx;display: flex;justify-content: center;font-size: 48rpx;line-height: 200rpx;" wx:if="{{publishInfoList.length == 0}}">
    暂无任何资讯
  </view>
  <view class="firstTitle">
    常见办事入口
  </view>
  <scroll-view scroll-x="true" style="margin-left: 20rpx; width: 710rpx;background-color: #f7f7f7;">
    <view class="menutabbox1 " style="height: 200rpx;padding:0;">
      <view class="legalinfoitem" style="padding: 0 40rpx;" wx:for="{{publishInfoList}}"  wx:key="index" bindtap="goMini" data-entertype="{{item.adm2}}" data-content="{{item.adm1}}">
        <image src="../../static/img/icon-eye.png" style="width:99rpx;height:99rpx;border-radius: 50%;" mode="scaleToFill"></image>
        <text style="color: #333333;font-size: 22rpx; text-align: center;">{{item.name}}</text>
      </view>
    </view>
  </scroll-view>

  <view class="firstTitle">
    建议意见
  </view>
  <view class="zxfw" style="margin-bottom:50rpx">
    <view class="zxfw1" bindtap="goComplain" data-type="1">
      <image src="../../static/img/icon-admin.png" style="width:100%;height:100%"></image>
    </view>
    <view class="zxfw1" bindtap="goComplain" data-type="2">
      <image src="../../static/img/icon-admin.png" style="width:100%;height:100%"></image>
    </view>
  </view>
  <view class="contactus" bindtap="goContactUs" style="bottom:{{tabbarAndBottomSafeHeight + 15}}px">
    <image src="../../static/img/icon-eye.png" style="width:100%;height:100%"></image>
  </view>
</scroll-view>

index.wxss文件,代码如下:

.swiper-block{
  height: 400rpx;
  width: 100%;
  margin-top: 50rpx;
  z-index: 10;
}
.swiper-item{
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  overflow:unset;
}
.slide-image{
  height:380rpx;
  width: 90%;
  border-radius: 9rpx;
  /* box-shadow: 0px 0px 30rpx rgba(0, 0,0,.2);  */
  margin: 0rpx 30rpx;
  z-index: 1;  
}
.active{
  transform: scale(1.14);
  transition:all .2s ease-in 0s;
  z-index: 20; 
}

.navclass{
  width: 40rpx;
  height: 12rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 30rpx;
}

/* 导航 */
.navigation-container {
  position: fixed;
  width: 100%;
  z-index: 99;
  top: 0;
  left: 0;
  background-color: #ffffff;
}

.navigation-bar {
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.navigation-title {
  position: absolute;
  left: 104px;
  right: 104px;
  text-align: center;
  font-size: 16px;
  font-weight: bold;
  color: #000000;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.index-bg{
  width: 100%;
  height: 450rpx;
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
}

.pageWrapper{
  height: 100%;
  width: 100%;
  /* display: flex;
  flex-direction: column;
  align-items: center; */
  overflow-x: hidden;
}

.swiper-nav{
  width: 100%;
    height: 12rpx;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 10;
}

.firstTitle{
  width: 95%;
    position: relative;
    margin: 30rpx 0;
    padding-left: 60rpx;
    font-weight: bold;
}
.firstTitle::before{
  position:absolute;
  content: " ";
  height: 100%;
  width: 10rpx;
  background-color: #062da9;
  left: 5%;
}

.cont-title {
  width: 100%;
  height: 90rpx;
  padding: 0 40rpx;
  border-bottom: solid 2rpx #f0f0f0;
  color: #0d91ff;
  font-size: 28rpx;
  line-height: 80rpx;
  box-sizing: border-box;
}
.cont-title text {
  line-height: 80rpx;
}

.flexbetween {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.menutabbox1 {
  padding: 0 30rpx;
  box-sizing: border-box;
  display: flex;
  width: 100%;
  color: #666666;
}

.menuitem {
  width: auto;
  height: 100%;
  background: #fff;
}

.label-title {
  display: inline-block;
  padding: 0 20rpx;
  white-space: nowrap;
  font-size: 28rpx;
}

.itemactive {
  color: #062da9;
  font-weight: 600;
}

.infobox:first-child {
  border-top: none;
}

.infobox {
  width: calc(100% - 40rpx);
  height: 100%;
  margin-left: 40rpx;
  padding: 20rpx 40rpx 20rpx 0;
  border-bottom: solid 2rpx #f0f0f0;
  box-sizing: border-box;
  position: relative;
}

.info-title {
  font-family: SourceHanSansCN-Medium;
	font-size: 30rpx;
	font-weight: bold;
	font-stretch: normal;
	line-height: 45rpx;
	letter-spacing: 0rpx;
	color: #000000;
  overflow: hidden;
  white-space: nowrap; /*不换行  */
  text-overflow: ellipsis;
}

.itemflex {
  display: flex;
  align-items: center;
  margin-top: 28rpx;
}

.info-text {
  color: #aebdd8;
  font-size: 20rpx;
  margin-left: 5rpx;
}

.icon1 {
  width: 17rpx;
  height: 21rpx;
}

.icon2 {
  width: 24rpx;
  height: 15rpx;
  margin-left: 20rpx;
}

.info-img {
  width: 236rpx;
  height: 133rpx;
}

.menutabbox1 {
  padding: 0 30rpx;
  box-sizing: border-box;
  display: flex;
  width: 100%;
  color: #666666;
}

.legalinfoitem{
  display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
}

.zxfw{
  margin-left: 30rpx;
  width: 690rpx;
  height: 350rpx;
  display: flex;
  align-items: center;
  justify-content: space-around;
}
.zxfw1{
  width: 40%;
  height: 280rpx;
}

.contactus{
  height: 150rpx;
  width: 145rpx;
  position: fixed;
  right: 20rpx;
}

运行结果如下: image.png

问题总结

本文初步介绍了微信小程序开发中如何自定义tabbar,有兴趣的同学可以进一步深入研究。

标签:index,center,自定义,flex,微信,100%,程序开发,height,width
From: https://blog.51cto.com/baorant24/6206364

相关文章

  • 物联网多协议、多场景自定义测试|XMeter Cloud 更新
    近日,全球首个物联网MQTT负载测试云服务XMeterCloud推出了自定义场景测试功能。该功能将满足用户自主定义测试场景和测试更广泛协议的需求,实现对除MQTT以外的TCP、WebSocket、HTTP等其他网络协议的测试,帮助用户构建更复杂的测试场景,提高测试效率和测试覆盖率。了解详情:XMet......
  • 自定义Mybatis-plus插件(限制最大查询数量)
    自定义Mybatis-plus插件(限制最大查询数量)需求背景​ 一次查询如果结果返回太多(1万或更多),往往会导致系统性能下降,有时更会内存不足,影响系统稳定性,故需要做限制。解决思路1.经分析最后决定,应限制一次查询返回的最大结果数量不应该超出1万,对于一次返回结果大于限制的时候应该......
  • vue3微信公众号商城项目实战系列(8)商品展示页面
    本篇实现在首页展示商品功能,表结构如下:表名字段功能goodsgoods_id(int)商品编号goods_name(varchar)商品名称photo(varchar)商品图片price(decimal)价格商品表页面呈现效果如下: 第1步:在api.js中加入获取首页商品信息和加购物车的接口方法,如下......
  • 中交二公局的数字化转型之路:微信扫一扫即可轻松巡检
    中交二公局主要从事路桥施工等业务,具有公路工程施工总承包特级资质,是一家集铁路、隧道、机场、水工、市政、工程施工设计、咨询、监理等为一体的大型国有施工企业。自成立以来,中交二公局在工程施工领域积累了丰富的经验,业务范围涵盖全国各地。中交二公局的每个项目都需要用到大量的......
  • 【web 开发基础】PHP 自定义函数之函数的返回值-PHP 快速入门 (27)
    前言在定义函数时,函数名后面括号中的参数列表是用户在调用函数时用来将数据传递到函数内部的接口,而函数的返回值则将函数执行后的结果返回给调用者。如果函数没有返回值,就只能算一个执行过程。只依靠函数做一些事情还不够,有时更需要在程序脚本中使用函数执行后的结果。由于变量的作......
  • uniapp兼容微信小程序和支付宝小程序遇见的坑
    1、获取当前帐号信息getAccountInfoSync兼容;my.getOpenUserInfo 无效的授权关系微信小程序:wx.getAccountInfoSync()支付宝小程序:<buttonclass="popup-btn"@click="openAuth"type="primary"size="mini">获取</button>my.getOpenUserI......
  • CentOS7添加自定义脚本服务
    在CentOS7下,已经不再使用chkconfig命令管理系统开机自启动服务和条件自定义脚本服务了,而是使用管理unit的方式来控制开机自启动服务和添加自定义脚本服务。在/usr/lib/systemd/system目录下包含了各种unit文件,有service后缀的服务unit,有target后缀的开机级别unit等。如果想把自定......
  • 6.自定义注解与设计模式
    自定义注解与设计模式课程目标熟悉注解底层实现原理完成ORM框架底层原理常用设计模式单例、工厂、代理一.自定义注解1.1什么是注解?Jdk1.5新增新技术,注解。很多框架为了简化代码,都会提供有些注解。可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在......
  • 11.Session与Cookie(自定义Session)
    Session与Cookie(自定义Session)课程目标:#熟悉Cookie、Session底层实现原理、自定义缓存、自定义Token、表单重复提交#解决方案、Servlet之Fileter解决XSS攻击。一、.会话管理入门1.1生活中会话我:小张,你会跳小苹果码?小张:会,怎么了?我:公司年会上要表演节目,你教教......
  • 小程序打印小票,复制功能,自定义导航栏
    //复制联系地址fnCopyAddress(){wx.setClipboardData({data:this.data.detailInfo.address,success:res=>{Util.errorShow('复制联系地址成功')}})},//打印小票fnPrintTicket(){let_this=this;......