Более эффективный способ размещения виджетов на экране — Flutter

Я создаю экран с данными из некоторых математических задач, но я новичок во Flutter, и мне кажется очень сложным размещать вещи в фиксированных местах, не создавая беспорядка, поскольку я не знаю кучу виджетов, которые могут мне помочь. , и я почти уверен, что есть более простой способ сделать этот экран, поэтому я хочу спросить, может ли кто-нибудь помочь мне с этим.

Этот экран - результат, который я хочу

И это код, который я сделал:

import 'package:flutter/material.dart';

class ProblemsScreen extends StatefulWidget {
  const ProblemsScreen({super.key});

  @override
  State<ProblemsScreen> createState() => _ProblemsScreenState();
}

class _ProblemsScreenState extends State<ProblemsScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: const Text('Problem title',
            style: TextStyle(
            color: Colors.white,
            fontSize: 30,
            fontWeight: FontWeight.w300
            ),
          ),
          centerTitle: true,
      ),

      body: Container(
        padding: const EdgeInsets.all(20),
        child:Stack(
          children: <Widget>[
            
            //Timer counter
            const Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('00:00')
              ],
            ),

            //Timer Icon
            const Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                Icon(Icons.timer)
              ],
            ),

            //Problem data, will be a long string later
            const Center(
              child: Text('Problem data'),
            ),
      
            //Button grid with a label
            Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                const Text('Select an asnwer'), //Label

                //Button grid
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Column(
                      children: [
                        Row(
                          children: [
                            TextButton(onPressed: (){}, child: const Text('Answer 1')), 
                            TextButton(onPressed: (){}, child: const Text('Answer 2')),                               
                          ]
                        ),

                        Row(
                          children: [
                            TextButton(onPressed: (){}, child: const Text('Answer 3')), 
                            TextButton(onPressed: (){}, child: const Text('Answer 4')),                               
                          ]
                        )
                      ],
                    )
                  ],
                )
              ],
            ),
          ],
        ),
      ),
    );
  }
}

Как видите, это полный беспорядок из-за stack-row-column трюков, которые я делал, и мне сложно их поддерживать, может кто-нибудь показать мне другой способ сделать это?

Row предназначена для того, чтобы иметь несколько детей. Я бы не стал использовать его, если у него только один ребенок. Вместо этого вы можете использовать Align
Ivo 01.08.2023 13:03
1
1
51
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Структура, которую вы используете, на самом деле не так уж плоха, но если вы хотите посмотреть на другой подход, вы можете взглянуть на FlutterFlow.

Домашняя страница FlutterFlow

Таким образом, вам не придется иметь дело с таким кодом.

Ответ принят как подходящий

Вы можете использовать widgets или helper methods. Вам не нужно использовать виджет Stack as Container. Виджет-контейнер может быть столбцом, потому что макет идет сверху вниз. И обратитесь к комментарию Иво, вы можете использовать Align вместо Row.

рефакторинг кода, как показано ниже

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const ProblemsScreen(),
    );
  }
}

class ProblemsScreen extends StatefulWidget {
  const ProblemsScreen({super.key});

  @override
  State<ProblemsScreen> createState() => _ProblemsScreenState();
}

class _ProblemsScreenState extends State<ProblemsScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'Problem title',
          style: TextStyle(
              color: Colors.white, fontSize: 30, fontWeight: FontWeight.w300),
        ),
        centerTitle: true,
      ),
      body: Container(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [
            _buildTimer(),
            const Expanded(
              child: Center(
                child: Text('Problem data'),
              ),
            ),
            _buildAnswers(),
          ],
        ),
      ),
    );
  }

  Widget _buildTimer() {
    return const Stack(
      alignment: Alignment.center,
      children: [
        Text('00:00', textAlign: TextAlign.center),
        Align(alignment: Alignment.centerRight, child: Icon(Icons.timer)),
      ],
    );
  }

  Widget _buildAnswers() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Row(
          mainAxisSize: MainAxisSize.min,
          children: [
          TextButton(onPressed: () {}, child: const Text('Answer 1')),
          TextButton(onPressed: () {}, child: const Text('Answer 2')),
        ],),
        Row(
          mainAxisSize: MainAxisSize.min,
          children: [
          TextButton(onPressed: () {}, child: const Text('Answer 3')),
          TextButton(onPressed: () {}, child: const Text('Answer 4')),
        ],
        ),
      ],
    );
  }
}

Для этого есть официальное видео.

  • виджеты
    • для этого требуется больше шаблонного кода, но Flutter может оптимизировать скорость рендеринга.
    • виджет может быть постоянным.
  • вспомогательные методы
    • вы можете написать меньше кода.
    • проще получить доступ к родительскому полю.

Если вы хотите разместить свои виджеты внутри экрана, вы можете использовать Stack и Alignments для размещения вашего виджета. Вот код для вашей помощи

Container(
      height: double.infinity,
        width: double.infinity,
        padding: const EdgeInsets.all(20),
        child:Stack(
          children: <Widget>[

            //Timer counter
            Align(
              alignment: Alignment.topCenter,
              child: Text('00:00'),
            ),
            Align(
              alignment: Alignment.topRight,
              child: Icon(Icons.timer),
            ),

            //Problem data, will be a long string later
            Align(
              alignment: Alignment.center,
              child: Text('Problem data'),
            ),

            //Button grid with a label
            Align(
              alignment: Alignment.bottomCenter,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  const Text('Select an asnwer'), //Label
                  Row(
                    mainAxisSize: MainAxisSize.min,
                      children: [
                        TextButton(onPressed: (){}, child: const Text('Answer 1')),
                        TextButton(onPressed: (){}, child: const Text('Answer 2')),
                      ]
                  ),
                  Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        TextButton(onPressed: (){}, child: const Text('Answer 2')),
                        TextButton(onPressed: (){}, child: const Text('Answer 3')),
                      ]
                  ),

                ],
              ),
            )

          ],
        )
    );

Другие вопросы по теме