首页 > 解决方案 > 相对于另一个小部件颤动固定小部件

问题描述

我正在尝试创建一个包含卡片和登录按钮的表单: 在此处输入图像描述

我尝试了以下代码:

import 'package:flutter/material.dart';

class LoginScreenDemo extends StatefulWidget {
  @override
  _LoginScreenState createState() => new _LoginScreenState();
 }

 class _LoginScreenState extends State<LoginScreenDemo> {
 @override
 Widget build(BuildContext context) {
 final email = TextFormField(
  keyboardType: TextInputType.emailAddress,
  autofocus: false,
  style: TextStyle(fontSize: 25.0),
  decoration: InputDecoration(
    labelText: 'Email',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
    border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.0)),
  ),
);

final password = TextFormField(
  obscureText: true,
  autofocus: false,
  style: TextStyle(fontSize: 25.0),
  decoration: InputDecoration(
    labelText: 'Password',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
    border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.0)),
  ),
);

final loginButton = Padding(
  padding: EdgeInsets.only(top: 10.0),
  child: RaisedButton(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(20.0),
    ),
    onPressed: () {},
    padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 30.0),
    color: Colors.lightBlueAccent,
    child: Text(
      'LOGIN',
      style: TextStyle(
        color: Colors.white,
        fontSize: 25.0,
        fontWeight: FontWeight.bold,
      ),
    ),
  ),
);

final goToSignUpScreen = Padding(
  padding: EdgeInsets.only(top: 5.0),
  child: FlatButton(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(20.0),
    ),
    onPressed: () {
      Navigator.of(context).pushNamed('/signup');
    },
    child: Text(
      "New account? Sign Up",
      style: TextStyle(
        fontSize: 15.0,
      ),
    ),
  ),
);

final loginCard = Card(
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(15.0),
  ),
  color: Colors.white,
  elevation: 4.0,
  child: ListView(
    shrinkWrap: true,
    padding:
        EdgeInsets.only(top: 100.0, left: 50.0, right: 50.0, bottom: 75.0),
    children: <Widget>[
      email,
      SizedBox(height: 15.0),
      password,
    ],
  ),
);

final buttonsContainer = Container(
  alignment: Alignment.bottomCenter,
  padding: EdgeInsets.only(
    top: MediaQuery.of(context).orientation == Orientation.landscape
        ? MediaQuery.of(context).size.height * 0.35
        : MediaQuery.of(context).size.height * 0.26,
  ),
  child: Column(
    children: <Widget>[
      loginButton,
      goToSignUpScreen,
    ],
  ),
);

final backgroundContainer = Container(
  height: MediaQuery.of(context).size.height * 0.40,
  decoration: BoxDecoration(
    image: DecorationImage(
      image: AssetImage('assets/background_golf_course.jpeg'),
      fit: BoxFit.cover,
    ),
  ),
);

final formContainer = Container(
  alignment: Alignment.topCenter,
  padding: EdgeInsets.only(
    top: MediaQuery.of(context).size.height * 0.25,
    right: 20.0,
    left: 20.0,
  ),
  child: Container(
    width: MediaQuery.of(context).size.width * 0.75,
    child: Stack(
      children: <Widget>[
        loginCard,
        buttonsContainer,
      ],
    ),
  ),
);

return SafeArea(
  child: Container(
    color: Color(0xFFEEEEEE),
    child: Stack(
      children: <Widget>[
        backgroundContainer,
        formContainer,
      ],
    ),
  ),
);
}
}

我已将卡片和按钮放置在堆栈小部件中,并尝试通过定义它们的高度和填充将按钮(如 buttonContainer 中所示)放置在卡片上方。可以看出,我需要为纵向和横向模式定义不同的填充,而且如果屏幕尺寸发生变化,它也会中断。有没有更简洁的方法来实现这一点?

谢谢

标签: flutterflutter-layout

解决方案


Container确实有财产transform。使用它是顶部填充的替代方法。然后buttonsContainer相对于loginCard但重叠放置。

小部件buttonsContainer有一个顶部的翻译。

    final buttonsContainer = Container(
      transform: Matrix4.translationValues(0.0, -34.0, 0.0),
      alignment: Alignment.bottomCenter,
      child: Column(
        children: <Widget>[
          loginButton,
          goToSignUpScreen,
        ],
      ),
    );

然后小部件formContainer使用Column而不是Stack.

    final formContainer = Container(
      alignment: Alignment.topCenter,
      padding: EdgeInsets.only(
        top: MediaQuery.of(context).size.height * 0.25,
        right: 20.0,
        left: 20.0,
      ),
      child: Container(
        width: MediaQuery.of(context).size.width * 0.75,
        child: Column(
          children: <Widget>[
            loginCard,
            buttonsContainer,
          ],
        ),
      ),
    );

推荐阅读