Flutter中内置了Material的一些icon资源,但是有些时候这些icon并不能满足我们的需求。 当内置的icon package不能满足需求的时候,我们可以选择使用Image进行替代,当然更好的方法就是自己制作一下定制的icon package。

先来下Flutter中的icon到底是什么:

基本原理

先看一下Material Icon:

static const IconData threesixty = IconData(0xe577, fontFamily: 'MaterialIcons');

实际上Flutter中的Icon使用的是IconFont。

IconFont实际上就是将多个icon打包到一个ttf的字体文件里面去,我们在项目里放置ttf字体文件,然后通过指定的格式(通常是Unicode码)来读取对应的icon,比如上面代码中的0xe577

后面让我们来制作属于自己的icon package吧!

你可以选择直接在项目中添加,也可以单独创建一个package,把icon都放在一个package里。

这里使用单独创建package的方式进行处理:

创建一个icon package

 flutter create --template=package kicons

其中kicons是包名,用来区分各种package。

找到并添加iconfont中的ttf文件

iconfont的资源在网上还是比较多的。 在国内可以使用:阿里巴巴矢量库图标 如果可以科学上网,自行Google,可以使用:IconFont

image.png

然后在package的pubspec.yaml文件中指定ttf文件位置:


flutter:
  fonts:
    - family: Emoji
      fonts:
        - asset: fonts/emoji.ttf
    - family: Aliyun
      fonts:
        - asset: fonts/aliyun.ttf

我这里使用了两个字体文件,一个是表情Icon,一个是阿里云Icon。

从ttf文件中读取信息创建IconData

这个时候可以在package的lib/文件下创建dart文件,从ttf中读取信息,然后创建IconData:

import 'package:flutter/widgets.dart';
import 'package:kicons/kicons.dart';

/// 表情Icon
class EmojiIcon {
  static const String _family = "Emoji";

  EmojiIcon._();

  static const IconData angry =
      IconData(0xeaf4, fontFamily: _family, fontPackage: package);
  static const IconData astonished =
      IconData(0xeaf5, fontFamily: _family, fontPackage: package);
  static const IconData confounded =
      IconData(0xeaf6, fontFamily: _family, fontPackage: package);
  static const IconData confused =
      IconData(0xeaf7, fontFamily: _family, fontPackage: package);
  static const IconData crying =
      IconData(0xeaf8, fontFamily: _family, fontPackage: package);
  static const IconData dizzy =
      IconData(0xeaf9, fontFamily: _family, fontPackage: package);
  static const IconData expressionless =
      IconData(0xeafa, fontFamily: _family, fontPackage: package);
  static const IconData heart_eyes =
      IconData(0xeafb, fontFamily: _family, fontPackage: package);
  static const IconData laughing =
      IconData(0xeafc, fontFamily: _family, fontPackage: package);
  static const IconData nerd_smile =
      IconData(0xeafd, fontFamily: _family, fontPackage: package);
  static const IconData open_mouth =
      IconData(0xeafe, fontFamily: _family, fontPackage: package);
  static const IconData rage =
      IconData(0xeaff, fontFamily: _family, fontPackage: package);
  static const IconData rolling_eyes =
      IconData(0xeb00, fontFamily: _family, fontPackage: package);
  static const IconData sad =
      IconData(0xeb01, fontFamily: _family, fontPackage: package);
  static const IconData simple_smile =
      IconData(0xeb02, fontFamily: _family, fontPackage: package);
  static const IconData slightly_smile =
      IconData(0xeb03, fontFamily: _family, fontPackage: package);
  static const IconData smirk =
      IconData(0xeb04, fontFamily: _family, fontPackage: package);
  static const IconData stuck_out_tongue =
      IconData(0xeb05, fontFamily: _family, fontPackage: package);
  static const IconData wink_smile =
      IconData(0xeb06, fontFamily: _family, fontPackage: package);
  static const IconData worried =
      IconData(0xeb07, fontFamily: _family, fontPackage: package);

  /// 返回IconData列表
  static List<IconData> toList() {
    final result = <IconData>[];
    for (int i = 0xeaf4; i <= 0xeb07; i++) {
      result.add(IconData(i, fontFamily: _family, fontPackage: package));
    }
    return result;
  }
}

需要注意的是IconData中必须指定fontFamily和fontPackage

Unicode码可以从下载下来的文件中找到html文件查看(比如阿里的IconFont),也可以在对应的css文件中查看:

image.png

image.png

到这里你的icon package就创建成功了,后面就看看使用的效果吧:

image.png

源码

https://github.com/jiangkang/flutter-system/tree/master/kicons