An overview of the

  • This article mainly introduces how to use Flutter to build the function of wechat home page, describes in detail the technology used to realize this function, and how to solve problems encountered in Flutter. Although this function seems simple at first glance, it is found that the function logic is complex and the internal details are relatively high when carefully studied. Of course, it covers most of the knowledge points of Flutter. I believe that by implementing this function, learners will have a better grasp of Flutter knowledge.

  • The author mainly achieved the following functions of the wechat home page:

    • The message’s sideslip is deleted
    • Drop down shows applets
    • Click navigation bar + button to pop up the menu bar
    • Click on the search box to pop up the search page
  • I hope that by realizing the function points of 👆 above, beginners can be helpful in learning Flutter. Of course, I will tell you everything I know about Flutter, sort out the problems in the process of Flutter practice, and summarize the solutions to solve the problems so that you can know how Flutter is and why. Hope can cast jade lead brick, ferrying sentient beings, if there is a mistake, also hope to be corrected.

  • Source code address: flutter_wechat

rendering

GIF WeChat pp. The menu bar
Small program Search page

Knowledge reserves

  • Stack + Positioned
  • The Transform. Translate (translation),The Transform. Scale (enlarge),Opacity: Set the Opacity of the child component
  • Scroll monitor and control
  • 21. Animation module use (animatedanimation, AnimatedOpacity, ScaleTransition)
  • Status Management Provider
  • Listen for the keyboard to bounce up
  • Get the size of a Widget using GlobalKey

function

First, delete the side slide of the message

This function is mainly realized using flutter_slidable plug-in. The specific implementation process and detailed treatment experience are similar to my previous article about how to implement the function of Flutter for wechat — contacts. I will not repeat the details here. If you are interested, please move by yourself.

Two, drop down display small program

The function of pull-down display of small programs and pull-up hiding of small programs after display is quite complicated in the implementation process of Flutter, which covers most of the essential knowledge points. Therefore, the author will detail the pits encountered in the implementation process of Flutter and the methods to fill the pits.

  • The UI structures,

Because in the drop-down process, the content page, the navigation bar, the three spots and the small program will all be presented one on top of another, so Stack + Positioned position is adopted in the whole wechat page. For details of THE UI-construction, please refer to the source code, which will not be repeated here, the exact pseudocode is as follows:

/// Build child Widget _buildChildWidget() {return Container(constraints: BoxConstraints. Expand (), color: Style. PBackgroundColor, child: Stack(overflow: overflow. visible, // < widgets > [/ / navigation/page/content / / three point component / / small program / / menu],),); }Copy the code

Of special note: the Stack of neutrons is added in sequence, the rearmost is on the top, she does not have the concept of z-index like the version in the Web.

  • Functional analysis

We can compare your mobile phone wechat home page, the function of the drop-down show small program actually covers the logical processing of the two processes, the drop-down show small program and the drop-down hide small program, of course, this is a real closed loop, there will be hidden display. Here the author will only take the drop-down logic as an example to explain in detail the logical analysis and detail processing. Pull up logic and you can do it backwards.

❗️ drop-down logic

  1. As I scroll down the content page with my finger,The navigation barThe top of the finger will pull downOffset (offset)The offset distance is equal to the pull-down distance.
  2. I’m going to scroll down toCritical point ① = 60When, aA ballGradually zoom in,Amplification factor (Scale) = 0whenOffset > critical point ①When,Scale is going to get bigger; On the other hand,scale = 0
  3. I’m going to scroll down toCritical point ② = 90In this process,A ballWill be magnified to the maximum (scale = 2). namelyOffset: critical point ① --> critical point ②.scale: 0 --> 2. Following the
  4. To continue the drop-downCritical point ③ = 130In this process,A ballTwo balls are generated, one of which is gradually shifted left to the maximum and one of which is gradually shifted right to the maximum, and is itself scaled to the original value (scale = 1).
  5. I’m going to scroll down toCritical point ④ = 180In this process,Three goalsTransparency (opacity) from1.0 --> 0.2Changes, and applets module transparency (opacity) from0 - - > 0.5Change and its scaling ratio (scale) to (Scale = 0.4).
  6. Continue to drop downOffset > critical point ④When,Three ballsThe transparency of is equal to0.2, and the applets module transparency is identical to0.5And its scaling ratio (scale) constant for (Scale = 0.4).

Note: in the above 👆 process, the user’s finger is in the dragging state, that is, the finger does not leave the screen. Let me explain what happens when your finger leaves the screen.

  1. At the moment of finger release, determine the pull-down offsetoffsetIf more thanCritical point ② = 90, if greater than, the small program module is displayed, otherwise, the small program module is hidden.
  2. The bottom of the navigation bar is shifted to the bottom of the screen, the top of the content page is shifted to the bottom of the screen, and the transparency of the applet changes from0.5 -- -- > 1And the scaling ratio is from0.4 -- -- > 1The bottom navigation bar is hidden.
  • Function implementation

Through the above functional analysis, we are not difficult to give the code implementation. But to be clear, we have to rely on one very important piece of data — the scroll offset — for the entire pull-down or pull-up process, so we have to listen for the list to scroll, and then do the whole UI logic based on the offset. For more information on scrolllistening, see 👉 scrolllistening and Control.

There are two schemes for scrolllistening, and the key codes are as follows:

_controller.addListener(() {final offset = _controller.offset; / / processing _handlerOffset (offset); }); // Solution 2 NotificationListener(onNotification: (ScrollNotification notification) {// Refreshingdo nothing...
    if (_isRefreshing || _isAnimating) {
       return false;
    }
    // offset
    final offset = notification.metrics.pixels;
    if (notification is ScrollStartNotification) {
      if(notification.dragDetails ! = null) { _focus =true; }}else if(Notification is ScrollUpdateNotification) {// Can you refresh? Final bool canRefresh = offset <= 0.0? (-1 * offset >= _topDistance ?true : false)
          : false;
      if (_focusState && notification.dragDetails == null) {
          _focus = false; _isRefreshing = canRefresh; }}else if (notification is ScrollEndNotification) {
       if (_focusState) {
         _focus = false; }} // handle _handlerOffset(offset);return false;
},
Copy the code

There are two major differences between listening for a rolling event through NotificationListener and listening for a rolling event through a ScrollController:

  • throughNotificationListenerCan be changed from scrollable components towidgetCan listen anywhere between the roots. whileScrollControllerThis can only be done if it is associated with a specific scrollable component.
  • Different information is obtained after receiving a rolling event;NotificationListenerWhen a scroll event is received, the notification carries the current scroll position andViewPortSome of the information, whileScrollControllerYou can only get the current scroll position.

Of course, another important reason why I use NotificationListener to listen for rolling events is whether the finger is in the drag state, i.e. Notificationdragdetails! = null. In order to make clear the moment when the user finger leaves the screen, get the offset at this time, in order to determine whether the small program module display.

Once we listen for the list scroll offset, the page only needs to change according to the _offset change. The offset is handled as follows:

Void _handlerOffset(double offset) {// calculateif(offset <= 0.0) {_offset = offset * -1; }else if(_offset ! = 0) {_offset = 0; } // this is requiredif(_isRefreshing && ! _isAnimating) {// Refresh and not animate // Animating _isAnimating =true; // animation time _duration = 300; / / final resting position _offset = ScreenUtil screenHeightDp - kToolbarHeight - ScreenUtil. StatusBarHeight; Of <TabBarProvider>(context, listen:false).setHidden(true);
    setState(() {});
    return; } _duration = 0; // Non-refreshed and non-animated stateif(! _isAnimating) {setState(() {}); }}Copy the code

Since the UI layout varies depending on the _offset change, it is important to emphasize two states in the pull-down process:

  • Drag state (fingers not leaving the screen)
  • Non-drag state (finger off screen)

In the dragging state, the top of the navigation bar shifts with the change of _offset, which simply changes the top attribute of tourists, with the pseudo-code as follows:

Positioned(
    top: _offset,
    //...
)
Copy the code

When the UI in drag state is finished, that is: if the moment of finger release, _offset is greater than the critical point, then the navigation bar, content page… Parts will be silky transition to the bottom, here must be clear, in order to achieve the function of silky transition, must be inseparable from the support of animation. In this state, if the method of modifying the top attribute of Positioned tourists is still extended, it would appear stiff in the process, so the animation component of the Flutter, AnimatedPositioned, is used instead of offering tourists. The pseudocode is as follows:

AnimatedPositioned(
    top: _offset,
    duration: Duration(milliseconds: 300),
    //...
)
Copy the code

Although the unstretched position of the navigation bar provides a convenient gap between the bottom and the corner, in the trailing position, the animatedwould give a very small space, which is not very desirable. In order to give balance to both of these states, the author uses the duration property of animatedtraveler to achieve, that is, in the tug, _duration=0; Release and greater than the critical point, _duration=300. The pseudocode is as follows:

AnimatedPositioned( top: _offset, duration: Duration(milliseconds:(_isRefreshing ? 300:0), //...)Copy the code

Of course, I think one of the more interesting features of the pull-down process is the three-ball logic. Of course, in combination with the above functional analysis, the implementation is relatively simple, mainly using Opacity, transform.translate and transform. scale components, which are frequently used, so it is necessary for everyone to master them. Here, the author gives the key code logic, which you can see at a glance:

// Final double stage1Distance = 60; // Final double stage2Distance = 90; // Final double stage3Distance = 130; // Final double stage4Distance = 180; Final top = (offset + 44 + 10-6) * 0.5; // Double scale = 0.0; double opacityC = 0; // Double translateR = 0.0; double opacityR = 0; // Double translateL = 0.0; double opacityL = 0; final cOffset = (offset <= stage4Distance) ? offset : stage4Distance;if(offset > stage3Distance) {// stage4 1-0.2 final step = 0.8 / (stage4distance-stage3distance); double opacity = 1 - step * (cOffset - stage3Distance);ifOpacity < 0.2) {opacity = 0.2; } // Phase III: keep scale 1 opacityC = opacity; scale = 1; OpacityR = opacity; translateR = 16; OpacityL = opacity; translateL = -16; }else if(offset > stage2Distance) { final delta = stage3Distance - stage2Distance; final deltaOffset = offset - stage2Distance; // Final stepC = 1 / delta; // Final stepC = 1 / delta; opacityC = 1; scale = 2 - stepC * deltaOffset; // Right point stage II: slowly shift 0 -> 16 final stepR = 16.0 / delta; opacityR = 1; translateR = stepR * deltaOffset; Final stepL = -16.0 / delta; opacityL = 1; translateL = stepL * deltaOffset; }else if(offset > stage1Distance) { final delta = stage2Distance - stage1Distance; final deltaOffset = offset - stage1Distance; Final step = 2 / delta; opacityC = 1; scale = 0 + step * deltaOffset; }Copy the code

In the pull-down process, the small program module only needs to control its opacity and the scale coefficient of the content page; in the pull-up process, it only needs to control its opacity. In general, it is So Easy ~. Of course, the dragging state of the finger needs to be considered in the whole process, that is, animation needs to be added. Such as: transparency animation, zoom animation. The corresponding animation component used here is as follows,

  • AnimatedOpacityalternativeOpacityAdd transparency animation
  • ScaleTransitionalternativeTransform.scaleAdd zoom animation

On its specific use, we also please read the source code ha, no further details. Of course, small program module I feel more details of the place, is the UI layout. Because to achieve a pull up slide, and small program content page also support pull up. So it involves nesting slides, listViews nested listViews. Because the outermost layer of the ListView’s maxScrollExtent: maximum scrollable length is handled in more detail, the outermost layer of the ListView’s maxScrollExtent: maximum scrollable length is handled in more detail. Ideally, drag your finger from the bottom of the screen up to the top of the screen so that the top of the navigation bar reaches the top of the screen, then maxScrollExtent = 2 * the height of the screen – the height of the status bar – the height of the navigation bar, and if the height of the applet content page is known (assume: 480). So the outermost ListView should not only nest a ListView(height 480), but also nest an empty (placeholder) part (SizedBox), and the height of the empty part is:

Placeholder height = 2 * screen height - status bar height - navigation bar height - 480;Copy the code

Of course, the pull-up and the pull-down are similar, but also listen to the scroll, handle the scroll offset, the pull-up offset processing code is as follows:

Void _handleAppletOnScroll(double offset, bool dragging) {if (dragging) {
    _isAnimating = false; _duration = 0; / / calculate height _offset = ScreenUtil. ScreenHeightDp - kToolbarHeight - ScreenUtil. StatusBarHeight - offset; // Fixed Bug: If I am dragging, it is already 0.0; Then non-dragging is also 0.0, which leads to evensetState(() {}); // The minimum value is 0.001_offset = Max (0.0001, _offset);setState(() {});
    return;
  }
  if(! _isAppletRefreshing && ! _isAnimating) {// Start animation _duration = 300; // Calculate the height _offset = 0.0; _isAppletRefreshing =true;
    _isAnimating = true;

    setState(() {}); }}Copy the code

Small module content page, also has a relatively novel small function: is the default every time come in small program module is hidden search box, only when the user pull down a diudiu, finger release, will automatically see the search box, and the user pull a diudiu, finger release, will also automatically hide the search box. The realization of this function mainly involves two knowledge points: monitor rolling and control rolling. There are two common apis for controlling scrolling:

  • jumpTo(double offset)
  • animateTo(double offset,...)

These two methods are used to jump to a specified location. The difference is that the latter performs an animation while the former does not.

So, we only need to scroll after the end, by whether to pull down or pull up, to determine whether to display the search box. The key codes are as follows:

return NotificationListener(
  onNotification: (ScrollNotification notification) {
    if (notification is ScrollStartNotification) {
      if(notification.dragDetails ! = null) {/ / record starting drag _startOffsetY = notification. Metrics. The pixels. }}else if (notification is ScrollEndNotification) {
      final offset = notification.metrics.pixels;
      if(_startOffsetY ! = null && offset ! = 0.0&&offset < ScreenUtil().setheight (60.0 * 3)) {// ScreenUtil < ScreenUtil()if(offset - _startOffsetY) < 0) {// pull future.delayed (Duration(milliseconds: 10), () async { _controllerContent.animateTo(.0, duration: Duration(milliseconds: 200), curve: Curves.ease); }); }else{// pull-up // Fixed Bug: Remember to delay a drop, otherwise will report an error Why? Future.delayed( Duration(milliseconds: . 10), () is async {_controllerContent animateTo (ScreenUtil () setHeight (60.0 * 3), duration, duration (milliseconds: 200), curve: Curves.ease); }); } // set this to null _startOffsetY = null; }return true; // Stop bubbles}, child: ListView()}Copy the code

But if we call jumpTo(Double offset) or animateTo(double offset…) immediately after we finish scrolling In fact, it does not work, only to delay a lost time, and then to control the rolling of the line, here THE author is meng force for a long time, but also hope predestined people to answer it (comment) ~.

One more feature: when you drop down, you need to hide the tabBar at the bottom; When pull-up releases, the bottom tabBar needs to be displayed. This is where state management comes in. Here the main author with the help of provider to achieve. The key codes are as follows:

Class TabBarProvider with ChangeNotifier {// Display or hide bool _hidden =false;
  bool get hidden => _hidden;

  void setHidden(bool hidden) { _hidden = hidden; notifyListeners(); }} // UI layerreturn Consumer<TabBarProvider>(
  builder: (context, tabBarProvider, _) {
    returnScaffold( appBar: null, body: list[_currentIndex], // iOS bottomNavigationBar: tabBarProvider.hidden ? null : CupertinoTabBar( items: myTabs, onTap: _itemTapped, currentIndex: _currentIndex, activeColor: Style.pTintColor, inactiveColor: Color(0xFF191919), ), ); }); // Hide provider. of<TabBarProvider>(context, listen:false).setHidden(true); Provider. Of <TabBarProvider>(context, listen:false).setHidden(false);

Copy the code

At this point! The function point of the drop-down display small program is the above, of course, some UI building and logical processing is still more complex, as long as you think carefully, logical clarity, it is nothing rare.


Click + button to pop up the menu

The implementation of this function is also full of details, because the display and hiding need to use animation, the main use of AnimatedOpacity animation and ScaleTransition animation components.

  • 1, click the navigation bar + button, the menu gradually display (transparency animation). 2. After displaying the menu bar, click the blank area of the page, and the menu will gradually zoom to the upper right corner to hide (Transparency animation + Zoom animation)

  • The key codes are as follows:

@override
void initState() { super.initState(); _controller = new AnimationController(vsync: this, duration: duration (milliseconds: 200)); _animation = new CurvedAnimation(parent: _controller, curve: Curves.easeInOut); / / to monitor animation _controller. AddStatusListener ((AnimationStatus status) {/ / got to the end state To roll back to the start stateif(status = = AnimationStatus.com pleted) {/ / is ended, and reset to the current _controller. The reset ();setState(() {}); }}); } @override Widget build(BuildContext context) {if(widget.show) {// Only after display should the animation be scaled _shouldAnimate =true;
    _scaleBegin = _scaleEnd = 1.0;
  } else{_scaleBegin = 1.0; _scaleEnd = 0.5; // Is in the beginning phase and requires animationif (_controller.isDismissed && _shouldAnimate) {
     _shouldAnimate = false;
      _controller.forward();
    } else{_scaleEnd = 1.0; }} // Fixed Bug: Offstage must wait until the zooming animation is finished before setting totrueOtherwise, you can't see the zoom animationreturnOffstage( offstage: ! widget.show && _controller.isDismissed, child: InkWell() }Copy the code

Combined with the 👆 code, it is particularly important to note that when hiding the menu, a judgment logic should be added. Only when the menu has been shown and the animation state is in the beginning state, will the zoom animation be carried out, and the animation needs to be reset to the initial state after completion, so as to continue to zoom next time. Of course, be sure to hide the entire menu (mask + content) after the zoom animation is over, otherwise you won’t see the zoom animation, because the mask will be hidden before the content.

4. Click the search box to pop up the search page

The realization of Flutter still covers several important knowledge points, which are commonly used in daily development. Since the author is also learning Flutter, many knowledge points are not comprehensive enough, which leads to some difficulties in the implementation process. Here, the author provides detailed knowledge points as follows:

  • Get the size of a Widget using GlobalKey

  • 1. Animation of the toy

  • Listen for keyboard height changes

  • 1. Click the Search box on wechat home page, the Search and cancel buttons will move to the left at the same time, and the AppBar and Search pages will move up at the same time, and the keyboard will pop up; The wechat content page and the bottom TabBar are hidden, and the search page is displayed. Press and hold the speak button to pop up and follow the keyboard to pop up. 2. Click the cancel button of the Search page, the Search and cancel buttons will move to the right at the same time, and the AppBar and Search page will move down at the same time, and the keyboard will fold up; Wechat content page and bottom TabBar display, search page hidden, clear the search content, press and hold the talk button to follow the keyboard fold up and fold up.

  • The UI structures,

UI mainly includes search box (SearchBar) and search page (SearchContent) construction, although the overall is not difficult, but full of details. Because consider translation (left, right) animation and to monitor the keyboard height changes in the UI, so the overall internal widget layout are using Stack + Positioned/AnimatedPositioned to build, of course, road ten million, realize the first. Here, take SearchBar as an example, its internal widget layout, pseudo-code is as follows:

Stack( children: <Widget>[// white background box animatedtoy (), // into the box, // 🔍 search button animatedtoy (), // Cancel the button animatedtoy ()])Copy the code
  • Function implementation

🔍 Search is implemented in the center. Although the UI center may be simple to achieve, such as: Stack alignment: AlignmentDirectional. Center, and the Row mainAxisAlignment: MainAxisAlignment center, and the alignment of the Container: AlignmentDirectional. Center, etc… However, considering the addition of animation and the silky effect of animation, we have to adopt the form of Stack layout and the alignment of Stack: AlignmentDirectional center, to center and AnimatedPositioned must set the left and right ` ` null, or cannot be centered, pseudo code is as follows:

Stack (alignment: AlignmentDirectional center, children: < widgets > [/ / 🔍 search button AnimatedPositioned (child: ` 🔍 search `, left: null, top: 0, bottom: 0 ), ] )Copy the code

Although the above does achieve 🔍 search center, and effortless. If you click the 🔍 search button, assume edit mode, that is, _isEdit = true; And the 🔍 search button needs to be inserted into the left corner of animatedtoy left: 0, so you could easily write the following code:

Stack (alignment: AlignmentDirectional center, children: < widgets > [/ / 🔍 search button AnimatedPositioned (child: ` 🔍 search `, left: _isEdit? 0 : null, top: 0, bottom: 0 ), ] )Copy the code

Sure, the logic is pretty smooth, but once it’s running, you’ll be stunned, because if you click the 🔍 search button, the 🔍 search button will zoom to the left, with none of the silkiness of the ideal left-shift. Lateral verification ideal 34D(very plump), reality on A(very skinny) truth. The reason is actually that the left of the animatedtoy is a transition from null -> 0, and if the left has a value, there is an animation of the transition to 0.

To move left and enjoy the stretch, the left of animatedtoy must have a value in the unedited (_isEdit = false) sequence, and in order to centralize the 🔍 search, the left must satisfy: Left = (width of screen – 🔍 width of search) * 0.5, so the first task is to obtain the size of 🔍 search button, use GlobalKey to obtain, about GlobalKey use, please baidu. The pseudocode is as follows

GlobalKey _textKey = new GlobalKey(); Double _searchIconLeft = 0; Override Widget build(BuildContext context) {override Widget build(BuildContext context) { Widgetutil. asyncPrepare(context,true, (Rect rect) {
    final RenderBox box = _textKey.currentContext.findRenderObject();
    final Size size = box.size;
    setState(() {_searchIconLeft = (rect.width -16.0-size-width) *.5; });print(${rect.size} $size ${size.width} $_searchIconLeft');
  });
   returnStack (alignment: AlignmentDirectional center, children: < widgets > [/ / 🔍 search button AnimatedPositioned (child: '🔍 search', left: _isEdit? 0: _searchIconLeft, top: 0, bottom: 0),]; }Copy the code

The 🔍 search button is perfectly centered and moves to the left to create a vertical slide. However, there is a jump Bug when initializing for the first time because _searchIconLeft is initialized to 0, resulting in _searchIconLeft being computed in widgetutil.asyncprepare (). _searchIconLeft transitions from 0 to greater than 0, causing a jump Bug. In the initial state, left is null. After rendering, set left to _searchIconLeft, and display 🔍 search button after rendering. The final pseudocode is as follows

GlobalKey _textKey = new GlobalKey(); Double _searchIconLeft = 0; Bool isprepared = bool isprepared =false; Override Widget build(BuildContext context) {override Widget build(BuildContext context) { Widgetutil. asyncPrepare(context,true, (Rect rect) {
    final RenderBox box = _textKey.currentContext.findRenderObject();
    final Size size = box.size;
    setState(() {
      _isPrepared = true; _searchIconLeft = (rect.width -16.0-size-width) *.5; });print(${rect.size} $size ${size.width} $_searchIconLeft');
  });
   returnStack (alignment: AlignmentDirectional center, children: < widgets > [/ / 🔍 search button AnimatedPositioned (child: Offstage(Offstage:!_isPrepared, child: '🔍 search',), left: _isEdit? 0: (_isPrepared? _searchIconLeft: null), top: 0, bottom: 0 ), ] ) ; }Copy the code

Keyboard height monitor. Although this seems to be simple, it is indeed the module that the author took the longest time to implement. First of all, the method of keyboard monitoring height is implemented as follows, and the pseudo-code is as follows:

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeMetrics() { super.didChangeMetrics(); // Fixed Bug : The bottomNavigationBar child can't listen for keyboard height changes, So it had no choice but to the listening again WidgetsBinding. Instance. AddPostFrameCallback ((_) {final keyboardHeight = MediaQuery.of(context).viewInsets.bottom; }); }}Copy the code

Adhering to the principle of predecessors planting trees, descendants enjoying the shade, that a copy of the code, the function has been realized, considering that only the search page (SearchContent) need to monitor, so the above code copy in high spirits, Result MediaQuery.of(context).viewinsets. Bottom; The value of is always 0, and the code is completely ok. When the result turns out to be a problem, it is really impossible to be broken. It turns out that wechat page and contact page cannot be monitored. After the author copy the code to the Homepage page on the line, during the process is really tearless… We have to use the Provider to record the change of the keyboard height of a HomePage, so as to modify the UI change of the SearchContent page. The pseudocode is as follows:

@override
void didChangeMetrics() { super.didChangeMetrics(); // Fixed Bug : The bottomNavigationBar child can't listen for keyboard height changes, So it had no choice but to the listening again WidgetsBinding. Instance. AddPostFrameCallback ((_) {final keyboardHeight = MediaQuery.of(context).viewInsets.bottom; Provider.of<KeyboardProvider>(context, listen:false)
        .setKeyboardHeight(keyboardHeight);
  });
}
Copy the code

conclusion

First of all, this article mainly explains the realization of several function points on the wechat home page module: the message side slide deletion, drop-down display small program, click the navigation bar + button, popup menu bar and other functions. Among them, through the gradual analysis and logical processing of function points, I believe that we should be able to achieve the code of each function point.

Secondly, we can master the use of animation components and deformation components, which enriches our library of FLUTTER components. At the same time, I learned the knowledge points of list-monitoring and scrolling control, grasped different schemes of monitoring or scrolling control, and had a certain understanding of the implementation of state management in Flutter…

Finally, the core of this article still wants to train you to do some functional or logical analysis before writing any function, clear your mind, determine a good implementation plan, and then write code, sharpness does not cut wood workers. We also hope that after completing this function, you will have motivation and fun to learn about Flutter.

Looking forward to

  1. Article if you have some help, please give a like ❤️, after all, the code word is not easy; If you do not have what help, please give some advice 💗, remember to learn endless.
  2. For the content of the article, during the reading of any questions; Please point out in the comments at the bottom of this article that I will fix and fix the problem quickly.
  3. GitHub address: github.com/CoderMikeHe
  4. Source code address: flutter_wechat

The home page

GitHub Jane’s book CSDN zhihu
Click to enter Click to enter Click to enter Click to enter

expand

  • Flutter plays wechat — address book
  • Flutter plays wechat — the wonderful use of splash screen page