sequence

During APP development, it is common to see the need to add backgrounds, set margins, and dynamically show and hide a component.

However, only Container(see my introduction to the Row, Column, and Container layout of Flutter) can add backgrounds, margins, shadows, borders, and rounded corners at the same time. This is already the most functional component of Flutter. In order to realize the display and hiding of components, another component Offstage is needed. Row is used for horizontal linear layout, and Column is used for vertical linear layout. Row and Column do not have the functions of setting background, margins, show and hide directly.

In the development process, this kind of requirement is very common. It is impossible to repeat the code in every place, so it is necessary to package these components and realize a component similar to the Android LinearLayout layout.

Encapsulation LinearLayout

The LinearLayout is actually very simple, which is to rationally combine the four components of Row, Column, Offstage and Container together.

  1. The first step is to expose a parameter that determines whether the layout is horizontal or vertical
  2. willContainerFrequently used background and margin parameters are exposed
  3. willRow,ColumnThe alignment of the spindle and cross axes used in the
  4. willRow,ColumnThe adaptation of the spindle size is exposed
  5. Exposes a method to dynamically change the display and hide of components

The code is as follows:

import 'package:flutter/material.dart';
import 'package:flutter_library/common/util.dart';

enum LayoutOrientation { horizontal, vertical }

class LinearLayout extends StatefulWidget {
  final LayoutOrientation orientation;
  final bool isVisible;
  final Decoration background;
  final EdgeInsetsGeometry padding;
  final EdgeInsetsGeometry margin;
  final List<Widget> children;

  final MainAxisAlignment mainAxisAlignment;
  final MainAxisSize mainAxisSize;
  final CrossAxisAlignment crossAxisAlignment;

  LinearLayout({
    Key key,
    this.orientation,
    this.isVisible = true,
    this.background,
    this.padding,
    this.margin,
    this.children = const <Widget>[],
    this.mainAxisAlignment = MainAxisAlignment.start,
    this.mainAxisSize = MainAxisSize.min,
    this.crossAxisAlignment = CrossAxisAlignment.center,
  }) : super(key: key);

  @override
  LinearLayoutState createState() {
    return LinearLayoutState();
  }
}

class LinearLayoutState extends State<LinearLayout> {
  bool _isVisible = true;

  @override
  void initState() {
    _isVisible = widget.isVisible;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return isNotNull(_isVisible)
        ? Offstage(
            offstage: !_isVisible,
            child: _buildLayoutWidget(),
          )
        : _buildLayoutWidget();
  }

  Widget _buildLayoutWidget() {
    if (_isNeedContainerWidget()) {
      return _buildContainerWidget();
    } else {
      return _buildOrientationWidget();
    }
  }

  bool _isNeedContainerWidget() {
    return isNotNull(widget.background) ||
        isNotNull(widget.padding) ||
        isNotNull(widget.margin);
  }

  Widget _buildContainerWidget() {
    return Container(
      decoration: widget.background,
      padding: widget.padding,
      margin: widget.margin,
      child: _buildOrientationWidget(),
    );
  }

  Widget _buildOrientationWidget() {
    if (widget.orientation == LayoutOrientation.horizontal) {
      return _buildHorizontalWidget();
    } else {
      return _buildVerticalWidget();
    }
  }

  Widget _buildVerticalWidget() {
    return Column(
      mainAxisSize: widget.mainAxisSize,
      mainAxisAlignment: widget.mainAxisAlignment,
      crossAxisAlignment: widget.crossAxisAlignment,
      children: widget.children,
    );
  }

  Widget _buildHorizontalWidget() {
    return Row(
      mainAxisSize: widget.mainAxisSize,
      mainAxisAlignment: widget.mainAxisAlignment,
      crossAxisAlignment: widget.crossAxisAlignment,
      children: widget.children,
    );
  }

  bool isVisible() {
    return _isVisible;
  }

  void setVisible(bool isVisible) {
    setState(() {
      _isVisible = isVisible;
    });
  }
}
Copy the code

Dart :flutter_library/common/util.

bool isNull(dynamic obj) { return obj == null; } bool isNotNull(dynamic obj) { return obj ! = null; }Copy the code

LinearLayout use

class LinearLayoutSampleWidget extends StatefulWidget { @override State<StatefulWidget> createState() { return LinearLayoutSampleState(); } } class LinearLayoutSampleState extends State<LinearLayoutSampleWidget> { GlobalKey<LinearLayoutState> _key = GlobalKey<LinearLayoutState>(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('LinearLayout Sample'), ), body: LinearLayout( background: BoxDecoration(color: Colors.blue), orientation: LayoutOrientation.vertical, children: <Widget>[ LinearLayout( key: _key, background: BoxDecoration(color: Colors.red), orientation: LayoutOrientation.horizontal, mainAxisSize: MainAxisSize.min, children: <Widget>[Icon(Icons. List), Text(' linear layout ')],), FlatButton(onPressed: () { bool isVisible = _key.currentState.isVisible(); _key.currentState.setVisible(!isVisible); }, child: Text(' toggle display '),)],); }}Copy the code