Zero, preface,

First up, the nuggets author list, please vote for me ~, the text begins:

1. About Icon component

ICONS are indispensable to every application. We can specify an Icon to display through Icon component. You can specify its color and size at will. Compared to pictures, ICONS are not distorted by magnification. But have you ever wondered how the Icon component is implemented? Have you ever wondered what Icons. Android_rounded actually stands for? Do you believe me when I tell you that its essence is words? The next two or three articles in the text interpretation series will cover this Icon component in detail.

2. Other articles in this series
  • The Flutter Text reading 1 | know from source Text component”
  • 2 | the Flutter Text reading Text is how to draw out”
  • The 3 | Flutter Text reading Text component using introduction
  • 4 the Flutter text reading | TextStyle text style interpretation”
  • 5 the Flutter text reading | RichText the use of the rich text (on)”
  • 6 the Flutter text reading | RichText rich text use (in)”
  • The textual interpretation of Flutter 7 | RichText write a code highlighting components”

1. Understand the Icon component

1. The source code implementation of Icon component

Icon is a StatelessWidget component, indicating that it is not built in a way that depends on the implementation of other widgets. In the constructor, several properties are exposed for the user to use, such as color, size, icon data, and so on.

A quick glance at the Icon#build method in the source code shows that it uses RichText internally, which shows that the Icon component is also text by nature. As for the more detailed code, let’s not look at it now and talk about the pre-writing knowledge first.


2. What exactly is IconData

We’ve always used Icons. XXX to get the corresponding icon data, have you ever wondered what that is? It’s actually a static constant in the Icons class of type IconData.

The IconData class is as follows, which mainly requires a codePoint object of type int and a fontFamily of type String. That is, you need to get the corresponding ‘text’ from a font file via an int value.


3. MaterialIcons font position

You can’t help but ask, where is the typeface of the MaterialIcons? If you look at your app’s data, you’ll find the following icon font file. This is where the icon data comes from.

At this point, you might be thinking, I can use my own icon fonts, but I don’t have to use the default ones, because the two add up to over 1m, which is quite a waste of space. You can set uses-material-design to false in pubspec.yaml so that the default icon font is not packaged into the application. Note that some of the Flutter components use these fonts. Just change them to your own when you use them.


4. The connection between Icon and text

From the previous description, you should understand the relationship between Icon and text. Let’s take a look at two small examples. The icon font is itself a font, and if not specified, the default font is used. Write an int as follows. If it is found in the default font, it will be displayed.


Icon fonts are themselves fonts, so they can also be displayed as Text ICONS through their Unicode counterparts.

You can even style ICONS via TextStyle, think of all the fancy stuff in Chapter 4, in font ICONS as well. Because they are essentially the same, they are both drawn based on the RichText component through RenderParagraph. This is the connection and mastery of knowledge.


How to customize icon font

1. Look for icon fonts

My favorite icon site is www.iconfont.cn/. There are tons of ICONS available for download. You can also upload your own ICONS.

Add your favorite icon to the small basket by searching.

You can download the icon directly, but I recommend creating a project to manage later.

In the new Ruby project below, you can add ICONS to it.


2. Modify and download icon fonts

When hovering, you can see the modify button. Click to enter the modify interface.


This is where you can set the icon name and Unicode. Yes, that’s the int in IconData.


Click download after modification.

Where iconfont. TTF is the iconfont file for.

In addition, iconfont. CSS records icon information. So the two elements needed to display an icon font in Flutter are all that is needed.


3. Use icon fonts in Flutter

The first step is to import resources and configure them in pubspec.yaml. Note: file location and file name do not matter, as long as the corresponding.


This way, the downloaded icon font can be used in Flutter. Of course, we can also copy the Icons source code and provide a tolyicon.xxx to retrieve IconData.

class IconShow extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Icon(
      TolyIcon.ruby,
      size: 50,); }}class TolyIcon{
  static const IconData ruby = IconData(0xe64c,fontFamily: 'TolyIcon');
}
Copy the code

At this point, you might say, wow, is this Unicode one by one? It’s a hassle. You don’t know that there is a power called tools, programs that are created to solve this mindless labor. Let’s take a look at how code generates code.


Three, start to write a small tool

1. Implementation analysis

In fact, the principle is very simple, we just need to parse the iconfont. CSS content, to obtain the name of each icon and Unicode code. Then the TolyIcon class can be generated by code, that is, the process of customizing font icon in the future is: download -> copy -> generate.


2.The icon nameandUnicode codeextract

As follows, with re \.icon-(.*?) : matches all icon names.


Through the \ \ “(. *?) “Can be matched to Unicode codes.


3. Use of re in Dart

StringScanner scans and matches strings against the re. Here we get the icon name. In the re above, the matched strings are grouped by (), and _scanner.lastmatch [1] below indicates the first group, which is in parentheses. Group 0 defaults to matching full characters.

main()async{
  
  File target = File('${Directory.current.path}/assets/iconfont/iconfont.css');
  
  String str = await target.readAsString();

  StringScanner _scanner = StringScanner(str);

  while(! _scanner.isDone) {if (_scanner.scan(RegExp(r'\.(.*?) : '))) {
      String word = _scanner.lastMatch[1];
      print(word);
    }

    if(! _scanner.isDone) { _scanner.position++; }}}Copy the code

Similarly, you can get Unicode codes and gather information through two String lists. This extracts the most critical data from iconFont. CSS.

main() async {
  File target = File('${Directory.current.path}/assets/iconfont/iconfont.css');

  String str = await target.readAsString();

  Map<String.String> iconInfo = {};

  List<String> names = [];
  List<String> unicodes = [];
  StringScanner _scanner = StringScanner(str);
	// Scan according to the re
  while(! _scanner.isDone) {if (_scanner.scan(RegExp(r'\.(.*?) : '))) {
      String word = _scanner.lastMatch[1];
      names.add(word);
    }
    if (_scanner.scan(RegExp(r'"\\(.*?) "'))) {
      String word = _scanner.lastMatch[1];
      unicodes.add(word);
    }
    if (!_scanner.isDone) {
      _scanner.position++;
    }
  }

  assert(names.length == unicodes.length);
	/ / synthetic map
  Map<String.String> iconMap = Map.fromIterables(names, unicodes);
  iconMap.forEach((key, value) {
    print('--$key-----$value- ');
  });
}
Copy the code

4. Generate code files

With the information in hand, you can automatically generate code as follows:

String getCode(Map<String.String> iconMap, {String fontName: 'TolyIcon'{})String result = """import 'package:flutter/widgets.dart'; //Power By Zhang Fan-ji-tj -- Generated file. Do not edit.class$fontName {
    $fontName. _ (); "" ";
  iconMap.forEach((key, value) {
    result +=
        """static const IconData $key = IconData( 0x$value, fontFamily: "$fontName"); \n""";
  });
  result += "}";
  return result;
}
Copy the code

Then write it to a file, and running icon_Builder.dart will automatically generate the corresponding DART file.

void save2File(String content,
               {String filePath: 'generate/icon'.String fontName: 'TolyIcon'}) async{
  
  File target = File(path.join(Directory.current.path,'lib',filePath,'$fontName.dart'));
  if(! target.existsSync()){await target.create(recursive: true);
  }
  await target.writeAsString(content);
}
Copy the code

At this point, the basic and core processing is over, but this is just a simple tool. In the next article, you’ll improve this tool to make it easier to use. After all…