如何在微信小程序中实现今日头条App那样的Topbar
来源:互联网 发布:matlab数据归一化 编辑:程序博客网 时间:2024/05/21 09:32
今日头条App的Topbar是一个典型的频道管理和切换组件,自己前段时间研究了一番,在微信小程序上也实现了类似的效果。
http://biebu.xin/2017/03/07/%E5%A6%82%E4%BD%95%E5%9C%A8%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%B8%AD%E5%AE%9E%E7%8E%B0%E4%BB%8A%E6%97%A5%E5%A4%B4%E6%9D%A1App%E9%82%A3%E6%A0%B7%E7%9A%84Topbar/
我们先看具体效果好了 ↓↓↓
这个项目(wx-topbar)已经放在GitHub
上了——点此前往,欢迎学习交流。
接下来,简要说一下实现思路。
先看视图层,Topbar横向滚动对应的WXML
代码如下:
<scroll-view class="navbar" scroll-x="true" scroll-left="{{scrollNavbarLeft}}"> <view class="navbar-item {{ navbarArray[item].type }}" id="{{ item }}" wx:for="{{ navbarShowIndexArray }}" catchtap="onTapNavbar"> <view class="navbar-item-wrap">{{ navbarArray[item].text }}</view> </view> <view class="navbar-item visibility-hidden"> <view class="navbar-item-wrap">空白</view> </view></scroll-view><view class="navbar-arrow-down" catchtap="showChannelSettingModal"> <view class="navbar-arrow-down-wrap"> <image class="navbar-arrow-icon" src="/images/index/icon_arrow_down.png"></image> </view></view>
scroll-view
负责Topbar中各个频道的呈现,所有频道的相关数据都存储在navbarArray
这个对象数组里,而数组navbarShowIndexArray
里存储了要显示频道在数组navbarArray
中的索引。
不难猜测,频道是否选中高亮,与数组navbarArray
有关;频道是否显示,与数组navbarShowIndexArray
有关。
点击某个频道名称,就会触发对应频道的切换操作。
view.navbar-arrow-down
对应的是右上角的向下箭头,可采用fixed
定位类型,点击后弹出管理频道的Modal.
<view class="channel-setting-modal {{ channelSettingModalShow }}" hidden="{{ channelSettingModalHide }}"> <view class="channel-show-text"> <view class="channel-show-text-wrap">显示频道</view> </view> <view class="channel-item" wx:for="{{ navbarShowIndexArray }}"> <view class="channel-item-wrap"> <view class="channel-item-left"> <image class="channel-item-icon-minus {{ !index || navbarShowIndexArray.length < 4 ? 'visibility-hidden' : '' }}" id="{{ item }}.0" src="/images/index/icon_minus.png" catchtap="hideChannel"></image> <view class="channel-item-text">{{ navbarArray[item].text }}</view> </view> <view class="channel-item-up {{ index < 2 ? 'visibility-hidden' : '' }}" id="{{ item }}.00" catchtap="upChannel">上移</view> </view> </view> <view class="channel-hide-text"> <view class="channel-hide-text-wrap">隐藏频道</view> </view> <view class="channel-item" wx:for="{{ navbarHideIndexArray }}"> <view class="channel-item-wrap"> <view class="channel-item-left"> <image class="channel-item-icon-plus" id="{{ item }}.0" src="/images/index/icon_plus.png" catchtap="showChannel"></image> <view class="channel-item-text">{{ navbarArray[item].text }}</view> </view> <view class="channel-item-up visibility-hidden">上移</view> </view> </view></view>
在这个管理频道的Modal里,通过改变数组navbarShowIndexArray
来控制频道是否显示和显示顺序,同时,需要另外一个数组navbarHideIndexArray
来存储隐藏的频道。
Modal显示的时候,Topbar需要被另一个写有“频道设置”字样的Bar覆盖。
<view class="channel-setting {{ channelSettingShow }}"> <view class="channel-setting-text">频道设置</view> <view class="navbar-arrow-up" catchtap="hideChannelSettingModal"> <image class="navbar-arrow-icon navbar-arrow-icon-up" src="/images/index/icon_arrow_up.png"></image> </view></view>
然后,我们来看逻辑层的实现。初始化的部分data
如下:
data: { navbarArray: [{ text: '推荐', type: 'navbar-item-active' }, { text: '热点', type: '' }, { text: '视频', type: '' }, { text: '图片', type: '' }, { text: '段子', type: '' }, { text: '社会', type: '' }, { text: '娱乐', type: '' }, { text: '科技', type: '' }, { text: '体育', type: '' }, { text: '汽车', type: '' }, { text: '财经', type: '' }, { text: '搞笑', type: '' }], navbarShowIndexArray: Array.from(Array(12).keys()), navbarHideIndexArray: [], channelSettingShow: '', channelSettingModalShow: '', channelSettingModalHide: true}
navbar-item-active
是一个可使频道高亮的Class
,navbarShowIndexArray
初始化的结果是一个0到11的数组,刚好是数组navbarArray
的所有元素的索引。显然,初始化的结果是所有频道都将显示。
为了实现频道个性化配置的保存,navbarShowIndexArray
还需要通过小程序的数据缓存API储存起来。
storeNavbarShowIndexArray: function() { const that = this; wx.setStorage({ key: 'navbarShowIndexArray', data: that.data.navbarShowIndexArray });}
切换频道的函数如下:
switchChannel: function(targetChannelIndex) { this.getArticles(targetChannelIndex); let navbarArray = this.data.navbarArray; navbarArray.forEach((item, index, array) => { item.type = ''; if (index === targetChannelIndex) { item.type = 'navbar-item-active'; } }); this.setData({ navbarArray: navbarArray, currentChannelIndex: targetChannelIndex });}
这样,频道的管理和简单切换我们就实现了。
但是,到此为止,频道的切换只能通过点击对应Topbar中频道那一小块区域来实现,要是在正文区域左滑和右滑也能切换频道就好了。
一个容易想到的思路是,在正文区域绑定touch
事件,通过坐标判断滑动方向,然后使Topbar中当前频道的上一个或下一个频道高亮,同时,控制Topbar横向滚动合适的偏移长度,以确保切换后的频道能出现在视图区域。
onTouchstartArticles: function(e) { this.setData({ 'startTouchs.x': e.changedTouches[0].clientX, 'startTouchs.y': e.changedTouches[0].clientY });},onTouchendArticles: function(e) { let deltaX = e.changedTouches[0].clientX - this.data.startTouchs.x; let deltaY = e.changedTouches[0].clientY - this.data.startTouchs.y; if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 10) { let deltaNavbarIndex = deltaX > 0 ? -1 : 1; let currentChannelIndex = this.data.currentChannelIndex; let navbarShowIndexArray = this.data.navbarShowIndexArray; let targetChannelIndexOfNavbarShowIndexArray = navbarShowIndexArray.indexOf(currentChannelIndex) + deltaNavbarIndex; let navbarShowIndexArrayLength = navbarShowIndexArray.length; if (targetChannelIndexOfNavbarShowIndexArray >= 0 && targetChannelIndexOfNavbarShowIndexArray <= navbarShowIndexArrayLength - 1) { let targetChannelIndex = navbarShowIndexArray[targetChannelIndexOfNavbarShowIndexArray]; if (navbarShowIndexArrayLength > 6) { let scrollNavbarLeft; if (targetChannelIndexOfNavbarShowIndexArray < 5) { scrollNavbarLeft = 0; } else if (targetChannelIndexOfNavbarShowIndexArray === navbarShowIndexArrayLength - 1) { scrollNavbarLeft = this.rpx2px(110 * (navbarShowIndexArrayLength - 6)); } else { scrollNavbarLeft = this.rpx2px(110 * (targetChannelIndexOfNavbarShowIndexArray - 4)); } this.setData({ scrollNavbarLeft: scrollNavbarLeft }); } this.switchChannel(targetChannelIndex); } }}
更多的技术细节,请移步GitHub
——点此前往。
- 如何在微信小程序中实现今日头条App那样的Topbar
- 怎么实现类似"今日头条"app
- 微信小程序_今日头条
- 微信小程序---仿今日头条
- 大数据时代,如何像看“今日头条”那样去看电视?
- 今日头条app数据包分析
- 今日头条(App和MainActivity类)
- 今日头条的首页
- Viewpager实现今日头条顶部导航的功能
- ListView+Fragment+ViewPager配合,实现今日头条的效果
- iOS 仿照今日头条 实现的滚动表格 XLSlideSwitch
- 仿今日头条“关注”按钮的实现
- 今日头条lite:你关心的才是头条【极乐小程序商店出品】
- 如何利用今日头条盈利?
- 如何下载今日头条视频
- 今日头条如何快速开通原创
- 产品经理爱好者的App评测之今日头条(一)
- AndroidStudio——今日头条(可以实时获取数据的app)
- BlueTooth----蓝牙
- java 算法理解二
- [Boolan] C++第八周 STL 泛型编程(二)
- 继承System.Web.UI.Page的页面基类
- 初探Linux——Linux中常用的操作命令
- 如何在微信小程序中实现今日头条App那样的Topbar
- BIO
- getParameterValues和getParameter的区别
- [LeetCode]389. Find the Difference(找不同)
- react native开发:实现点击左侧选择项,右侧显示内容的功能
- java.lang.ClassNotFoundException: com.fasterxml.jackson.core.JsonProcessingException
- 纯css实现进度条效果
- future.channel().closeFuture().sync();后面代码不执行
- 盒模型代码简写