Flutter | 常用组件(上)

简介: Flutter | 常用组件(上)

文本


常用的配置


class TextTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
      padding: EdgeInsets.all(30),
      child: Column(
        children: <Widget>[
          Text("hello "),
          //最大行数为一 ,TextOverflow.ellipsis :省略号代替
          Text(
            "hello! I'm 345 " * 5,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
          ),
          //文本缩放因子
          Text("hello 345", textScaleFactor: 2),
          //
          Text("hello 345",
              style: TextStyle(
                  //颜色
                  color: Colors.red,
                  //字号,默认 14
                  fontSize: 18,
                  //粗细
                  fontWeight: FontWeight.w800,
                  //斜体
                  fontStyle: FontStyle.italic,
                  //underline:下划线,overline:上划线,lineThrough:删除线
                  decoration: TextDecoration.underline,
                  decorationColor: Colors.black,
                  //solid:实线,double:双线,dotted:点虚线,dashed:横虚线,wavy:波浪线
                  decorationStyle: TextDecorationStyle.wavy))
        ],
      ),
    ));
  }
}


textAlign:文本的对齐方式;可以选择左对齐、右对齐还是居中。注意,对齐的参考系是Text widget本身


DefaultTextStyle


在 widget 树中,文本的样式默认是可以继承的,因此,如果在 widget 树中的某一个节点设置一个默认的样式,那么该接口的子树中所有文本都会默认使用这个样式


Widget build(BuildContext context) {
  return Scaffold(
      body: Padding(
          padding: EdgeInsets.all(30),
          child: DefaultTextStyle(
              style: TextStyle(
                //颜色
                color: Colors.red,
                //字号,默认 14
                fontSize: 20,
                //粗细
                fontWeight: FontWeight.w900,
              ),
              child: Column(
                children: [
                  Text("hello "),
                  Text("hello! I'm 345 " * 5, maxLines: 1,overflow: TextOverflow.ellipsis,),
                  //替换默认文本
                  Text("hello 345",style: TextStyle(fontSize: 25, color: Colors.black))
                ],
              ))));
}


TextSpan


如果需要对一个 Text 按照不同部分进行不同的显示,这个时候就可以使用 TextSpan,他代表文本中的一个片段


const TextSpan({
TextStyle style,
Sting text,
List children,
GestureRecognizer recognizer,
});

style 和 text 表示样式和内容,children 是一个数组,也就是说 TextSpan 可以包含其他的 TextSpan,recognizer 用于对该文本片段上用手势进行识别处理


```dart
Widget _richText() {
var textSpan = TextSpan(text: "hello", children: [
    TextSpan(text: "3", style: TextStyle(color: Colors.blueAccent)),
  TextSpan(text: "4", style: TextStyle(color: Colors.black)),
    TextSpan(text: "5", style: TextStyle(color: Colors.green))
]);
  return Text.rich(textSpan);
}


上面使用 Text.rich 方法将 TextSpan 添加到 Text 中,之所以这样做,就是应为 Text 本身就是 RichText 的一个包装,而 RichText 是可以显示多种样式(富文本)的 widget


字体


在 flutter 中使用字体需要两个步骤,首先是在 pubspec.yaml文件中声明,然后通过 textStyle 属性使用字体


flutter:
  fonts:
    - family: Raleway
      fonts:
        - asset: assets/fonts/Raleway-Regular.ttf
        - asset: assets/fonts/Raleway-Medium.ttf
          weight: 500
        - asset: assets/fonts/Raleway-SemiBold.ttf
          weight: 600
    - family: AbrilFatface
      fonts:
        - asset: assets/fonts/abrilfatface/AbrilFatface-Regular.ttf


使用字体


// 声明文本样式
const textStyle = const TextStyle(
  fontFamily: 'Raleway',
);
// 使用文本样式
var buttonText = const Text(
  "Use the font for this text",
  style: textStyle,
);


按钮


Material 组件库中提供了很多按钮组件,如 RaisedButton,FlatButton,OutlineButton,等,他们都是间接或者直接对 RawMaterialButton 组件的包装定制,所以他们大多是属性都和 RawMaterialButton 一样


另外,所有的 Material 库中的按钮都有如下的相同点:


1,按下都会有 “水波纹动画”


2,都有一个 onPressed 属性来设置点击事件的回调,若没有该回调则按钮会处于禁用状态,禁用状态不响应用户点击


各种常见的按钮


class Button extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
      padding: EdgeInsets.all(20),
      child: Column(
        children: [
          //漂浮按钮,默认有阴影和灰色背景
          RaisedButton(
            child: Text("RaisedButton"),
            onPressed: () => print('RaisedButton'),
          ),
            //扁平按钮,默认背景透明不带阴影
          FlatButton(
            child: Text("flatButton"),
            onPressed: () => print('flatButton'),
          ),
          //默认有一个边框,不带阴影且背景透明
          OutlineButton(
            child: Text("OutlineButton"),
            onPressed: () => print('OutlineButton'),
          ),
          //可点击的 Icon
          IconButton(
            icon: Icon(Icons.thumb_up_alt),
            onPressed: () => print('点赞'),
          ),
          //带图标的按钮,通过 icon 构造函数创建带图标的按钮
          RaisedButton.icon(
            icon: Icon(Icons.send),
            label: Text("发送"),
            onPressed: () => print('发送'),
          ),
          FlatButton.icon(
            icon: Icon(Icons.live_help),
            label: Text("疑问"),
            onPressed: () => print('疑问'),
          )
        ],
      ),
    ));
  }
}


有些按钮默认是由 icon 这个构造函数的,同个这个构造可以轻松创建出带图标的按钮,如 RaisedButton 等


自定义按钮外观


按钮的外观可以通过属性来定义,不同的按钮属性都大同小异,以 FlatButton 为例,看一下常用的按钮属性,详细的可以查看 api


const FlatButton({
  ...  
  @required this.onPressed, //按钮点击回调
  this.textColor, //按钮文字颜色
  this.disabledTextColor, //按钮禁用时的文字颜色
  this.color, //按钮背景颜色
  this.disabledColor,//按钮禁用时的背景颜色
  this.highlightColor, //按钮按下时的背景颜色
  this.splashColor, //点击时,水波动画中水波的颜色
  this.colorBrightness,//按钮主题,默认是浅色主题 
  this.padding, //按钮的填充
  this.shape, //外形
  @required this.child, //按钮的内容
})


栗子:定义一个提交按钮


FlatButton(
  color: Colors.blue,
  child: Text("提交"),
  splashColor: Colors.grey,
  highlightColor: Colors.red,
  shape:
      RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
  onPressed: () => print('提交'),
)


Flutter 中 没有提供去除背景的设置,如果需要去除背景,可通过将背景颜色设置为透明来实现,将 color: Colors.blue 替换为 color: Color(0x000000) 即可


FlatButton 是没有 阴影的,这样总会感觉差了点啥,如果需要阴影,可直接使用 RaisedButton 即可


const RaisedButton({
  ...
  this.elevation = 2.0, //正常状态下的阴影
  this.highlightElevation = 8.0,//按下时的阴影
  this.disabledElevation = 0.0,// 禁用时的阴影
  ...
}


通过设置以上属性即可设置阴影,elevation 这个属性会在很多组件中见到,都是用来控制阴影的


图片


在 Flutter 中,我们可以通过 Image 组件来加载并显示图片,Image 的加载源可能是 asset,文件,内存,以及网络


ImageProvider


ImageProvider 是一个抽象类,主要定义了图片获取的接口 load , 从不同的数据源获取图片需要实现不同的 ImageProvider,如 AssetImage 就是实现了 Asset 中加载图片的 ImageProvider,而 NetWorkImage s实现了从网络加载图片的 ImageProvider。


Image


Image widget 有一个必选的参数,对应一个 ImageProvider


加载图片


加载图片等资源可参考此文章


1,加载 assets 中图片


Image(
  image: AssetImage("images/avatar.png"),
  width: 100.0
);
Image.asset("images/avatar.png",
  width: 100.0,
)


2,加载网络图片


Image(
  image: NetworkImage(
      "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4"),
  width: 100.0,
)
Image.network(
  "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4",
  width: 100.0,
)


3,加载本地图片文件


Image.file


4,加载内存图片


Image.memory


参数


const Image({
  ...
  this.width, //图片的宽
  this.height, //图片高度
  this.color, //图片的混合色值
  this.colorBlendMode, //混合模式
  this.fit,//缩放模式
  this.alignment = Alignment.center, //对齐方式
  this.repeat = ImageRepeat.noRepeat, //重复方式
  ...
})


width ,height :设置图片的宽高,若不指定,图片图片会根据当前父容器的限制,尽可能的显示其原始大小,如果只设置了其中的一个,则另一个则会按比例缩放,但是可通过 fit 属性来适应规则


fit:用于在图片的显示空间和图片本身大小不同的时候指定图片的适应模式

image.png

color 和 colorBlendMode :在图片绘制时可以对每一个像素的颜色进行混合处理,color 指定混合色,colorBlenMode 指定混合模式


Image(
  image:NetworkImage("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.houpao.com%2Fdy%2Fdyrs%2F20200711%2F94fb713a5985aa0c0c6f29a20357880f.jpeg&refer=http%3A%2F%2Fimg.houpao.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1614828035&t=cf5430f8cc9a51b7000cde9c9cc30b5a"),
  width: 500,
  height: 300,
  fit: BoxFit.cover,
  color: Colors.red,
  colorBlendMode: BlendMode.difference,
)


repeat:当图片本身大小小于显示空间时,指定图片的重复规则


Image 缓存


Flutter 框架对加载获得图片是有缓存的(内存),默认最大缓存数量是 1000,最大缓存空间为 100M


常用的图片组件


CircleAvatar
CircleAvatar(
backgroundImage:NetworkImage("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.houpao.com%2Fdy%2Fdyrs%2F20200711%2F94fb713a5985aa0c0c6f29a20357880f.jpeg&refer=http%3A%2F%2Fimg.houpao.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1614828035&t=cf5430f8cc9a51b7000cde9c9cc30b5a"),
  radius: 50,
),


圆形图片


FadeInImage
FadeInImage(
  image: NetworkImage("https://gimg2.baidu.com/i......."),
  placeholder: AssetImage("images/icon.png"),
)


如果直接从网络加载图片然后在显示会有些突兀,使用 FadeInImage 之后会在图片的加载过程中显示一个占位符,在图片加载完成之后显示淡入


ICON


在 Flutter 中,可以直接使用 字体图标,它是将图标做成字体文件,然后通过指定不同的字符而现实不同的图片


在字体文件中,每个字符都对应一个码,每个码对应一个显示字形,不同的字体就是指字形不同,及字符对应的字形是不同的。而在 iconfont 中,只是将位码对应的字形做成了图标,所以不同的字符最终就会渲染成不同的图标


在 Flutter 中,iconfont 和图片相比有如下优势


1,体积小


2,矢量的图标,放大不会影响清晰度


3,可以应用文本样式,可以像文本一样改变字体图标颜色,大小对齐等


4,可以通过 TextSpan 和文本混用


使用 Material Design 字体图标


Flutter 默认包含了一套 Material Design 的字体图标库,在 pubspec.yaml 文件中配置如下


flutter:

 uses-material-design: true


看一个简单栗子


String icons = "";
icons += "\uE814";
icons += " \uE200";
icons += " \uE80D";
 Text(
  icons,
  style: TextStyle(
  fontFamily: "MaterialIcons", fontSize: 40, color: Colors.green),
 )


通过上面可以看到,使用图标就像使用文本一样,但这种需要提供每个图标的码点,这点对开发者并不友好,所以 Flutter 封装了 IconData 和 Icon 来专门显示字体图标,上面栗子可使用如下方式实现


Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Icon(Icons.accessible, color: Colors.green),
    Icon(Icons.error, color: Colors.green),
    Icon(Icons.fingerprint, color: Colors.green)
  ],
)


使用自定义图标库


1,导入 ttf 文件


fonts:
  - family: myIcon  #指定一个字体名
    fonts:
      - asset: fonts/iconfont.ttf


2,自定义 icon 类,功能和上面的 Icons 一样,将字体文件中的所有文件都定义为静态变量


class MyIcons{
  static const IconData book = const IconData(
      0xe614, 
      fontFamily: 'myIcon', 
      matchTextDirection: true
  );
  static const IconData wechat = const IconData(
      0xec7d,  
      fontFamily: 'myIcon', 
      matchTextDirection: true
  );
}


3,使用


Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Icon(MyIcons.book,color: Colors.purple,),
    Icon(MyIcons.wechat,color: Colors.green,),
  ],
)


单选按钮和复选框


Material 组件库中提供了单选开关 Switch 和 复选框 Checkbox,他们本身都是继承自 StatefulWidget ,他们本身不会保存当前选择状态,选中状态都是由父组件来管理的。


当 Switch 或者 CheckBox 被点击时,会触发 onChanged 回调,我们可以回调中改变逻辑


class SwitchAndCheckboxTest extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _SwitchAndCheckboxTest();
  }
}
class _SwitchAndCheckboxTest extends State<SwitchAndCheckboxTest> {
  bool _switchSelected = true; //单选状态
  bool _checkboxSelected = true; //复选框状态
  var groupValue = 0; //单选框,默认选中的值
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("单选开关和复选框"),
      ),
      body: Column(
        children: [
          Switch(
            value: _switchSelected,
            activeColor: Colors.red,
            onChanged: (value) {
              setState(() {
                _switchSelected = value;
              });
            },
          ),
          Checkbox(
            value: _checkboxSelected,
            activeColor: Colors.red,
            onChanged: (value) => setState(() => _checkboxSelected = value),
          ),
          Row(
            children: [
              Radio(
                activeColor: Colors.red,
                //此单选框绑定的值
                value: 0,
                //点击状态改变的回调
                onChanged: (value) => setState(() => this.groupValue = value),
                //当前组件中选定的值
                groupValue: groupValue,
              ),
              Radio(
                //此单选框绑定的值
                activeColor: Colors.red,
                value: 1,
                //点击状态改变的回调
                onChanged: (value) => setState(() => this.groupValue = value),
                //当前组件中选定的值
                groupValue: groupValue,
              ),
              Radio(
                activeColor: Colors.red,
                //此单选框绑定的值
                value: 2,
                //点击状态改变的回调
                onChanged: (value) => setState(() => this.groupValue = value),
                //当前组件中选定的值
                groupValue: groupValue,
              )
            ],
          )
        ],
      ),
    );
  }
}
相关文章
|
2月前
|
传感器 缓存 监控
Stream 组件在 Flutter 中的应用场景有哪些?
Stream 组件在 Flutter 中的应用场景有哪些?
173 58
|
2月前
|
UED 开发者
Flutter|常用数据通信组件
Flutter|常用数据通信组件
102 49
|
15天前
Flutter 自定义组件继承与调用的高级使用方式
本文深入探讨了 Flutter 中自定义组件的高级使用方式,包括创建基本自定义组件、继承现有组件、使用 Mixins 和组合模式等。通过这些方法,您可以构建灵活、可重用且易于维护的 UI 组件,从而提升开发效率和代码质量。
111 1
|
15天前
|
开发工具 UED
Flutter&鸿蒙next中封装一个输入框组件
本文介绍了如何创建一个简单的Flutter播客应用。首先,通过`flutter create`命令创建项目;接着,在`lib`目录下封装一个自定义输入框组件`CustomInput`;然后,在主应用文件`main.dart`中使用该输入框组件,实现简单的UI布局和功能;最后,通过`flutter run`启动应用。本文还提供了后续扩展建议,如状态管理、网络请求和UI优化。
92 1
|
18天前
|
Dart UED
Flutter用户交互组件
Flutter用户交互组件
18 2
|
2月前
|
开发工具
Flutter-AnimatedWidget组件源码解析
Flutter-AnimatedWidget组件源码解析
172 60
|
1月前
|
存储 开发框架 开发者
flutter:代码存储&基本组件 (五)
本文档介绍了Flutter中的一些基本组件和代码示例,包括代码存储、基本组件如AppBar的简单使用、可滑动切换的标签栏、TextField的多种用法(如简单使用、登录页面、文本控制器的监听与使用、修饰等),以及如何实现点击空白区域隐藏键盘等功能。通过这些示例,开发者可以快速掌握在Flutter应用中实现常见UI元素的方法。
|
14天前
|
开发工具
Flutter&鸿蒙next中封装一个列表组件
Flutter&鸿蒙next中封装一个列表组件
27 0
|
2月前
|
开发者
Flutter|常用数据通信组件
Flutter|常用数据通信组件
|
2月前
Stream 组件在 Flutter 中的具体使用方法是什么?
Stream 组件在 Flutter 中的具体使用方法是什么?