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. CF733F

    扯在前面 人生第一道黑(>▽< ). 那天听了老师讲图论讲了这道题,发现这道黑题并不是很黑于是就做了做,在同机房dalao的帮助下三个小时做完(太菜了),于是来发篇题解. 正文 题意 给出 ...

  2. 小w、小j和小z

    n个月没更了,现在学的东西很难,掌握不好,不敢更! 这个题目既不超范围又足够难想,反正我没想出来,很好的题目! 我发现noi.ac上的题目很不错!!! ------------------------ ...

  3. BootstrapValidator验证规则、BootStrap表格:列参数

    BootstrapValidator验证规则 需引用组件 <script src="~/Scripts/jquery-1.10.2.js"></script> ...

  4. 最简单直接地理解Java软件设计原则之依赖倒置原则

    理论性知识 定义 依赖倒置原则,Dependence Inversion Principle (DIP) 高层模块不应该依赖低层模块.二者都应该依赖其抽象. 抽象不应该依赖细节,细节应该依赖抽象. 针 ...

  5. 复制虚拟机,链接网络问题:没有找到合适的设备:没有找到可用于链接System eth0 的

    http://my.oschina.net/coolfire368/blog/292742 1./etc/udev/rules.d/70-persistent-net.rules 修改也成,修改时留下 ...

  6. UML——基本结构

    一.宏观导图 学习UML的时候我们首先要把握好她的结构,基本上好料都在里面了.最重要的是构造块的学习. 公共机制:是为了让我们更加清楚的描述UML的各种关系.图.事物等. 规则:和语法的意思差不多,就 ...

  7. acid解释

    原子性A:一个事务内部的所有操作都是不可分割的,这叫原子性.一致性C:事务内部的所有操作要么都成功,要么都失败.隔离性I:事务与事务之间永远不相见.持久性D:就是说数据最终是落到磁盘永久保存的.

  8. Hyperbase常用SQL

    1.创建表 1.1 建HBase内表 CREATE TABLE hbase_inner_table(   key1 string,   bi bigint,   dc decimal(10,2),   ...

  9. PTA甲级—链表

    1032 Sharing (25分) 回顾了下链表的基本使用,这题就是判断两个链表是否有交叉点. 我最开始的做法就是用cnt[]记录每个节点的入度,发现入度为2的节点即为答案.后来发现这里忽略了两个链 ...

  10. 1155 Heap Paths

    题干前半略. Sample Input 1: 8 98 72 86 60 65 12 23 50   Sample Output 1: 98 86 23 98 86 12 98 72 65 98 72 ...