Each problem set is set to about ten records. Most of them are my own situations and solutions encountered in the actual development of Flutter, which will deepen my thinking and thoughts about the problems I faced in the development process and make it easy to refer to for backup in the future. I also hope to help you.

Chinese and English words display different heights

There is a problem with the UI layout where the height of the Chinese and English Text is not consistent when you set the Padding for the Text. No wonder designers keep picking on me. I finally know what the problem is.The solution is actually very simple and you can just set the height of TextStyle to 1.

TextStyle(
    fontSize: 15,
    fontFamily: "",
    height: 1.)Copy the code

In practice, it will be found that the Chinese display will exceed the actual height, but here we want to maintain a uniform height to facilitate the setting of the external border, so the excess part does not affect the normal use.

Sliders work differently on Android and iOS

Because of the different UI specifications of Android and iOS platforms, the interaction of sliding components is different. For example, on The Android platform the boundary is a ripple animation interaction while on the iOS platform the boundary is a rebound damping effect. Instead of SingleChildScrollView’s physics, developers want to use Either ClampingScrollPhysics (Android) or BouncingScrollPhysics (iOS) for uniform interaction effects.

SingleChildScrollView(
    physics: BouncingScrollPhysics(), ///ClampingScrollPhysics
)
Copy the code

Designer please don’t cut so many ICONS

Android ImageView has a property called Tint that allows you to render an image in color, but only if the image is monochrome. The color of Iamge in Flutter also plays the same role. On one hand, it can reduce the amount of cutting and on the other hand, it can facilitate the development of late color mixing. Before, some ICONS had different colors in the clickable and non-clickable renderings. The UI cut two copies of the same image to me, but rendering the image color failed because the cut image was not monochrome.

Image.asset(
   "res/drawable/ic_circle_company.png",
   height: 40,
   width: 40,
   color:Colors.red,
),
Copy the code

Monochrome cuts can be changed by setting different colors, so stateful ICONS should be cut in monochrome and left to the developer.

It’s not really a development problem, but it’s a meaningful problem in the development process, so I want to keep a record of whether we should try to minimize the points of repetition and optimization. In addition, it reduces the usage of redundant resources and reduces the size of application packages.

Don’t just use pop for routing

timer = Timer.periodic(Duration(milliseconds: 100), (timer) { if (num == 0) { timer.cancel(); Navigator.of(context).pop(); bus.emit(EventBus.privateEvent); } else { num--; setState(() {}); }});Copy the code

As shown in the preceding code, the flicker page counts down the close logic, because there are other asynchronous business logic such as the pop-up login page. When the countdown ends and navigator-of (context).pop is called, the login page at the top of the routing stack exits. As a result, the routing stack page has a problem and cannot be manually logged out of the pop-up page and cannot be accessed to the home page (the exit prohibition has been set on the pre-pop-up page). So use removeRoute to close the current page.

To learn more about Flutter routing, see the Routing Features section of the Flutter combat.

timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
  if (num= =0) {
    timer.cancel();
    Navigator.of(context).removeRoute(ModalRoute.of(context));
    bus.emit(EventBus.privateEvent);
  } else {
    num-; setState(() {}); }});Copy the code

TextField is killing you

Use TextField problems in special cases, such as nesting Textfields in Row with Expanded constraint widths.

Display layout failure

Some special cases can cause a layout build to fail, such as an error when adding a Row wrapper with an outer layer.

Row(
  children: <Widget>[
    Image.asset("res/img/ic_star.png"),
    TextField(
        cursorColor: Colors.grey,
        decoration: InputDecoration(
          hintText: "HHHHHH",
          border: InputBorder.none,
          contentPadding: EdgeInsets.all(0),
          isDense: true))])Copy the code

An InputDecorator, which is typically created by a TextField, cannot have an unbounded width

In this case, you can only solve this problem by nesting Expanded on the outer layer of TextField.

Row(
  children: <Widget>[
    Image.asset("res/img/ic_star.png"),
    Expanded(
      child: TextField(
        cursorColor: Colors.grey,
        decoration: InputDecoration(
          hintText: "HHHHHH",
          border: InputBorder.none,
          contentPadding: EdgeInsets.all(0),
          isDense: true)))])Copy the code

Get focus on the soft keyboard

Usually the input box default to get the focus of the soft keyboard.

TextField(
  autofocus: true.)Copy the code

However, there are also cases where the default focus of the input box is not obtained and the soft keyboard is not displayed. In this case, you can set the focusNode to achieve this.

SchedulerBinding.instance.addPostFrameCallback((_) {
   FocusScope.of(context).requestFocus(_focusNode);
});
TextField(
   autofocus: true,
   focusNode: _focusNode,
)
Copy the code

Finally, remember to remove focus and retract the soft keyboard when you exit the page

FocusScope.of(context).requestFocus(FocusNode());
Copy the code

Input box display height problem with other components

Because the native input box style does not meet the daily business development, the custom input box uses the Container nested input box to add the outer border style. The following code causes the input box and other components to be at different heights.

Container(
  margin: EdgeInsets.symmetric(horizontal: 10),
  padding: EdgeInsets.symmetric(horizontal: 10),
  alignment: Alignment.centerLeft,
  height: 30,
  decoration: new BoxDecoration(
    color: Colors.blueGrey,
    borderRadius: new BorderRadius.circular(4),
  ),
  child: Row(
    crossAxisAlignment: CrossAxisAlignment.center,
    children: <Widget>[
      Image.asset(
        "res/img/ic_star.png",
        width: 10,
      ),
      Expanded(
        child: TextField(
          cursorColor: Colors.grey,
          autofocus: true,
          decoration: InputDecoration(
              hintText: "HHHHHH",
          ),
          showCursor: true,
          textInputAction: TextInputAction.search,
        ),
      ),
    ],
  ),
),
Copy the code

Finally set the following code to solve the problem, isDense to true, contentPadding is set to 0.

TextField(
  cursorColor: Colors.grey,
  decoration: InputDecoration(
      hintText: "HHHHHH",
      border: InputBorder.none,
      contentPadding: EdgeInsets.all(0),
      isDense: true,
      hintStyle: TextStyle(fontSize: 15)),
  style: TextStyle(fontSize: 15),
  showCursor: true,
),
Copy the code

The network request failed to capture packets

The test student said that THE application I developed could not capture packets, and wanted to monitor the test data and troubleshoot problems, which caused confusion. The fact that web requests were developed with Flutter did not capture packets directly by default.

  • 1.
  • 2.

Flutter upgrade to V1.12.3 iOS package size issue

The previous development had been using The FlutterV1.9 version, because FlutterBoost had been upgraded to support V1.12.3- Hotfix, so I wanted to do my best to update the Flutter. The previous upgrade went smoothly without any problems and basically nothing needed to be changed in the configuration, until something happened during iOS packaging. The original package size of iOS was about 30M, but now the package size is about 100M.

After making sure I packaged it for release, I quickly looked at the issue on Github, and I wasn’t the only one who had this problem. The problem was not a bug with the Flutter but rather the LLVM IR (Bitcode) that was included in the Flutter engine since version 1.12 caused the packet size to change.

After you upload the ipA file to App Store Connect, the platform will automatically compress the installation package to a normal size. However, I still don’t know how to compress the package size without uploading it to the store. I will study it later when I have time.

  • Issue (1) with the same problem
  • Issue (2) with the same problem
  • The official documentation

Page route return value processing

Page return has a sideslip operation in addition to the return key of the Appbar. In the sideslip operation return pass the parameters through the route also need to intercept the sideslip return operation custom route eject operation pass the required parameters. Here we use the WillPopScope component to set the onWillPop return value to Future.value(false), and then customize the return value. So pay special attention to this if all business requirements require a return value. But you can ignore this problem if you use redux global state management estimates 😂

But on the other hand, passing parameters through routing is not particularly sour and cool. In some special cases, many cases need to be considered. Perhaps global state management is indeed a better alternative.

PS: At the same time, WillPopScope is also suitable for loading to prohibit sideslip exit and other operations

onWillPop: () {
    Navigator.of(context).pop({
      "code": industryCode,
      "filter": vm.filters.length > 0 ? vm.filters : ""});return Future.value(false);
  },
Copy the code

IPhoneX bottom black stick stick fit

The bottom navigation bar supports the iOS bottom bar by default, but writing your own layout can be problematic. For example, using Stack at the bottom of the Position component makes it more likely that the component display will be blocked by a horizontal bar.

Scaffold(
  appBar: AppBar(),
  body: Container(
    color: Colors.green,
    child: Stack(
      children: <Widget>[
        Positioned(
          bottom: 0,
          child: Text("LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL")))))))))))Copy the code

Looking at the BottomNavigationBar source code, you’ll find the following code that uses MediaQuery. Of (context).padding to get the bottom margin of the screen and sets the padding in the BottomNav layout to avoid being blocked by the horizontal bar.

  // Labels apply up to _bottomMargin padding. Remainder is media padding.
    final double additionalBottomPadding = math.max(MediaQuery.of(context).padding.bottom - widget.selectedFontSize / 2.0.0.0);
/// Omitted some useless code. Padding( padding: EdgeInsets.only(bottom: additionalBottomPadding), child: MediaQuery.removePadding( context: context, removeBottom:true,
    child: _createContainer(_createTiles()),
  ),
 ),
Copy the code

Therefore, ios bar adapting requires adding mediaQuery.of (context).padding.bottom spacing to the component at the bottom. Of course, for the iPhoneX, the bottom value is greater than 0, for the iPhone6, the bottom value is 0, and for android (depending on the phone model and model).