Equivalent of RelativeLayout in Flutter

前端 未结 4 1878
后悔当初
后悔当初 2021-01-29 18:00

Is there a way to implement something similar to what RelativeLayout does on Android?

In particular I\'m looking for something similar to centerInPare

相关标签:
4条回答
  • 2021-01-29 18:04

    Here is another example to show how Stack along with Positioned can be used to make it work like RelativeLayout.

    double _containerHeight = 120, _imageHeight = 80, _iconTop = 44, _iconLeft = 12, _marginLeft = 110;
    
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        backgroundColor: Colors.white,
        body: Stack(
          children: <Widget>[
            Positioned(
              left: 0,
              right: 0,
              height: _containerHeight,
              child: Container(color: Colors.blue),
            ),
            Positioned(
              left: _iconLeft,
              top: _iconTop,
              child: Icon(Icons.settings, color: Colors.white),
            ),
            Positioned(
              right: _iconLeft,
              top: _iconTop,
              child: Icon(Icons.bubble_chart, color: Colors.white),
            ),
            Positioned(
              left: _iconLeft,
              top: _containerHeight - _imageHeight / 2,
              child: ClipOval(child: Image.asset("assets/images/profile.jpg", fit: BoxFit.cover, height: _imageHeight, width: _imageHeight)),
            ),
            Positioned(
              left: _marginLeft,
              top: _containerHeight - (_imageHeight / 2.5),
              child: Text("CopsOnRoad", style: TextStyle(color: Colors.white, fontWeight: FontWeight.w500, fontSize: 18)),
            ),
            Positioned.fill(
              left: _marginLeft,
              top: _containerHeight + (_imageHeight / 4),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Column(
                    children: <Widget>[
                      Text("2", style: TextStyle(fontWeight: FontWeight.bold)),
                      Text("Gold", style: TextStyle(color: Colors.grey)),
                    ],
                  ),
                  Column(
                    children: <Widget>[
                      Text("22", style: TextStyle(fontWeight: FontWeight.bold)),
                      Text("Silver", style: TextStyle(color: Colors.grey)),
                    ],
                  ),
                  Column(
                    children: <Widget>[
                      Text("28", style: TextStyle(fontWeight: FontWeight.bold)),
                      Text("Bronze", style: TextStyle(color: Colors.grey)),
                    ],
                  ),
                  Container(),
                ],
              ),
            ),
          ],
        ),
      );
    }
    
    0 讨论(0)
  • 2021-01-29 18:19

    Similar to Android's RelativeLayout (and in fact more powerful) is the AlignPositioned widget from the align_positioned package:

    https://pub.dev/packages/align_positioned

    From its docs:

    When your desired layout feels too complex for Columns and Rows, AlignPositioned is a real life saver. Flutter is very composable, which is good, but sometimes it's unnecessarily complex to translate some layout requirement into a composition of simpler widgets.

    The AlignPositioned aligns, positions, sizes, rotates and transforms its child in relation to both the container and the child itself. In other words, it lets you easily and directly define where and how a widget should appear in relation to another.

    For example, you can tell it to position the top-left of its child at 15 pixels to the left of the top-left corner of the container, plus move it two thirds of the child's height to the bottom plus 10 pixels, and then rotate 15 degrees. Do you even know how to start doing this by composing basic Flutter widgets? Maybe, but with AlignPositioned it's much easier, and it takes a single widget.

    However, the specific example in the question is quite simple, I'd just use Rows, Columns etc anyway. Note: I am the author of this package.

    0 讨论(0)
  • 2021-01-29 18:20

    You can use Stack and can have its children as Positioned or Align.

    Example #1 (Using Positioned in Stack)

    Stack(
      children: <Widget>[
        Positioned(left: 0.0, child: Text("Top\nleft")),
        Positioned(bottom: 0.0, child: Text("Bottom\nleft")),
        Positioned(top: 0.0, right: 0.0, child: Text("Top\nright")),
        Positioned(bottom: 0.0, right: 0.0, child: Text("Bottom\nright")),
        Positioned(bottom: 0.0, right: 0.0, child: Text("Bottom\nright")),
        Positioned(left: width / 2, top: height / 2, child: Text("Center")),
        Positioned(top: height / 2, child: Text("Center\nleft")),
        Positioned(top: height / 2, right: 0.0, child: Text("Center\nright")),
        Positioned(left: width / 2, child: Text("Center\ntop")),
        Positioned(left: width / 2, bottom: 0.0, child: Text("Center\nbottom")),
      ],
    )
    

    Example #2 (Using Align in Stack)

    Stack(
      children: <Widget>[
        Align(alignment: Alignment.center, child: Text("Center"),),
        Align(alignment: Alignment.topRight, child: Text("Top\nRight"),),
        Align(alignment: Alignment.centerRight, child: Text("Center\nRight"),),
        Align(alignment: Alignment.bottomRight, child: Text("Bottom\nRight"),),
        Align(alignment: Alignment.topLeft, child: Text("Top\nLeft"),),
        Align(alignment: Alignment.centerLeft, child: Text("Center\nLeft"),),
        Align(alignment: Alignment.bottomLeft, child: Text("Bottom\nLeft"),),
        Align(alignment: Alignment.topCenter, child: Text("Top\nCenter"),),
        Align(alignment: Alignment.bottomCenter, child: Text("Bottom\nCenter"),),
        Align(alignment: Alignment(0.0, 0.5), child: Text("Custom\nPostition", style: TextStyle(color: Colors.red, fontSize: 20.0, fontWeight: FontWeight.w800),),),
      ],
    );
    

    Screenshot:

    0 讨论(0)
  • 2021-01-29 18:28

    Flutter layouts are usually built using a tree of Column, Row and Stack widgets. These widgets take constructor arguments that specify rules for how the children are laid out relative to the parent, and you can also influence layout of individual children by wrapping them in Expanded, Flexible, Positioned, Align, or Center widgets.

    It is also possible to build complex layouts using CustomMultiChildLayout. This is how Scaffold is implemented internally, and an example of how to use it in an app appears in the Shrine demo. You can also use LayoutBuilder or CustomPaint, or go down a layer and extend RenderObject as shown in the sector example. Doing your layouts manually like this is more work and creates more potential for errors in corner cases, so I would try to get by with the high-level layout primitives if you can.

    To answer your specific questions:

    • Use the leading and trailing arguments to AppBar to position your app bar elements. If you want to use a Row instead, use a mainAxisAlignment of MainAxisAlignment.spaceBetween.
    • Use a Row with a crossAxisAlignment of CrossAxisAlignment.center to position the fire icon and number underneath.
    • Use a Column with a mainAxisAlignment of MainAxisAlignment.spaceBetween to position your top and bottom title. (You should consider using ListTile to lay out the list tiles, but you'll lose control over the exact positioning if you do this.)

    Here is a code snippet that implements the design you provided. In this example I used an IntrinsicHeight to determine the height of the song tiles, but you can improve the performance by hard coding them to a fixed height.

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            brightness: Brightness.dark,
            primaryColorBrightness: Brightness.dark,
          ),
          home: new HomeScreen(),
          debugShowCheckedModeBanner: false,
        );
      }
    }
    
    class Song extends StatelessWidget {
      const Song({ this.title, this.author, this.likes });
    
      final String title;
      final String author;
      final int likes;
    
      @override
      Widget build(BuildContext context) {
        TextTheme textTheme = Theme
          .of(context)
          .textTheme;
        return new Container(
          margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
          padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0),
          decoration: new BoxDecoration(
            color: Colors.grey.shade200.withOpacity(0.3),
            borderRadius: new BorderRadius.circular(5.0),
          ),
          child: new IntrinsicHeight(
            child: new Row(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                new Container(
                  margin: const EdgeInsets.only(top: 4.0, bottom: 4.0, right: 10.0),
                  child: new CircleAvatar(
                    backgroundImage: new NetworkImage(
                      'http://thecatapi.com/api/images/get?format=src'
                        '&size=small&type=jpg#${title.hashCode}'
                    ),
                    radius: 20.0,
                  ),
                ),
                new Expanded(
                  child: new Container(
                    child: new Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        new Text(title, style: textTheme.subhead),
                        new Text(author, style: textTheme.caption),
                      ],
                    ),
                  ),
                ),
                new Container(
                  margin: new EdgeInsets.symmetric(horizontal: 5.0),
                  child: new InkWell(
                    child: new Icon(Icons.play_arrow, size: 40.0),
                    onTap: () {
                      // TODO(implement)
                    },
                  ),
                ),
                new Container(
                  margin: new EdgeInsets.symmetric(horizontal: 5.0),
                  child: new InkWell(
                    child: new Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        new Icon(Icons.favorite, size: 25.0),
                        new Text('${likes ?? ''}'),
                      ],
                    ),
                    onTap: () {
                      // TODO(implement)
                    },
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class Feed extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new ListView(
          children: [
            new Song(title: 'Trapadelic lobo', author: 'lillobobeats', likes: 4),
            new Song(title: 'Different', author: 'younglowkey', likes: 23),
            new Song(title: 'Future', author: 'younglowkey', likes: 2),
            new Song(title: 'ASAP', author: 'tha_producer808', likes: 13),
            new Song(title: '                                                                    
    0 讨论(0)
提交回复
热议问题