首页 > 解决方案 > 如何使用 MediaQuery 管理不同设备的屏幕布局?

问题描述

我已经将 MediaQuery 用于响应式设计,但我没有得到想要的结果。请指导我并帮助我。我在不同的移动设备上得到不同的 UI。请告诉我我哪里错了,或者指导我使用正确的代码来使用 MediaQuery 进行响应式设计。我不想使用 SingleChildScrollView,因为它是登录屏幕。所以,我希望它能够响应所有设备,包括不同尺寸的标签和手机。下面是我的代码:

import 'dart:ui';
import 'package:conqer_music/App/Controller/UserController.dart';
import 'package:mvc_pattern/mvc_pattern.dart';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
import 'package:conqer_music/App/Repository/UserRepository.dart' as userRepo;

class LoginPage extends StatefulWidget {
  static const String routeName = '/loginPage';

  @override
  _LoginState createState() => _LoginState();
}

final _formKey = GlobalKey<FormState>();

class _LoginState extends State<LoginPage> {
  late UserController _con;

  // _LoginState() : super(UserController()) {
  //   _con = controller;
  @override
  void initState() {
    super.initState();
    if (userRepo.currentUser.value.apiToken != null) {
      Navigator.of(context).pushReplacementNamed('/Pages', arguments: 2);
    }
  }

  bool _rememberMe = false;
  Widget logo() {
    final screenHeight = MediaQuery.of(context).size.height;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Padding(padding: EdgeInsets.only(top: screenHeight * 0.08)),
        CircleAvatar(
          child: Image.asset('lib/App/Assets/Images/Logo.png'),
          backgroundColor: Colors.grey,
          radius: 80.0,
        ),
        SizedBox(
          height: 10.0,
        ),
        Text(
          'LOGIN',
          style: TextStyle(
              fontSize: 28.0, fontWeight: FontWeight.bold, color: Colors.white),
          textAlign: TextAlign.center,
        ),
      ],
    );
  }

  Widget backgroundImage() {
    return Expanded(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Container(
            constraints: BoxConstraints.expand(),
            decoration: BoxDecoration(
                image: DecorationImage(
                    image: AssetImage('lib/App/Assets/Images/BackGround.png'),
                    fit: BoxFit.cover)),
          )
        ],
      ),
    );
  }

  Widget userPass() {
    final screenHeight = MediaQuery.of(context).size.height;
    final screenWidth = MediaQuery.of(context).size.width;
    return Expanded(
      child: Container(
        height: screenHeight * 0.2,
        width: screenWidth * 0.8,
        child: Column(
          children: <Widget>[
            TextFormField(
              validator: (value) {
                if (value == null || value.isEmpty) {
                  return 'Please Enter Username';
                }
                return null;
              },
              decoration: InputDecoration(
                filled: true,
                fillColor: Colors.white,
                hintText: 'Username',
                hintStyle: TextStyle(
                  color: Color(0xFFbaa15e),
                ),
                suffixIcon: Icon(Icons.verified_user_sharp),
                border: OutlineInputBorder(
                    //  borderRadius: BorderRadius.circular(20.0),
                    ),
              ),
              style: TextStyle(
                  color: Colors.black,
                  fontSize: 12,
                  textBaseline: TextBaseline.alphabetic),
            ),
            SizedBox(height: 20),
            TextFormField(
              validator: (String? pass) {
                if (pass!.length == 0) {
                  return 'Please Enter Password';
                }
              },
              decoration: InputDecoration(
                filled: true,
                fillColor: Colors.white,
                hintText: 'Password',
                hintStyle: TextStyle(color: Color(0xFFbaa15e)),
                suffixIcon: Icon(Icons.security_rounded),
                border: OutlineInputBorder(
                    //  borderRadius: BorderRadius.circular(20.0),
                    ),
              ),
              style: TextStyle(color: Colors.black, fontSize: 12),
            ),
          ],
        ),
      ),
    );
  }

  Widget rememberMe() {
    final screenHeight = MediaQuery.of(context).size.height;
    final screenWidth = MediaQuery.of(context).size.width;
    return Container(
      height: screenHeight * 0.05,
      // width: screenWidth * 0.4,
      padding: EdgeInsets.only(left: 40),
      child: Row(
        children: <Widget>[
          Checkbox(
            value: _rememberMe,
            checkColor: Colors.green,
            activeColor: Colors.white,
            onChanged: (value) {
              setState(() {
                _rememberMe = value!;
              });
            },
          ),
          Text(
            'Remember Me',
            style: TextStyle(color: Colors.white, fontSize: 14),
          ),
        ],
      ),
    );
  }

  Widget loginButton() {
    final screenHeight = MediaQuery.of(context).size.height;
    final screenWidth = MediaQuery.of(context).size.width;
    return Container(
      // height: screenHeight * 0.1,
      width: screenWidth * 0.8,
      child: RaisedButton(
        elevation: 4.0,

        onPressed: () {
          Navigator.of(context).pushReplacementNamed('/MainPage');
          if (_formKey.currentState!.validate()) {
            Navigator.of(context).pushReplacementNamed('/MainPage');

            _con.login();
          }
        },

        //  if (_formKey.currentState!.validate()) {
        // Navigator.of(context).pushReplacementNamed('/MainPage'),
        //  },
        padding: EdgeInsets.all(15.0),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(30.0),
        ),

        color: Color(0xFFbaa15e),
        child: Text(
          'LOGIN',
          style: TextStyle(
            color: Colors.white,
            letterSpacing: 1.5,
            fontSize: 14.0,
            fontWeight: FontWeight.bold,
            fontFamily: 'OpenSans',
          ),
        ),
      ),
    );
  }

  Widget forgotPasswordhelp() {
    final screenHeight = MediaQuery.of(context).size.height;
    final screenWidth = MediaQuery.of(context).size.width;
    return Container(
      padding: EdgeInsets.fromLTRB(
          screenWidth * 0.14, 0, screenWidth * 0.14, screenHeight * 0.09),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          Text(
            'Forgot Password?',
            style: TextStyle(
              color: Color(0xFFbaa15e),
            ),
          ),
          Text(
            'Help?',
            style: TextStyle(
              color: Color(0xFFbaa15e),
            ),
          )
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final screenHeight = MediaQuery.of(context).size.height;
    final screenWidth = MediaQuery.of(context).size.width;
    return Scaffold(
      body: Container(
        height: screenHeight,
        width: screenWidth,
        decoration: BoxDecoration(
            image: DecorationImage(
                image: AssetImage('lib/App/Assets/Images/BackGround.png'),
                fit: BoxFit.cover)),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            logo(),
            SizedBox(
              height: 10,
            ),
            userPass(),
            rememberMe(),
            SizedBox(
              height: 10,
            ),
            loginButton(),
            SizedBox(
              height: 5,
            ),
            forgotPasswordhelp()
          ],
        ),
      ),
    );
  }
}

标签: flutterflutter-layout

解决方案


Flutter 并不能让你轻松地为移动设备构建响应式应用程序。一种解决方法是检测设备方向并根据您的需要更改容器的高度和宽度。一种方法是使用 Container 小部件的“mediaquery”属性。

width: MediaQuery.of(context).orientation == Orientation.landscape ? 25 : 14

如果设备处于横向模式,这会将容器的宽度更改为 25,如果设备处于纵向模式,则将宽度更改为 14。你也可以对 height 属性做同样的事情。


推荐阅读