Я создаю экран с данными из некоторых математических задач, но я новичок во 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 трюков, которые я делал, и мне сложно их поддерживать, может кто-нибудь показать мне другой способ сделать это?
Структура, которую вы используете, на самом деле не так уж плоха, но если вы хотите посмотреть на другой подход, вы можете взглянуть на 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')),
],
),
],
);
}
}
Для этого есть официальное видео.
Если вы хотите разместить свои виджеты внутри экрана, вы можете использовать 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')),
]
),
],
),
)
],
)
);
Rowпредназначена для того, чтобы иметь несколько детей. Я бы не стал использовать его, если у него только один ребенок. Вместо этого вы можете использоватьAlign