zoukankan      html  css  js  c++  java
  • flutter 自定义TabBar

    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 / 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 / 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),
                      )
                  ],
                ),
              ),
            ],
          ),
        );
      }
    }
    
  • 相关阅读:
    Symbol
    对象的附加属性
    怪异盒模型
    javascript的三大组成部分
    让目标对象滚动到视口位置
    隐藏单个盒子的滚动条
    uni-app判断有没有安装这个app,如果有的话直接打开,没有的话跳转到下载页面
    js 读取json文件
    openlays 使用 svg标注,动态修改svg颜色
    iview table组件内容过多用“...”代替,鼠标悬停显示全部内容
  • 原文地址:https://www.cnblogs.com/ajanuw/p/11456688.html
Copyright © 2011-2022 走看看