Flutter - 动态结构

243 阅读3分钟

5、动态结构

5.1 StatefulWidget

class TableView extends StatefulWidget {
  List listData;
  TableView(this.listData, {Key? key}) : super(key: key);
  @override
  _TableViewState createState() => _TableViewState(this.listData);
}
​
class _TableViewState extends State<TableView> {
  List listData;
  _TableViewState(this.listData);
  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: EdgeInsets.all(10),
      children: [
        Column(
          children: this.listData.map((e){
            return ListTile(
              leading: Image.network(e["imageUrl"]),
              title: Text(e["title"]),
              subtitle: Text(e["subTitle"]),
            );
          }).toList(),
        ),
        SizedBox(height: 20,),
        OutlinedButton(onPressed: () {
            setState(() {
              // this.listData.add({"title" : "ani", "subTitle" : "I,m is dongchanghuyidao. and i was very handsome", "imageUrl" : "https://www.itying.com/images/flutter/1.png"});
              this.listData[1]["title"] = "chaoshuai";
            });
        },  child: Text("点击改变"))
      ],
    );
  }
}

5.2 Tabbar

import 'package:flutter/material.dart';
import 'package:fluttertest/Common/HexColor.dart';
import 'package:fluttertest/Mine/Mine.dart';
import 'package:fluttertest/TaskHall/TaskHall.dart';
import 'package:fluttertest/TaskRelease/TaskRelease.dart';
import '../Home/Home.dart';
​
class JCTabBar extends StatefulWidget {
  JCTabBar({Key? key}) : super(key: key);
  @override
  _JCTabBarState createState() => _JCTabBarState();
}
​
class _JCTabBarState extends State<JCTabBar> {
​
  int _currentIndex = 0;
  List _listControl = [Home(), TaskHall(), TaskRelease(), Mine()];
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("title"),),
      body: this._listControl[this._currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: this._currentIndex,
        onTap: (index) {
          setState(() {
            this._currentIndex = index;
          });
        },
​
        unselectedIconTheme: IconThemeData(color: HexColor.disableColor),
        selectedIconTheme: IconThemeData(color: HexColor.blueColor,),
        unselectedLabelStyle: TextStyle(color: HexColor.disableColor, fontSize: 14),
        selectedLabelStyle: TextStyle(color: HexColor.blueColor, fontSize: 14),
        backgroundColor: HexColor.bgColor,
        type: BottomNavigationBarType.fixed,
​
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
          BottomNavigationBarItem(icon: Icon(Icons.task), label: "分类"),
          BottomNavigationBarItem(icon: Icon(Icons.add_circle), label: "搜索"),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: "我的"),
        ],
      ),
    );
  }
}

5.3 路由跳转

  • push

    Navigator.of(context).push(
        MaterialPageRoute(
          // builder: (context)=> Setting(titleString: "设置中心",)
          builder: (context) {
            return Setting(titleString: "设置中心");
          }
        )
      );
    ​
    // 
    if (item["title"] == "设置中心") {
      Navigator.pushNamed(context, '/setting');
    ​
    } else if (item["title"] == "我的任务") {
      Navigator.pushNamed(context, "/taskDetail", arguments: {"title" : "hellow rd"}); // 路由跳转,不用导入, 直接跳转
    }
    
  • pop

    Navigator.of(context).pop();
    
    import 'package:flutter/material.dart';
    import 'package:fluttertest/Login/LoginController.dart';
    import 'package:fluttertest/Login/RegistCodeController.dart';
    import 'package:fluttertest/Login/RegistPhoneController.dart';
    import 'package:fluttertest/Mine/Setting/Setting.dart';
    import 'package:fluttertest/Mine/TaskDetailController.dart';
    import 'package:fluttertest/Root/TabBarController.dart';
    ​
    class JCRouter extends Object {
    ​
      static final Map<String, WidgetBuilder> routes = {
        
        // 我的模块
        '/taskDetail' : (context, {arguments}) => TaskDetailController(arguments: arguments,), // 我的任务详情
        '/setting' : (context) => Setting(),    // 设置
    ​
        // 登录注册
        '/login' : (context) => LoginController(),                     // 登录
        '/registPhone' : (context) => RegistPhoneController(),         // 手机号码注册
        '/registPhoneCode' : (context) => RegistCodeController(),      // 手机号码注册 - 输入手机号码
      };
    ​
      // push
      static push(BuildContext context, Widget widget) {
        Navigator.of(context).push(MaterialPageRoute(builder: (context) => widget));
      }
    ​
      // push并且覆盖当前页面
      static pushAndReplaceCurrent(BuildContext context, String name) {
        Navigator.of(context).pushReplacementNamed(name);
      }
    ​
      // pop
      static pop(BuildContext context) {
        Navigator.of(context).pop();
      }
    ​
      // pop 到 tabbar
      static popToTab(BuildContext context, int index) {
        Navigator.of(context).pushAndRemoveUntil(
          new MaterialPageRoute(builder: (context) => JCTabBar(index: index,)),
          (route) => route == null
        );
      }
    ​
       // 设置路由传参
      static RouteFactory onGenerateRoute = (RouteSettings settings) {
          final String name = settings.name!;
          final Function pageContentBuilder = routes[name]!;
          if (pageContentBuilder != null) {
            if (settings.arguments != null) {
              final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context, arguments : settings.arguments));
              return route;
            } else {
              final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context));
              return route;
            }
          }
      };
    }
    // 路由push
    Navigator.pushNamed(context, '/registPhoneCode');
    Navigator.of(context).pushReplacementNamed("/registPhoneCode");
    JCRouter.pushAndReplaceCurrent(context, "/registPhoneCode");
    ​
    // pop
    JCRouter.pop(context);
    JCRouter.popToTab(context, 3);
    

5.4 自定义AppBar

return DefaultTabController(
    length: 5, 
    child: Scaffold(
      appBar: AppBar(
        backgroundColor: HexColor("f5f5f5"),
        title: Text("任务大厅", style: TextStyle(color: HexColor.textColor,fontSize: 18),),
        iconTheme : IconThemeData(color: HexColor.textColor),
        bottom: TabBar(
          indicatorColor: HexColor.themeColor,  
          labelColor: HexColor.themeColor,
          unselectedLabelColor: HexColor.disableColor,
          indicatorSize: TabBarIndicatorSize.label,
          tabs: [
            Tab(text: "全部",),
            Tab(text: "待提交",),
            Tab(text: "审核中",),
            Tab(text: "未通过",),
            Tab(text: "已完成",)
          ],
          onTap: (index) {
            print(index);
          },
        ),
      ),
      body: TabBarView(
        children: [
          ListView(children: this.getListViewWithData(this.listData),),
          ListView(children: this.getListViewWithData(this.listData2),),
          ListView(children: this.getListViewWithData(this.listData),),
          ListView(children: this.getListViewWithData(this.listData2),),
          ListView(children: this.getListViewWithData(this.listData),),
        ],
      ),
    )
  );

5.5 自定义侧边栏 Drawer

5.6 FButton

https://pub.dev/packages/fbutton
​
fbutton_nullsafety: ^3.0.1
​
flutter pub get
FButton(
    highlightColor: Colors.red,
    width: 140,
    height: 40,
    alignment: Alignment.center,
    onPressed: () {
​
    },
    text: "飞猪按钮",
    color: HexColor.themeColor,
    style: TextStyle(color: HexColor.bgColor),
    image: Icon(Icons.search),
    imageAlignment: ImageAlignment.right,
    corner: FCorner.all(16.0),
)

5.7 FloatButton 凸起Tabbar

floatingActionButton: Container(
  padding: EdgeInsets.all(6),
  width: 60,
  height: 60,
  margin: EdgeInsets.only(top: 5),
  decoration: BoxDecoration(
    borderRadius: BorderRadius.circular(60/2.0),
    color: HexColor.whiteColor
  ),
  child: FloatingActionButton(
    onPressed: () {
      setState(() {
        this._currentIndex = 2;
       });
    },
    backgroundColor: this._currentIndex == 2 ? HexColor.themeColor : HexColor.disableColor,
    child: Icon(Icons.add),
    ),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,

5.8 CheckBox

自定义复选框

InkWell(
    onTap: () {
      setState(() {
        this.userAgree = !this.userAgree;
      });
    },
    child:  Padding(
      padding: const EdgeInsets.all(10.0),
      child: this.userAgree
          ? Icon(
              Icons.check_box,
              size: 20.0,
              color: Colors.blue,
            )
          : Icon(
              Icons.check_box_outline_blank,
              size: 20.0,
              color: Colors.blue,
            ),
    ),
  )
Checkbox(
  value: this.userAgree,
  activeColor: HexColor.blueColor,
  hoverColor: HexColor.blueColor, // 悬停颜色
  // checkColor: HexColor.whiteColor, 选中的时候勾勾颜色
​
  onChanged: (value) {
    setState(() {
      this.userAgree = value;
    });
  }
),

5.9 TextField

final FocusNode _keyboydFoucs = new FocusNode();
String userPhone = "";
bool userAgree = false;
​
FButton(
  highlightColor: HexColor.clearColor, color: HexColor.clearColor,
  height: 150, width: 500, 
  onPressed: () {
    // FocusScope.of(context).autofocus(FocusNode()); 获取焦点
    this._keyboydFoucs.unfocus(); // 失去焦点
  },
),
Container(
  padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
  child: TextField(
    autofocus: true,
    focusNode: this._keyboydFoucs, // 绑定焦点处理
    keyboardType: TextInputType.number,
    maxLength: 11,
    decoration: InputDecoration(
      labelText: "手机号",
      helperText: "请输入手机号码, 未注册手机号码将自动注册",
​
    ),
    style: TextStyle(fontSize: 18),
    onChanged: (value) {
      setState(() {
        print("value " + value);
        this.userPhone = value;
      });
    },
  ),
),
  • 点击背景让键盘消失
body: GestureDetector (
    behavior: HitTestBehavior.translucent,
    onTap: () {
      print("点击背景手势");
      this._keyboydFoucs.unfocus(); // 失去焦点
    },
    child: child,
)

5.10 定时器

_showTimer(context) {
    var timer;
    timer = Timer.periodic(Duration(milliseconds: 3000), (timer) {
      Navigator.pop(context);
      timer.cancel();
    });
  }

5.11 轮播图

child: AspectRatio(
    aspectRatio: 16 / 9,
    child: Swiper(
      itemCount: list.length,
      itemBuilder: (BuildContext context, int index) {
        return new Image.network(
          list[index]["url"] as String,
          fit: BoxFit.cover,
        );
      },
      autoplay: true,
      pagination: SwiperPagination(),
    ),
  ),