window 调整大小时 NavigationRail 和 NavigationRailDestination 中的 RenderFlex 溢出

RenderFlex overflowing in NavigationRail and NavigationRailDestination on window-resizing

调整桌面大小时,如何修复 NavigationRail 和 NavigationRailDestination 中的 RenderFlex 溢出 window?

Flutter 2.11.0-0.0.pre.794 • channel master • https://github.com/flutter/flutter.git
Framework • revision dce7f869cc (5 days ago) • 2022-03-06 17:11:15 -0500
Engine • revision 6576bd428a
Tools • Dart 2.17.0 (build 2.17.0-180.0.dev) • DevTools 2.11.1

错误信息

The relevant error-causing widget was
Row
lib\main.dart:69
To inspect this widget in Flutter DevTools, visit: [http://127.0.0.1:9100/#/inspector?uri=http%3A%2F%2F127.0.0.1%3A51282%2F2uROG0czKjg%3D%2F&inspectorRef=inspector-0]()
The overflowing RenderFlex has an orientation of Axis.horizontal.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and black striped pattern. This is usually caused by the contents being too big for the RenderFlex.

Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView.

The specific RenderFlex in question is: RenderFlex#939a0 relayoutBoundary=up1 OVERFLOWING

代码

import 'dart:math';
import 'dart:ui';

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        textTheme: GoogleFonts.robotoMonoTextTheme(Theme.of(context).textTheme),
      ),
      scrollBehavior: AppScrollBehavior(),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;
  final PageController _pageController = PageController();

  _pageChanged(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  _destinationSelected(int index) {
    setState(() {
      _selectedIndex = index;
      _pageController.jumpToPage(index);
    });
  }

  @override
  void initState() {
    super.initState();
    //_pageController = PageController();
    _pageController.addListener(() {
      // double offset = _pageController.offset;
      // double? page = _pageController.page;
      // debugPrint('$offset, $page');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: <Widget>[
          LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
              debugPrint('$constraints');
              return ScrollConfiguration(
                behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
                child: SingleChildScrollView(
                  scrollDirection: Axis.vertical,
                  child: ConstrainedBox(
                    constraints: BoxConstraints(minHeight: constraints.maxHeight),
                    child: IntrinsicHeight(
                      child: NavigationRail(
                        backgroundColor: Colors.grey[300],
                        unselectedIconTheme: const IconThemeData(color: Color.fromARGB(255, 59, 141, 182)),
                        unselectedLabelTextStyle: const TextStyle(color: Colors.blueGrey),

                        ///
                        elevation: 1.0,

                        ///
                        selectedIndex: _selectedIndex,
                        onDestinationSelected: _destinationSelected,

                        ///
                        minWidth: 56,
                        labelType: NavigationRailLabelType.none,
                        extended: true,
                        minExtendedWidth: 190,

                        ///
                        destinations: const [
                          NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('1')),
                          NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('22')),
                          NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('333')),
                          NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('4444')),
                          NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('55555')),
                          NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('666666')),
                          NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('7777777')),
                          NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('888888888888')),
                        ],
                      ),
                    ),
                  ),
                ),
              );
            },
          ),

          //const VerticalDivider(thickness: 1, width: 1),

          /// This is the main content.
          Expanded(
            child: PageView(
              scrollDirection: Axis.vertical,
              controller: _pageController,
              physics: const NeverScrollableScrollPhysics(),

              ///
              onPageChanged: _pageChanged,
              children: <Widget>[
                Container(
                  color: Colors.blue,
                ),
                Container(
                  color: Colors.green,
                ),
                Container(
                  color: Colors.indigo,
                ),
                Container(
                  color: Colors.pink,
                ),
                Container(
                  color: Colors.orange,
                ),
                Container(
                  color: Colors.red,
                ),
                Container(
                  color: Colors.yellow,
                ),
                Container(
                  color: Colors.teal,
                ),
                Container(
                  color: Colors.cyan,
                ),
                Container(
                  color: Colors.brown,
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}

class AppScrollBehavior extends MaterialScrollBehavior {
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}

Color randomColor() {
  return Color.fromARGB(255, Random().nextInt(256) + 0, Random().nextInt(256) + 0, Random().nextInt(256) + 0);
}

我想我已经解决了。

  1. 大量使用了 SingleChildScrollView 和 IntrinsicWidth 和 IntrinsicHeight 约束。

  2. 基本宽度和高度限制。

代码

import 'dart:math';
import 'dart:ui';

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

import 'custom_lineedit.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        /// This is the theme of your application.

        /// Try running your application with "flutter run". You'll see the
        /// application has a blue toolbar. Then, without quitting the app, try
        /// changing the primarySwatch below to Colors.green and then invoke
        /// "hot reload" (press "r" in the console where you ran "flutter run",
        /// or simply save your changes to "hot reload" in a Flutter IDE).
        /// Notice that the counter didn't reset back to zero; the application
        /// is not restarted.
        primarySwatch: Colors.blue,
        textTheme: GoogleFonts.robotoMonoTextTheme(Theme.of(context).textTheme),
      ),
      scrollBehavior: AppScrollBehavior().copyWith(scrollbars: false),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  /// This widget is the home page of your application. It is stateful, meaning
  /// that it has a State object (defined below) that contains fields that affect
  /// how it looks.

  /// This class is the configuration for the state. It holds the values (in this
  /// case the title) provided by the parent (in this case the App widget) and
  /// used by the build method of the State. Fields in a Widget subclass are
  /// always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;
  final PageController _pageController = PageController();

  _pageChanged(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  _destinationSelected(int index) {
    setState(() {
      _selectedIndex = index;
      _pageController.jumpToPage(index);
    });
  }

  @override
  void initState() {
    //windowManager.addListener(this);
    super.initState();
    //_pageController = PageController();
    _pageController.addListener(() {
      // double offset = _pageController.offset;
      // double? page = _pageController.page;
    });
  }

  @override
  void dispose() {
    //windowManager.removeListener(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    /// This method is rerun every time setState is called, for instance as done
    /// by the _incrementCounter method above.
    ///
    /// The Flutter framework has been optimized to make rerunning build methods
    /// fast, so that you can just rebuild anything that needs updating rather
    /// than having to individually change instances of widgets.
    return Scaffold(
      body: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return SingleChildScrollView(
            controller: ScrollController(),
            scrollDirection: Axis.horizontal,
            physics: const NeverScrollableScrollPhysics(),
            child: ConstrainedBox(
              constraints: BoxConstraints(minWidth: constraints.maxWidth),
              child: IntrinsicWidth(
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                    SingleChildScrollView(
                      controller: ScrollController(),
                      scrollDirection: Axis.vertical,
                      child: ConstrainedBox(
                        constraints: BoxConstraints(minHeight: constraints.maxHeight),
                        child: IntrinsicHeight(
                          child: NavigationRail(
                            backgroundColor: Colors.grey[300],
                            unselectedIconTheme: const IconThemeData(color: Color.fromARGB(255, 59, 141, 182)),
                            unselectedLabelTextStyle: const TextStyle(color: Colors.blueGrey),
                            elevation: 1.0,
                            selectedIndex: _selectedIndex,
                            onDestinationSelected: _destinationSelected,
                            minWidth: 40,
                            labelType: NavigationRailLabelType.none,
                            extended: true,
                            minExtendedWidth: 180,
                            destinations: const [
                              NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('1')),
                              NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('22')),
                              NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('333')),
                              NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('4444')),
                              NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('55555')),
                              NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('666666')),
                              NavigationRailDestination(icon: Icon(Icons.label_outline), label: Text('7777777')),
                              NavigationRailDestination(
                                  icon: Icon(Icons.label_outline),
                                  label: SizedBox(
                                      width: 120,
                                      child: Text(
                                          '8888888888888888888888',
                                          maxLines: 1,
                                          overflow: TextOverflow.ellipsis,
                                      ),
                                  ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),

                    //const VerticalDivider(thickness: 1, width: 1),

                    /// This is the main content.
                    Expanded(
                      child: Container(
                        width: 400,
                        height: 400,
                        color: Colors.white,
                        child: PageView(
                          scrollDirection: Axis.vertical,
                          //physics: const NeverScrollableScrollPhysics(),
                          controller: _pageController,

                          onPageChanged: _pageChanged,
                          children: <Widget>[
                            //const SignPage(),
                            Container(),
                            Container(
                              padding: const EdgeInsets.all(10),
                              child: SingleChildScrollView(
                                controller: ScrollController(),
                                //physics: const NeverScrollableScrollPhysics(),
                                child: Column(
                                  children: [
                                    CuostomLineEdit(
                                      rowLable: "json     :",
                                      child: OutlinedButton(onPressed: () {}, child: const Text('Enabled')),
                                    ),
                                    CuostomLineEdit(
                                      rowLable: "json123  :",
                                      child: OutlinedButton(onPressed: () {}, child: const Text('Enabled')),
                                    ),
                                    const CuostomLineEdit(
                                      rowLable: "json1234 :",
                                      child: Spacer(),
                                      //child: OutlinedButton(onPressed: () {}, child: const Text('Enabled')),
                                    )
                                  ],
                                ),
                              ),
                            ),
                            Container(
                              color: Colors.blue,
                            ),
                            Container(
                              color: Colors.green,
                            ),
                            Container(
                              color: Colors.indigo,
                            ),
                            Container(
                              color: Colors.pink,
                            ),
                            Container(
                              color: Colors.orange,
                            ),
                            Container(
                              color: Colors.red,
                            ),
                            Container(
                              color: Colors.yellow,
                            ),
                            Container(
                              color: Colors.teal,
                            ),
                            Container(
                              color: Colors.cyan,
                            ),
                            Container(
                              color: Colors.brown,
                            ),
                          ],
                        ),
                      ),
                    )
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

class AppScrollBehavior extends MaterialScrollBehavior {
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}

Color randomColor() {
  return Color.fromARGB(255, Random().nextInt(256) + 0, Random().nextInt(256) + 0, Random().nextInt(256) + 0);
}