Flutter第五期 - 樣式、Scaffold、TabBar、底部導航

    繼續我們的flutter之旅,今天學首頁怎麼寫,APP的首頁目前比較單一,都是下面幾個菜單,上面幾個菜單,或者側面一個我的,所以可以寫一個活的套用,以後就不用麻煩了。

    前言:樣式自定義基本上都是一樣的,什麼圓角,什麼陰影,什麼旋轉,什麼漸變,總結一下以後別忘了。

    樣式1:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

//Stateless widgets 是不可變的, 這意味着它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new MaterialApp(
      title: "樣式佈局",
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("樣式佈局"),
        ),
        body: new Center(
          child: new FormTestRoute1(),
        ),
      ),
    );
  }
}

class FormTestRoute1 extends StatefulWidget {
  @override
  _FormTestRouteState1 createState() => new _FormTestRouteState1();
}

class _FormTestRouteState1 extends State<FormTestRoute1> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      //上下左右各添加16像素補白
      padding: EdgeInsets.all(16.0),
      child: Column(
        //顯式指定對齊方式爲左對齊,排除對齊干擾
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            //左邊添加8像素補白
            padding: const EdgeInsets.only(left: 8.0),
            child: Text("hi yun1"),
          ),
          Padding(
            //上下各添加8像素補白
            padding: const EdgeInsets.symmetric(vertical: 8.0),
            child: Text("hi yun2"),
          ),
          Padding(
            // 分別指定四個方向的補白
            padding: const EdgeInsets.fromLTRB(20.0, .0, 20.0, 20.0),
            child: Text("hi yun3"),
          ),
          DecoratedBox(
              decoration: BoxDecoration(
                  gradient: LinearGradient(
                      colors: [Colors.red, Colors.orange[700]]), //背景漸變
                  borderRadius: BorderRadius.circular(3.0), //3像素圓角
                  boxShadow: [
                    //陰影
                    BoxShadow(
                        color: Colors.black54,
                        offset: Offset(2.0, 2.0),
                        blurRadius: 4.0)
                  ]),
              child: Padding(
                padding: EdgeInsets.symmetric(horizontal: 80.0, vertical: 18.0),
                child: Text(
                  "Login",
                  style: TextStyle(color: Colors.white),
                ),
              )),
        ],
      ),
    );
  }
}

    blob.png

    

    樣式2:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

//Stateless widgets 是不可變的, 這意味着它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new MaterialApp(
      title: "樣式佈局",
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("樣式佈局"),
        ),
        body: new Center(
          child: new FormTestRoute1(),
        ),
      ),
    );
  }
}

class FormTestRoute1 extends StatefulWidget {
  @override
  _FormTestRouteState1 createState() => new _FormTestRouteState1();
}

class _FormTestRouteState1 extends State<FormTestRoute1> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      //上下左右各添加16像素補白
      padding: EdgeInsets.all(16.0),
      child: Column(
        //顯式指定對齊方式爲左對齊,排除對齊干擾
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Container(
            margin: EdgeInsets.only(
                top: 50.0, left: 120.0, right: 0.0, bottom: 50.0),
            //容器外補白
            constraints: BoxConstraints.tightFor(width: 200.0, height: 150.0),
            //卡片大小
            decoration: BoxDecoration(
                //背景裝飾
                gradient: RadialGradient(
                    //背景徑向漸變
                    colors: [Colors.red, Colors.orange],
                    center: Alignment.topLeft,
                    radius: .98),
                boxShadow: [
                  //卡片陰影
                  BoxShadow(
                      color: Colors.black54,
                      offset: Offset(2.0, 2.0),
                      blurRadius: 4.0)
                ]),
            transform: Matrix4.rotationZ(.2),
            //卡片傾斜變換
            alignment: Alignment.center,
            //卡片內文字居中
            child: Text(
              //卡片文字
              "5.20", style: TextStyle(color: Colors.white, fontSize: 40.0),
            ),
          ),
          Container(
            margin: EdgeInsets.all(20.0), //容器外補白
            color: Colors.orange,
            child: Text("hi yun~"),
          ),
          Container(
            padding: EdgeInsets.all(20.0), //容器內補白
            color: Colors.orange,
            child: Text("hi yun~"),
          ),
        ],
      ),
    );
  }
}

    blob.png


    Scaffold:

    大多數路由頁都會包含一個導航欄,有些路由頁可能會有抽屜菜單(Drawer)以及底部Tab導航菜單等。如果每個頁面都需要開發者自己手動去實現,這會是一件非常無聊的事。幸運的是,我們前面提到過,Flutter Material庫提供了一個Scaffold Widget,它是一個路由頁的骨架,可以非常容易的拼裝出一個完整的頁面。

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

//Stateless widgets 是不可變的, 這意味着它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new MaterialApp(
      title: "Scaffold首頁",
      home: new Scaffold(
//        appBar: new AppBar(
//          title: new Text("Scaffold首頁"),
//        ),
        body: new Center(
          child: new FormTestRoute1(),
        ),
      ),
    );
  }
}

class FormTestRoute1 extends StatefulWidget {
  @override
  _FormTestRouteState1 createState() => new _FormTestRouteState1();
}

class _FormTestRouteState1 extends State<FormTestRoute1>
    with SingleTickerProviderStateMixin {
  int _selectedIndex = 1;

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  void _onAdd() {}

  TabController _tabController;
  List tabs = ["Yun1", "Yun2", "Yun3"];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _tabController = TabController(length: tabs.length, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: new Text("Scafford首頁"),
        leading: Builder(builder: (context) {
          return IconButton(
            icon: Icon(Icons.dashboard, color: Colors.white), //自定義圖標
            onPressed: () {
              // 打開抽屜菜單
              Scaffold.of(context).openDrawer();
            },
          );
        }),
        actions: <Widget>[
          IconButton(
            icon: Icon(
              Icons.share,
            ),
            onPressed: () {},
          ),
        ],
        bottom: TabBar(
          controller: _tabController,
          tabs: tabs.map((e) => Tab(text: e)).toList(),
        ),
      ),
      drawer: new MyDrawer(),
      body: TabBarView(
        controller: _tabController,
        children: tabs.map((e) {
          return Container(
            alignment: Alignment.center,
            child: Text(
              e,
              textScaleFactor: 5,
            ),
          );
        }).toList(),
      ),
//      bottomNavigationBar: BottomNavigationBar(
//        items: <BottomNavigationBarItem>[
//          BottomNavigationBarItem(
//              icon: Icon(Icons.home), title: new Text("Yun1")),
//          BottomNavigationBarItem(
//              icon: Icon(Icons.business), title: new Text("Yun2")),
//          BottomNavigationBarItem(
//              icon: Icon(Icons.school), title: new Text("Yun3")),
//        ],
//        currentIndex: _selectedIndex,
//        fixedColor: Colors.blueGrey,
//        onTap: _onItemTapped,
//      ),
      bottomNavigationBar: BottomAppBar(
        color: Colors.white,
        shape: CircularNotchedRectangle(), // 底部導航欄打一個圓形的洞
        child: Row(
          children: [
            IconButton(icon: Icon(Icons.home)),
            SizedBox(), //中間位置空出
            IconButton(icon: Icon(Icons.business)),
          ],
          mainAxisAlignment: MainAxisAlignment.spaceAround, //均分底部導航欄橫向空間
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: _onAdd,
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }
}

// 抽屜
class MyDrawer extends StatelessWidget {
  const MyDrawer({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: MediaQuery.removePadding(
        context: context,
        // DrawerHeader consumes top MediaQuery padding.
        removeTop: true,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(top: 38.0),
              child: Row(
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 16.0),
                    child: ClipOval(
                      child: Image.asset(
                        "imgs/avatar.png",
                        width: 80,
                      ),
                    ),
                  ),
                  Text(
                    "Wendux",
                    style: TextStyle(fontWeight: FontWeight.bold),
                  )
                ],
              ),
            ),
            Expanded(
              child: ListView(
                children: <Widget>[
                  ListTile(
                    leading: const Icon(Icons.add),
                    title: const Text('Add account'),
                  ),
                  ListTile(
                    leading: const Icon(Icons.settings),
                    title: const Text('Manage accounts'),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

    blob.png blob.png blob.png

    總結:這塊的關鍵leading,TabBar,TabBarView,BottomNavigationBar,BottomAppBar的使用,寫法都是固定的,需要相互配合,多練吧~

    60d2c107ly1g2ii746jyzg208c05kn3j.gif



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章