Flutter响应式设计:如果屏幕较大,动态更改Column为Row。

30
如何在设备屏幕宽度超过特定阈值时将Column Widget动态更改为Row Widget?
使用场景是当用户在平板电脑或横向模式上使用应用程序时,布局应有所不同以优化可用宽度的使用。
在CSS Flexbox中,仅需将类从flex-row更改为flex-column即可,但在Flutter中,使用小部件。
4个回答

81

RowColumn共享一个名为Flex的公共父级,该父级采用轴方向。只需更改direction的值,即可将Flex更改为行或列。

要获取屏幕宽度,您可以使用MediaQuery.of(context).size.width

您的小部件应如下所示:

@override
Widget build(BuildContext context) {
  bool isScreenWide = MediaQuery.of(context).size.width >= kMinWidthOfLargeScreen;

  return Scaffold(
    body: Flex(
      direction: isScreenWide ? Axis.horizontal : Axis.vertical,
      children: <Widget>[
        ...
      ],
    )
  );
}

如果您正在使用类似于希望拥有无限空间的列表视图之类的东西,那么Wrap将无法正常工作。我知道这一点,因为在找到这个答案之前,我刚遇到了这个问题。 :-) - Robert

7

要根据设备方向进行更改,您可以执行以下操作:

Orientation orientation = MediaQuery.of(context).orientation;

return orientation == Orientation.portrait
? Column(children: <Widget>[])
: Row(children: <Widget>[]);

我写了一个帮助器来完成这个任务(列转行)。
import 'package:flutter/material.dart';

class OrientationSwitcher extends StatelessWidget {
  final List<Widget> children;

  const OrientationSwitcher({Key key, this.children}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    Orientation orientation = MediaQuery.of(context).orientation;
    return orientation == Orientation.portrait
    ? Column(children: children)
    : Row(children: children);
  }
}

并且使用它...

  Widget build(BuildContext context) {
    return OrientationSwitcher(
      children: <Widget>[
           // place children here like its a column or row.
        ]
    )
  }

你也可以使用Flex()或任何其他小部件来实现此功能。
此外,除了方向之外还有更多选项可用,请确保查看Flutter文档中的MediaQuery.of(context)实现。

0

有一个库你应该去看看https://pub.dev/packages/responsive_framework

以下是使用这个库的方法:

ResponsiveRowColumn(
        layout: ResponsiveWrapper.of(context).isLargerThan(TABLET)
            ? ResponsiveRowColumnType.ROW
            : ResponsiveRowColumnType.COLUMN,
        children: const [
          ResponsiveRowColumnItem(rowFlex: 1, columnFlex: 1, child: Widget1()),
          ResponsiveRowColumnItem(rowFlex: 1, columnFlex: 1, child: Widget2())
        ],
      ),

如果屏幕尺寸大于定义的TABLET断点,此代码将在一行中排列小部件,否则将在一列中排列。


0
在宽屏幕上,我们展示一个等高的行,其中包含3个小部件。 在窄屏幕上,这三个小部件变成了一列,并占据整个宽度。
class CategorySelection extends StatelessWidget {
  const CategorySelection({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    double screenWidth = MediaQuery.of(context).size.width;
    double screenHeight = MediaQuery.of(context).size.height;
    bool isScreenWide = MediaQuery.of(context).size.width >= 1200;

    return MaxWidthContainer(
      child: isScreenWide? IntrinsicHeight(
        child:  Row(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: categoryList(isScreenWide,screenWidth,screenHeight),
        ),
      ): IntrinsicHeight(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: categoryList(isScreenWide,screenWidth,screenHeight),
        ),
      ),
    );
  }
}



List<Widget> categoryList(bool isScreenWide,double screenWidth,double screenHeight){
 return [
   const Widget1(),
   isScreenWide? SizedBox(width: screenWidth * 0.03):SizedBox(height: screenHeight * 0.03),
   const Widget1(),
   isScreenWide? SizedBox(width: screenWidth * 0.03):SizedBox(height: screenHeight * 0.03),
   const Widget1(),
 ];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接