如何使用父项目中心下方的项目制作Flutter视图?

问题描述 投票:0回答:4

我试图在Flutter中创建一个看起来像这样的视图。但是,Flutter中没有相对位置的概念。这就是我想要实现的目标。

enter image description here

红色矩形位于屏幕中央,绿色矩形位于红色矩形正下方。

在Android中,我可以使用Constraint Layout轻松完成此操作,

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/view"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="#ff0000"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:background="#00ff00"
        app:layout_constraintEnd_toEndOf="@+id/view"
        app:layout_constraintTop_toBottomOf="@+id/view" />

</android.support.constraint.ConstraintLayout>

任何人都可以在Flutter中建议一个好的解决方案吗?

flutter flutter-layout
4个回答
1
投票

@cynw

由于两个小部件都是文本,并且在渲染之前您不知道它们的高度,我们必须计算高度并重新渲染(重建)小部件。

在下面的方法中,我在大文本上方添加一个SizedBox以将其向下推,以确保它在中心布局。这种方法的坏处是我们必须重新构建小部件。

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

void main() {
  SystemChrome.setEnabledSystemUIOverlays([]);
  runApp(MyStatefulApp());
}

class MyStatefulApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyStatefulAppState();
  }
}

class _MyStatefulAppState extends State<MyStatefulApp> {
  GlobalKey _smallTextKey = GlobalKey();
  double _bigTextMarginTop = 0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
  }

  _afterLayout(_) {
    _getSizes();
  }

  _getSizes() {
    final RenderBox renderBoxRed =
        _smallTextKey.currentContext.findRenderObject();
    final smallTextSize = renderBoxRed.size;
    setState(() {
      _bigTextMarginTop = smallTextSize.height;
    });
  }

  @override
  Widget build(BuildContext context) {
    print('Margin = $_bigTextMarginTop');
    return MaterialApp(
      title: 'Flutter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: Center(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: <Widget>[
            SizedBox(
              height: _bigTextMarginTop,
            ),
            Text(
              'Hello',
              style: TextStyle(
                  fontSize: 120,
                  backgroundColor: Colors.red,
                  color: Colors.white),
            ),
            Text(
              'Hello',
              style: TextStyle(
                  fontSize: 40,
                  backgroundColor: Colors.green,
                  color: Colors.white),
              key: _smallTextKey,
            ),
          ],
        )),
      ),
    );
  }
}

enter image description here

希望它有所帮助!


0
投票

颤抖的Positioned班是你的朋友。

定位窗口小部件必须是Stack的后代,并且从定位窗口小部件到其封闭堆栈的路径必须只包含StatelessWidgets或StatefulWidgets(不是其他类型的小部件,如RenderObjectWidgets)。


0
投票

试试这个

enter image description here

Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.end,
    children: <Widget>[
      Container(
        width: MediaQuery.of(context).size.width * 0.7,
        height: MediaQuery.of(context).size.width * 0.7,
        color: Colors.red,
        child: Text("Some text"),
      ),
      Container(
        color: Colors.green,
        child: Text("text here"),
      )
    ],
  ),
)

您可以删除高度/宽度参数,以便根据其中的内容进行调整。


0
投票

这样做的一种方法是:如果您将列居中并给它水平填充对称水平填充,则在彼此之下构建2个Container,并定位它们。

home: Scaffold(
        body: Center(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 30.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  color: Colors.black,
                  height: 300,
                  width: 300,
                ),
                Align(
                  alignment: Alignment.bottomRight,
                  child: Container(
                    color: Colors.red,
                    height: 30,
                    width: 30,
                  ),
                ),
              ],
            ),
          ),
        ),
      )
© www.soinside.com 2019 - 2024. All rights reserved.