import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/subjects.dart'; double ourMap(v, start1, stop1, start2, stop2) {
return (v - start1) / (stop1 - start1) * (stop2 - start2) + start2;
} void main() => runApp(MyApp()); class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
} class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
} class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
final int initPage = 0;
PageController _pageController;
List<String> tabs = ['aaa', 'bbb', 'ccc', 'ddd', 'eee']; Stream<int> get currentPage$ => _currentPageSubject.stream;
Sink<int> get currentPageSink => _currentPageSubject.sink;
BehaviorSubject<int> _currentPageSubject; Alignment _dragAlignment;
AnimationController _controller;
Animation<Alignment> _animation; @override
void initState() {
super.initState();
_currentPageSubject = BehaviorSubject<int>.seeded(initPage);
_pageController = PageController(initialPage: initPage);
_dragAlignment = Alignment(ourMap(initPage, 0, tabs.length - 1, -1, 1), 0); _controller = AnimationController(
vsync: this,
duration: kThemeAnimationDuration,
)..addListener(() {
setState(() {
_dragAlignment = _animation.value;
});
}); currentPage$.listen((int page) {
_runAnimation(
_dragAlignment,
Alignment(ourMap(page, 0, tabs.length - 1, -1, 1), 0),
);
});
} @override
void dispose() {
_currentPageSubject.close();
_pageController.dispose();
_controller.dispose();
super.dispose();
} void _runAnimation(Alignment oldA, Alignment newA) {
_animation = _controller.drive(
AlignmentTween(
begin: oldA,
end: newA,
),
); _controller.reset();
_controller.forward();
} @override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
SizedBox(height: MediaQuery.of(context).padding.top + 20),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Container(
height: 40,
decoration: BoxDecoration(
color: Colors.black38,
borderRadius: BorderRadius.circular(35),
),
child: Stack(
children: <Widget>[
// use animation controller
// Align(
// alignment: _dragAlignment,
// child: LayoutBuilder(
// builder:
// (BuildContext context, BoxConstraints constraints) {
// double width = constraints.maxWidth;
// return Padding(
// padding: const EdgeInsets.all(2.0),
// child: Container(
// height: double.infinity,
// width: width / tabs.length,
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(35),
// ),
// ),
// );
// },
// ),
// ), // use animated widget
StreamBuilder(
stream: currentPage$,
builder: (context, AsyncSnapshot<int> snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
return AnimatedAlign(
duration: kThemeAnimationDuration,
alignment: Alignment(
ourMap(snapshot.data, 0, tabs.length - 1, -1, 1),
0),
child: LayoutBuilder(
builder: (BuildContext context,
BoxConstraints constraints) {
double width = constraints.maxWidth;
return Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
height: double.infinity,
width: width / tabs.length,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(35),
),
),
);
},
),
);
}
return SizedBox();
},
),
Align(
alignment: Alignment.center,
child: Row(
children: tabs.map((t) {
int index = tabs.indexOf(t);
return Expanded(
child: MaterialButton(
splashColor: Colors.transparent,
focusColor: Colors.transparent,
color: Colors.transparent,
highlightColor: Colors.transparent,
hoverColor: Colors.transparent,
focusElevation: 0.0,
hoverElevation: 0.0,
elevation: 0.0,
highlightElevation: 0.0,
child: StreamBuilder(
stream: currentPage$,
builder:
(context, AsyncSnapshot<int> snapshot) {
return AnimatedDefaultTextStyle(
duration: kThemeAnimationDuration,
style: TextStyle(
inherit: true,
color: snapshot.data == index
? Colors.black
: Colors.white,
),
child: Text(t),
);
}),
onPressed: () {
currentPageSink.add(index);
_pageController.jumpToPage(index);
},
),
);
}).toList(),
),
),
],
),
),
),
Expanded(
child: PageView(
controller: _pageController,
onPageChanged: (page) => currentPageSink.add(page),
children: <Widget>[
for (var t in tabs)
Center(
child: Text(t),
)
],
),
),
],
),
);
}
}

flutter 自定义TabBar的更多相关文章

  1. flutter 自定义tabbar 给tabbar添加背景功能

    flutter 自带的tabbar BottomNavigationBar有长按水波纹效果,不可以添加背景图片功能,如果有这方面的需求,就需要自定义tabbar了 自定义图片 我们使用BottomAp ...

  2. Flutter实战视频-移动电商-46.详细页_自定义TabBar Widget

    46.详细页_自定义TabBar Widget 主要实现详情和评论的tab provide定义变量 自己做一个tab然后用provide去控制 定义两个变量来判断是左侧选中了还是右侧选中了.并定义一个 ...

  3. 19 Flutter 自定义AppBar 定义顶部Tab切换 底部Tab结合顶部Tab实现类似头条页面布局(27分36秒)

    Flutter AppBar自定义顶部导航按钮图标.颜色以及TabBar定义顶部Tab切换. leading:在标题前面显示的一个控件,在首页通常显示应用的logo:在其他界面通常显示为付汇按钮. t ...

  4. 自定义tabBar

    ★★★★自定义tabBar★★★★★★★ Demo下载地址:https://github.com/marlonxlj/tabBarCustom.git 前言: 有的时候需求要对tabBar进行自定义的 ...

  5. IOS第二天-新浪微博 - 添加搜索框,弹出下拉菜单 ,代理的使用 ,HWTabBar.h(自定义TabBar)

    ********HWDiscoverViewController.m(发现) - (void)viewDidLoad { [super viewDidLoad]; // 创建搜索框对象 HWSearc ...

  6. iOS 隐藏自定义tabbar

    iOS  隐藏自定义tabbar -(void)viewWillAppear:(BOOL)animated { NSArray *array=self.tabBarController.view.su ...

  7. iOS开发之功能模块--关于自定义TabBar条

    只上项目中用到的代码: 1.实现重写TabBar的TabBarItem,然后在中间额外加一个按钮. #import <UIKit/UIKit.h> @interface BikeTabBa ...

  8. iOS开发项目之四 [ 调整自定义tabbar的位置与加号按钮的位置]

    自定义tabbar与按钮的添加 01 - 把系统的tabbar用我们自己的覆盖 LHQTabBar *lhqTabBar = [[LHQTabBar alloc]init]; [self setVal ...

  9. 关于自定义tabBar时修改系统自带tabBarItem属性造成的按钮顺序错乱的问题相关探究

      关于自定义tabBar时修改系统自带tabBarItem属性造成的按钮顺序错乱的问题相关探究 测试代码:http://git.oschina.net/Xiyue/TabBarItem_TEST 简 ...

随机推荐

  1. mysql8.0.19忘记密码

    1.管理员打开cmd窗口 2.输入net stop mysql,停止mysql服务 3.开启跳过验证密码的mysql服务 用记事本打开 输入skip-grant-tables ,保存 4.管理员打开新 ...

  2. 系列trick - bitmask

    目录 系列trick - bitmask 拆位 位运算优化(点少的)图操作 位筛 系列trick - bitmask 拆位 主体思想:位之间不影响,把每一位拆开来考虑贡献,转化成非常容易考虑的 0/1 ...

  3. jQuery实战笔记

    文章目录 1.标签隐藏显示 2.时间戳转换 3.radio单选框获取选中 4.判断字符串是否为数字类型 5.tab标签页实现 6.标签点击事件 7.jquery跳转链接 8.jquery修改图片url ...

  4. OpenStack (云计算与openstck简介)

    云计算 什么是云计算 云计算是一种按使用量付费的模式,这种模式提供可用的,便捷的,按需的网络访问,通过互联网进入可配置的计算资源共享池(资源包括,计算,存储,应用软件和服务) 云计算的特征 易于管理: ...

  5. RabbitMQ (简单集群部署操作)

    RabbitMQ 集群部署 前期准备 第一步:三台linux系统(centos7.3) 主机名(hostname) 网卡ip node1 192.168.137.138 node2 192.168.1 ...

  6. 人均年薪50万以上,docker到底是什么?为什么这么火?

    为什么要使用Docker? 场景一:公司双十一买了一堆服务器,技术总监让你给它们一个个都配置上JDK.Mysql.Redis等软件环境. 你心里小声嘀咕:"这总监不讲武德!"然后你 ...

  7. C/C++函数与变量前面的标识符的作用

    ​​ 作者:良知犹存 转载授权以及围观->欢迎添加Wx:Allen-Iverson-me-LYN 缅怀逝者,向英雄致敬.愿山河无恙,国泰民安. 在用C/C++写代码的时候我们经常会使用一些标识符 ...

  8. 2020第十一届蓝桥杯第二场省赛C++A组【A-H】

    A. 门牌制作 答案 624 代码 #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_st ...

  9. c++格式化输入输出以及操纵器的使用

    C++格式化输入和输出 1,ios类中定义的格式控制标志 ios类中定义了一个数据成员:格式控制标志字,long x_flags x_flags每一位的状态值用枚举符号常量定义:如下列出常用几个 en ...

  10. 【uva 11054】Wine trading in Gergovia(算法效率--等价转换)

    题意:N个等距村庄,买(>0)卖(<0)酒,供需平衡,运K则需K劳动力.问所需的最小劳动力. 解法:由于运出或运入1的都需经过2,所以无论如何,都可以等价于从2本身运入或运出.因此可以将1 ...