当前位置:网站首页>Decrypt the responsive layout of the flutter

Decrypt the responsive layout of the flutter

2020-12-06 23:02:03 Salted fish jack

Decrypt Flutter Responsive layout

Image for post

Flutter Is a cross platform application development framework , Devices that support a variety of screen sizes , It can run on a small device like a smart watch , It can also run on a big device like a TV . Using the same code to adapt to different screen sizes and pixel densities is a challenge .

Flutter There are no rigid rules for responsive layout design . In this paper , I'll show you some of the ways you can follow when designing responsive layouts .

In the use of Flutter Before building a responsive layout , I'd like to make it clear Android and iOS How to handle the layout of different screen sizes .

Android Methods

To handle different screen sizes and pixel densities , stay Android The following concepts are used in :

1. ConstraintLayout

Android UI One of the revolutionary things introduced in design is ConstraintLayout. It can be used to create flexible 、 Responsive UI Design , To accommodate different screen sizes and sizes . It allows you to specify the location and size of each view based on its spatial relationship to other views in the layout .

But that doesn't solve the problem of large equipment , In large equipment , Stretch or just adjust UI Component size is not the most elegant way to use screen area . In a smart watch with a small screen area , Adjusting components to fit the screen size can lead to strange UI.

2. Alternative layouts

To solve the above problems , You can use... For devices of different sizes alternative layouts. for example , You can use split view on devices like tablets to provide a good user experience , And use the big screen wisely .

Image for post

stay Android in , You can define different layout files for different screen sizes ,Android The framework automatically handles the switching between these layouts based on the screen size of the device .

3. Fragments

Use Fragment, You can UI The logic is extracted into separate components , So when you design a multi pane layout for a large screen size , You don't have to define logic alone . You can reuse the... Defined for each fragment Fragment.

4. Vector graphics

Vector graphics Use XML Create images to define paths and colors , Instead of using pixel bitmaps . It can be scaled to any size . stay Android in , You can use VectorDrawable To draw any kind of illustration , Like icons .

iOS Methods

iOS The way to define a responsive layout is as follows

1. Auto Layout

Auto Layout Can be used to build adaptive interfaces , You can define rules that control the content of your application ( It's called constraint ). When certain environmental changes are detected ( It's called a feature ) when ,“Auto Layout” The layout is automatically readjusted according to the specified constraints .

2. Size classes

Size Class is automatically assigned to the content area based on its size . iOS According to the content area Size Categories dynamically adjust the layout . stay iPad On ,size Class also applies .

3. some UI Components

There are others UI You can use it in iOS Build responsive UI, image UIStackView, UIViewController, and UISplitViewController.

Flutter How adaptive

Even if you're not Android or iOS The developer of the , up to now , You should already know how these platforms handle responsive layout .

stay Android in , To display more than one on a single screen UI View , Please use Fragments, They are similar to the Activity Reusable components running in .

You can be in a Activity Running multiple Fragment, But you can't run more than one application at the same time Activity.

stay iOS in , To control multiple view controllers , Used UISplitViewController, It manages subview controllers in a hierarchical interface .

Now we come to Flutter

Flutter Introduced widget The concept of . They're building blocks together to build the application picture .

remember , stay Flutter in , Each screen and the entire application is also a widget!

widget It's essentially reusable , So in Flutter When building responsive layouts in , You don't need to learn any other concepts .

Flutter The responsive concept of

As I said earlier , I'll discuss the important concepts needed to develop responsive layouts , Then you choose what way to use in your APP On the implementation of responsive layout .

1. MediaQuery

You can use MediaQuery To retrieve the size of the screen ( Width / Height ) And direction ( The longitudinal / The transverse ).

Here is an example

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;
    Orientation orientation = MediaQuery.of(context).orientation;

    return Scaffold(
      body: Container(
        color: CustomColors.android,
        child: Center(
          child: Text(
            'View\n\n' +
                '[MediaQuery width]: ${screenSize.width.toStringAsFixed(2)}\n\n' +
                '[MediaQuery orientation]: $orientation',
            style: TextStyle(color: Colors.white, fontSize: 18),
          ),
        ),
      ),
    );
  }
}

Image for post

2. LayoutBuilder

Use LayoutBuilder class , You can get BoxConstraints object , This object can be used to determine the maxWidth and maxHeight.

please remember :MediaQuery and LayoutBuilder The main difference between them is ,MediaQuery Use the full context of the screen , Not just the size of a particular widget . and LayoutBuilder You can determine the maximum width and height of a particular widget .

Here is an example

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;

    return Scaffold(
      body: Row(
        children: [
          Expanded(
            flex: 2,
            child: LayoutBuilder(
              builder: (context, constraints) => Container(
                color: CustomColors.android,
                child: Center(
                  child: Text(
                    'View 1\n\n' +
                        '[MediaQuery]:\n ${screenSize.width.toStringAsFixed(2)}\n\n' +
                        '[LayoutBuilder]:\n${constraints.maxWidth.toStringAsFixed(2)}',
                    style: TextStyle(color: Colors.white, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            flex: 3,
            child: LayoutBuilder(
              builder: (context, constraints) => Container(
                color: Colors.white,
                child: Center(
                  child: Text(
                    'View 2\n\n' +
                        '[MediaQuery]:\n ${screenSize.width.toStringAsFixed(2)}\n\n' +
                        '[LayoutBuilder]:\n${constraints.maxWidth.toStringAsFixed(2)}',
                    style: TextStyle(color: CustomColors.android, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Image for post
PS: When you're building a widget , When you want to know what his width is , Use this component , You can use high according to the sub components / Width to judge , Building different layouts

3. OrientationBuilder

To be sure widget The current direction of , have access to OrientationBuilder class .

remember : This is with your use of MediaQuery The direction of retrieval devices is different .

Here is an example

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Orientation deviceOrientation = MediaQuery.of(context).orientation;

    return Scaffold(
      body: Column(
        children: [
          Expanded(
            flex: 2,
            child: Container(
              color: CustomColors.android,
              child: OrientationBuilder(
                builder: (context, orientation) => Center(
                  child: Text(
                    'View 1\n\n' +
                        '[MediaQuery orientation]:\n$deviceOrientation\n\n' +
                        '[OrientationBuilder]:\n$orientation',
                    style: TextStyle(color: Colors.white, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            flex: 3,
            child: OrientationBuilder(
              builder: (context, orientation) => Container(
                color: Colors.white,
                child: Center(
                  child: Text(
                    'View 2\n\n' +
                        '[MediaQuery orientation]:\n$deviceOrientation\n\n' +
                        '[OrientationBuilder]:\n$orientation',
                    style: TextStyle(color: CustomColors.android, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Image for post

portrait ( The longitudinal ) landscape( The transverse )

PS: Looked at the OrientationBuilder Source code annotation of

widget Its direction is only a coefficient of its width relative to its height . If one [Column] The width of the part exceeds its height , Its direction is horizontal , Even if it displays its child elements vertically .

This is the translator's code

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

/// Copyright (C), 2020-2020, flutter_demo
/// FileName: orientationBuilder_demo
/// Author: Jack
/// Date: 2020/12/6
/// Description:

class OrientationBuilderDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Orientation deviceOrientation = MediaQuery.of(context).orientation;

    return Scaffold(
      body: Column(
        children: [

          Expanded(
            flex: 1,
            child: Container(
              color: Colors.greenAccent,
              child: OrientationBuilder(
                builder: (context, orientation) => Center(
                  child: Text(
                    'View 1\n\n' +
                        '[MediaQuery orientation]:\n$deviceOrientation\n\n' +
                        '[OrientationBuilder]:\n$orientation',
                    style: TextStyle(color: Colors.white, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            flex: 2,
            child: OrientationBuilder(
              builder: (context, orientation) => Container(
                color: Colors.white,
                child: Center(
                  child: Text(
                    'View 2\n\n' +
                        '[MediaQuery orientation]:\n$deviceOrientation\n\n' +
                        '[OrientationBuilder]:\n$orientation',
                    style: TextStyle(color: Colors.greenAccent, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

 Insert picture description here

You must have understood OrientationBuilder The direction of the definition of , If the width of a widget is greater than its height , He's horizontal , If the height is greater than the width , He's horizontal , That's it .

4. Expanded and Flexible

stay Row or Column A particularly useful widget in is Expanded and Flexible. When Expanded Use in a Row、Column or Flex in ,Expanded Can make its son Widget Auto fill available space , By contrast ,Flexible The son of widget It doesn't fill up the entire available space .

Examples are as follows .

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: Column(
          children: [
            Row(
              children: [
                ExpandedWidget(),
                FlexibleWidget(),
              ],
            ),
            Row(
              children: [
                ExpandedWidget(),
                ExpandedWidget(),
              ],
            ),
            Row(
              children: [
                FlexibleWidget(),
                FlexibleWidget(),
              ],
            ),
            Row(
              children: [
                FlexibleWidget(),
                ExpandedWidget(),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

class ExpandedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        decoration: BoxDecoration(
          color: CustomColors.android,
          border: Border.all(color: Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Text(
            'Expanded',
            style: TextStyle(color: Colors.white, fontSize: 24),
          ),
        ),
      ),
    );
  }
}

class FlexibleWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Flexible(
      child: Container(
        decoration: BoxDecoration(
          color: CustomColors.androidAccent,
          border: Border.all(color: Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Text(
            'Flexible',
            style: TextStyle(color: CustomColors.android, fontSize: 24),
          ),
        ),
      ),
    );
  }
}

Image for post

PS: And [expand] The difference is ,[Flexible] There is no need for children widget Fill in the rest of the space , First example ,expanded Although it has the function of filling the spare space , however expanded Components and flexible Component's flex All are 1, It's like splitting the vertical axis in two ,expanded All the space you have is half of the vertical axis , In fact, he has filled in .

5. FractionallySizedBox

FractionallySizedBox widget Size its child elements to a fraction of the available space . It's in Expanded or Flexible widget It's especially useful .

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                FractionallySizedWidget(widthFactor: 0.4),
              ],
            ),
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                FractionallySizedWidget(widthFactor: 0.6),
              ],
            ),
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                FractionallySizedWidget(widthFactor: 0.8),
              ],
            ),
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                FractionallySizedWidget(widthFactor: 1.0),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

class FractionallySizedWidget extends StatelessWidget {
  final double widthFactor;
  FractionallySizedWidget({@required this.widthFactor});

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: FractionallySizedBox(
        alignment: Alignment.centerLeft,
        widthFactor: widthFactor,
        child: Container(
          decoration: BoxDecoration(
            color: CustomColors.android,
            border: Border.all(color: Colors.white),
          ),
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Text(
              '${widthFactor * 100}%',
              style: TextStyle(color: Colors.white, fontSize: 24),
            ),
          ),
        ),
      ),
    );
  }
}

PS: When you want your widget, What percentage of the current screen width and height , Use this component , Want to be in Row and Column When using percentage layout in components , Need to be in FractionallySizedBox It's wrapped in a package expanded or flexible

6. AspectRatio

have access to AspectRatio The small part adjusts the size of the child elements to a specific aspect ratio . First , It tries the maximum width allowed by the layout constraint , And determine the height by applying the given aspect ratio to the width .

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: Column(
          children: [
            AspectRatioWidget(ratio: '16 / 9'),
            AspectRatioWidget(ratio: '3 / 2'),
          ],
        ),
      ),
    );
  }
}

class AspectRatioWidget extends StatelessWidget {
  final String ratio;

  AspectRatioWidget({@required this.ratio});

  @override
  Widget build(BuildContext context) {
    return AspectRatio(
      aspectRatio: Fraction.fromString(ratio).toDouble(),
      child: Container(
        decoration: BoxDecoration(
          color: CustomColors.android,
          border: Border.all(color: Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Center(
            child: Text(
              'AspectRatio - $ratio',
              style: TextStyle(color: Colors.white, fontSize: 24),
            ),
          ),
        ),
      ),
    );
  }
}

Image for post

We've looked at most of the important concepts , To create a responsive layout Flutter app, Except for the last one .

When building a sample responsive application , Let's learn the last concept .

Create a responsive APP

Now? , We will apply some of the concepts described in the previous section . meanwhile , You'll also learn another important concept of building a layout for a large screen , That's split screen view ( Multiple pages on one screen ).

Responsive layout : Use different layouts on different sized screens .
We're going to build a new one called Flow Application chat .

app It consists of two parts :

  • HomePage (PeopleView, BookmarkView, ContactView)
  • ChatPage (PeopleView, ChatView) Insert picture description here

     Insert picture description here

For the big screen , We'll show that it contains MenuWidget and DestinationView Split screen view of . You can see , stay Flutter It's very easy to create split view in , You just use a single line of them side by side , And then in order to fill the space , Just use Expanded widget Wrap two views . You can also define flex attribute , This will allow you to specify how much of the screen each widget should cover ( Default flex Set to 1).

however , If you move to a specific screen now , Then switch between views , Then you will lose the context of the page , That is, you will always return to the first page , namely “ Chat ”. To solve this problem , I used multiple callback functions to return the selected page to the home page . actually , You should use state management techniques to handle this scenario . Because the only purpose of this article is to teach you to build responsive layouts , So I'm not going to discuss any of the complexities of state management .

Response type APP Github Address Interested partners can have a look

Of all the layout components mentioned above demo It's all in the translator's github On

Address https://github.com/jack0-0wu/...

This paper is about medium translate

Original address

https://medium.com/flutter-co...
It's better to sit and talk than to act

版权声明
本文为[Salted fish jack]所创,转载请带上原文链接,感谢
https://chowdera.com/2020/12/20201206230059554m.html