美文网首页Flutter圈子程序员Flutter
新贵 Flutter (6)中 Material Design

新贵 Flutter (6)中 Material Design

作者: zidea | 来源:发表于2019-06-19 11:21 被阅读43次
flutter

大家都知道 google 推出 Material Design 让没有多少设计经验的开发者也可以设计出精美界面。而且对 material design google 也投入了很多,轻松找到许多 iso 或 android 端的组件。当然 Flutter 官方也提供许多支持 Material Design 的组件。
这些组件我们轻松地在 Flutter 官网提供 Material Component Widgets 找到。

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';

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

class MyApp extends StatelessWidget{
  const MyApp();

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(home: const MyHomePage(),);
  }

}

class MyHomePage extends StatelessWidget{
  const MyHomePage({Key key}):super(key:key);
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container();
  }

}

创建课件数据类,用于持有数据,Tut 包含课件名称、说明和课时以及图片。

class Tut{
  const Tut({this.name, this.description,this.courses,this.imageUrl});
  final String name;
  final String description;
  final String courses;
  final String imageUrl;

}

这里模拟数据集合,这一切都是为了演示做基础,为一些假数据。这里简单用 express 启动一个服务提供图片,供 flutter 对图片进行预览。

final List<Tut> _tuts = <Tut>[
  Tut(
      name: 'React',
      description: '有关 React 的基础教程',
      courses: 12,
      imageUrl: 'http://$server:3000/images/react.png'),
  Tut(
      name: 'Vue',
      description: '有关 Vue 的基础教程',
      courses: 12,
      imageUrl: 'http://$server:3000/images/vue.jpeg'),
  Tut(
      name: 'Angular',
      description: '有关 Angular 的基础教程',
      courses: 6,
      imageUrl: 'http://$server:3000/images/angular.jpg')
];

创建 ListView 的视图列表,调用其静态方法 builder 来构建 ListView,在 builder 方法传入 itemCount 也就是条目数,和 itemExtent 是列表条目的高度,itemBuilder 接受一个函数作为参数,函数会得到 context 和 index(位置信息)的参数来构建列表内容,返回 Widget 就是列表条目的内容。

class MyHomePage extends StatelessWidget{
  const MyHomePage({Key key}):super(key:key);

  Widget _listItemBuilder(BuildContext context, int index){
    return Text(_tuts[index].name);
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text('Tuts'),),
      body: ListView.builder(itemCount: _tuts.length,itemExtent:60.0,itemBuilder: _listItemBuilder),
    );
  }

}
  Widget _listItemBuilder(BuildContext context, int index){
    return Text(_tuts[index].name,style: Theme.of(context).textTheme.headline,);
  }
  • Theme.of(context).textTheme.headline 获取主题,然后为文本添加主题默认文本样式。
  Widget _listItemBuilder(BuildContext context, int index){
    return new Container(
      padding: const EdgeInsets.only(left: 16.0),
      child: Text(_tuts[index].name,style: Theme.of(context).textTheme.headline,),
    ) ;
  }

  • padding: const EdgeInsets.only(left: 16.0), 通过 padding 属性添加内边距属性。EdgeInsets 类的 only 方法来控制左侧的内边距。

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key key}) : super(key: key);

  Widget _listItemBuilder(BuildContext context, int index) {
    return new GestureDetector(
      onTap: () => showDialog(
          context: context,
          builder: (context) => _dialogBuilder(context, _tuts[index])),
      child: Container(
        padding: const EdgeInsets.only(left: 16.0),
        child: Text(
          _tuts[index].name,
          style: Theme.of(context).textTheme.headline,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('Tuts'),
      ),
      body: ListView.builder(
          itemCount: _tuts.length,
          itemExtent: 60.0,
          itemBuilder: _listItemBuilder),
    );
  }

  Widget _dialogBuilder(BuildContext context, Tut tut) {
    return SimpleDialog(
      children: <Widget>[
        Container(
          width: 80.0,
          height: 80.0,
        )
      ],
    );
  }
}

  • 使用手势组件对条目组件进行包裹,从而为条目添加点击事件 onTap 点击条目后会弹出一个对话框,与上面创建条目一样我们需要为函数做 dialog 构建函数,该函数返回组件就是我们看到对话框 SimpleDialog 。
  • 为 SimpleDialog 添加内容,这里添加一个图片 Image ,然后调用 network 方法来从网上获取图片资源将其显示,通过将 BoxFit.fill 传入到 fit 参数来用图片将对话框撑起来。
Widget _dialogBuilder(BuildContext context, Tut tut) {
    return SimpleDialog(
      children: <Widget>[
        Image.network(tut.imageUrl, fit:BoxFit.fill,),

      ],
    );
  }
  • 接下来将课程的一些信息如名称、说明显示在图片下方。
  Widget _dialogBuilder(BuildContext context, Tut tut) {
    return SimpleDialog(
      contentPadding: EdgeInsets.zero,
      children: <Widget>[
        Image.network(tut.imageUrl, fit:BoxFit.fill,),
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: <Widget>[],
          ),
        )
      ],

    );
  }
  Widget _dialogBuilder(BuildContext context, Tut tut) {
    return SimpleDialog(
      contentPadding: EdgeInsets.zero,
      children: <Widget>[
        Image.network(tut.imageUrl, fit:BoxFit.fill,),
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: <Widget>[
              Text(tut.name),
              Text('${tut.courses} 课'),
              Text(tut.description)
            ],
          ),
        )
      ],

    );
  }
  Widget _dialogBuilder(BuildContext context, Tut tut) {
    return SimpleDialog(
      contentPadding: EdgeInsets.zero,
      children: <Widget>[
        Image.network(tut.imageUrl, fit:BoxFit.fill,),
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Text(tut.name),
              Text('${tut.courses} 课'),
              Text(tut.description)
            ],
          ),
        )
      ],

    );
  }
Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Text(tut.name, style: localTheme.textTheme.display1,),
              Text('${tut.courses} 课',style: localTheme.textTheme.subhead.copyWith(fontStyle: FontStyle.italic),),
              SizedBox(height: 16.0,),
              Text(tut.description)
            ],
          ),
        )
  • style 使用 localTheme 为字体添加显示样式
  • SizeBox 可以为文字添加行间距


完整代码
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';

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

class MyApp extends StatelessWidget {
  const MyApp();

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      theme: ThemeData(primarySwatch: Colors.purple,buttonColor: Colors.purple,buttonTheme: const ButtonThemeData(
        textTheme: ButtonTextTheme.primary,
      )),
      home: const MyHomePage(),
    );
  }
}

class Tut {
  const Tut({this.name, this.description, this.courses, this.imageUrl});
  final String name;
  final String description;
  final int courses;
  final String imageUrl;
}

final String server =
    defaultTargetPlatform == TargetPlatform.android ? "10.0.2.2" : "localhost";

final List<Tut> _tuts = <Tut>[
  Tut(
      name: 'React',
      description: '有关 React 的基础教程',
      courses: 12,
      imageUrl: 'http://$server:3000/images/react.png'),
  Tut(
      name: 'Vue',
      description: '有关 Vue 的基础教程',
      courses: 12,
      imageUrl: 'http://$server:3000/images/vue.jpeg'),
  Tut(
      name: 'Angular',
      description: '有关 Angular 的基础教程',
      courses: 6,
      imageUrl: 'http://$server:3000/images/angular.jpg')
];

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key key}) : super(key: key);

  Widget _listItemBuilder(BuildContext context, int index) {
    return new GestureDetector(
      onTap: () => showDialog(
          context: context,
          builder: (context) => _dialogBuilder(context, _tuts[index])),
      child: Container(
        padding: const EdgeInsets.only(left: 16.0),
        child: Text(
          _tuts[index].name,
          style: Theme.of(context).textTheme.headline,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('Tuts'),
      ),
      body: ListView.builder(
          itemCount: _tuts.length,
          itemExtent: 60.0,
          itemBuilder: _listItemBuilder),
    );
  }

  Widget _dialogBuilder(BuildContext context, Tut tut) {

    ThemeData localTheme = Theme.of(context);

    return SimpleDialog(
      contentPadding: EdgeInsets.zero,
      children: <Widget>[
        Image.network(tut.imageUrl, fit:BoxFit.fill,),
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Text(tut.name, style: localTheme.textTheme.display1,),
              Text('${tut.courses} 课',style: localTheme.textTheme.subhead.copyWith(fontStyle: FontStyle.italic),),
              SizedBox(height: 16.0,),
              Text(tut.description,style: localTheme.textTheme.body1,),
              SizedBox(height: 16.0,),
              Align(
                alignment: Alignment.centerRight,
                child: Wrap(
                  children: <Widget>[
                    FlatButton(
                      onPressed: (){
                        Navigator.of(context).pop();
                      },
                      child: const Text('更多信息'),
                    ),
                    RaisedButton(
                      onPressed: (){},
                      child: const Text('按钮'),
                    )
                  ],
                ),
              )

            ],
          ),
        )
      ],

    );
  }
}

  • 继续美化界面,在文字下方添加一些按钮表示一些功能,
  • Align 组件用于按钮组件排列方向,alignment: Alignment.centerRight表示居中靠右,然后添加两个按钮分别是 FlatButton 和 RaiseButton

相关文章

网友评论

    本文标题:新贵 Flutter (6)中 Material Design

    本文链接:https://www.haomeiwen.com/subject/xovcqctx.html