嗨,在我的Flutter应用程序中,我必须在几个屏幕上添加复选框。 例如,如果我有6个屏幕,分别是Screen1,Screen2,Screen3,Screen4,Screen5和Screen6,并且我可以从screen1导航到Screen2,从Screen2导航到Screen3,依此类推。
我的屏幕堆栈示例
屏幕1->屏幕2->屏幕3->屏幕4->屏幕5->屏幕6
这里Screen1是我的根,而Screen6是最上面的屏幕。
如果我在Screen1,Screen2,Screen4和Screen6上有一个复选框,则为
Screen1(复选框)-> Screen2(复选框)-> Screen3-> Screen4(复选框)-> Screen5-> Screen6(复选框)
现在的问题是,如果我选中screen6的复选框,那么必须自动选择(选中)所有其他屏幕上的复选框(不传回结果)
我正在使用flutter_block软件包。
请帮助。
已编辑
(在导航器堆栈中)顶部的Screen是Screen4或Screen2时,需要做同样的事情
答案 0 :(得分:0)
为此,您可以使用BLOC,这对于初学者来说可能很难,但是为此,另一个技巧是在单独的dart文件上创建另一个类。假设
show the six checked box as Constants.box1 == "selected" ? Showcheckedbox() : showUncheckedBox()
// ? means if condition is true : means if condition is false
class Constants {
string box1 ;
string box2 ;
string box3 ;
string box4 ;
string box5 ;
}
1. now, when you select the box1 as checked then there you can write it as Constants.box1= "selected";
2. and when you pop the screen there you can setState({}) on pop out the screen.
答案 1 :(得分:0)
使用BLOC可以将复选框存储为一种状态,并使用块events
触发对该状态的配置更改(选中/取消选中选项)。
每次调用/添加事件时,在BLOC中,都应采用先前的状态,进行修改(选中/取消选中一个选项)并发出新的状态。发出新状态时,所有BlocBuilders
都会重新渲染,因此您的所有屏幕都是最新的(这是Flutter BLOC的实际工作方式)。
现在最重要的想法是全局提供所创建的BLOC或使THE SAME BLOC INSTANCE可用于所有屏幕(使用BlocProvider.value
-另请参阅此主题的附加教程)。这样,每次您要使用BlocBuilder
渲染复选框时,在所有屏幕上都会得到相同的复选框/状态。
我为您创建了完整的示例,以说明上述所有内容。只需复制到main.dart并运行。花些时间阅读错误的注释和歉意(如果有的话,要写一点时间)。
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
///
/// I put the checkboxes globally because I do not know how you have access to
/// them but you are free to put whenever you want as soon as they are passed
/// to the BLOC. You can even add them inside the BLOC.
///
final List<Checky> gCheckboxes = [
Checky("Checkbox 1"),
Checky("Checkbox 2"),
Checky("Checkbox 3"),
Checky("Checkbox 4"),
Checky("Checkbox 5"),
Checky("Checkbox 6"),
Checky("Checkbox 7"),
];
void main() {
runApp(CheckyApp());
}
///
/// This widget is the root of your application.
///
class CheckyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// For demo sake I will expose the BLOC globally
return BlocProvider<CheckyCubit>(
create: (context) => CheckyCubit(gCheckboxes),
child: MaterialApp(
title: 'Checky App',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
initialRoute: "/screen_1",
routes: {
'/screen_1': (context) => GenericScreen(1),
'/screen_2': (context) => GenericScreen(2),
'/screen_3': (context) => GenericScreen(3),
'/screen_4': (context) => GenericScreen(4),
'/screen_5': (context) => GenericScreen(5),
'/screen_6': (context) => SummaryScreen(),
},
));
}
}
///
/// A generic screen to demonstrate that data can be accessed among multiple
/// screens
///
class GenericScreen extends StatelessWidget {
///
/// This is used to create the generic screen and navigation buttons
///
final int id;
const GenericScreen(this.id, {Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(children: [
Scaffold(
appBar: AppBar(
title: Text("Checky :: Screen ${this.id}"),
),
body: BlocBuilder<CheckyCubit, CheckyState>(
builder: (context, state) {
return ListView.builder(
itemCount: state.checkboxes.length ?? 0,
itemBuilder: (context, index) =>
// Render the checkbox based on state data from BLOC.
// Here I just emulated the checkbox for the sake of example
GestureDetector(
onTap: () =>
BlocProvider.of<CheckyCubit>(context).toggle(index),
child: Container(
padding: EdgeInsets.all(10),
margin: EdgeInsets.all(5),
color: state.checkboxes[index].isChecked
? Colors.amberAccent
: Colors.white,
child: Text(state.checkboxes[index].label),
),
),
);
},
),
),
// THIS IS NOT IMPORTART FOR YOUR PURPOSE
if (Navigator.of(context).canPop())
Align(
alignment: Alignment.bottomLeft,
child: Container(
margin: EdgeInsets.all(20),
child: FloatingActionButton(
heroTag: "previous_$id",
child: Icon(Icons.chevron_left),
onPressed: () => Navigator.of(context).pop(),
),
),
),
if (this.id <= 5)
Align(
alignment: Alignment.bottomRight,
child: Container(
margin: EdgeInsets.all(20),
child: FloatingActionButton(
heroTag: "next_$id",
child: Icon(Icons.chevron_right),
onPressed: () =>
Navigator.of(context).pushNamed("/screen_${id + 1}"),
),
),
),
]);
}
}
///
/// Last screen where we just display the values by accessing the CheckyBloc.
///
class SummaryScreen extends StatelessWidget {
const SummaryScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(children: [
Scaffold(
appBar: AppBar(
title: Text("Checky :: Summary"),
),
body: BlocBuilder<CheckyCubit, CheckyState>(
builder: (context, state) {
return ListView.builder(
itemCount: state.checkboxes.length ?? 0,
itemBuilder: (context, index) =>
// Render only checked options
state.checkboxes[index].isChecked
? Container(
padding: EdgeInsets.all(10),
margin: EdgeInsets.all(5),
color: state.checkboxes[index].isChecked
? Colors.greenAccent
: Colors.white,
child: Text(state.checkboxes[index].label),
)
: SizedBox.shrink(),
);
},
),
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
margin: EdgeInsets.all(20),
child: FloatingActionButton(
heroTag: "Reset",
child: Icon(Icons.refresh),
onPressed: () {
// Reset the options
BlocProvider.of<CheckyCubit>(context).reset();
// Push to the first screen
Navigator.of(context).pushNamed("/screen_1");
},
),
),
),
]);
}
}
// =============================================================================
///
/// Checkbox entity which stores the label and whether is selected or not.
///
class Checky {
///
/// Checkbox displayed label
///
final String label;
///
/// Tells whether the checkbox is selected
///
bool isChecked;
///
/// Checkbox constructor. Default the checkbox is unchecked.
///
Checky(this.label, {this.isChecked = false});
///
/// Check the checkbox ;)
///
void check() {
this.isChecked = true;
}
///
/// Uncheck the checkbox ;)
///
void uncheck() {
this.isChecked = false;
}
///
/// Uncheck the checkbox ;)
///
void toggle() {
this.isChecked = !this.isChecked;
}
}
///
/// Checkboxes state that is sent from BLOC and only contains a list of
/// checkboxes (current checkboxes configuration).
///
class CheckyState {
///
/// The checkboxes list
///
final List<Checky> checkboxes;
CheckyState(this.checkboxes);
}
///
/// Checkboxes logic. Takes the current state and modifies the checkboxes and
/// then emit the new configuration on the "output" stream.
///
class CheckyCubit extends Cubit<CheckyState> {
///
/// Cubit constructor which emits the first/default checkboxes and their
/// configuration (ehich one are checked or not).
///
CheckyCubit(List<Checky> checkboxes) : super(CheckyState(checkboxes));
// ==================================
// EVENTS
// ==================================
///
/// Toggle a checkbox by index
///
void toggle(int index) async {
// Retrieve the current checkboxes from the last emited state
var checkboxes = this.state.checkboxes;
// Just take some precautions but this depends by your implementation
if (checkboxes != null && checkboxes[index] != null) {
// Toggle the checkbox by given index
checkboxes[index].toggle();
}
// Emit the new state/configuration
emit(CheckyState(checkboxes));
}
///
/// Reset the entire by unchecking all options.
///
void reset() {
// Retrieve the current checkboxes
var checkboxes = this.state.checkboxes;
// Uncheck all of them
checkboxes.forEach((checkbox) {
checkbox.uncheck();
});
// Emit the new state/configuration
emit(CheckyState(checkboxes));
}
}
如果您想进一步了解Flutter BLOC,请观看this series (Flutter BLOC from ZERO to HERO)-特别是第6集,其中介绍了一些可以帮助您解决问题的概念。