I currently have 3 Widgets to create the main page of my app. The first, body.dart, is where the majority of my main page resides. It uses receives a screenType to resize the screen based on what the size of the device is. This works fine, but I want to add the ability to sort the data in the body.dart. But the button to initiate this change resides in another class, home.dart. Between the two is a ResponsiveLayout class which handles figuring out the screen size and calling the Body constructor with the screen size.
我目前有3个小工具来创建我的应用程序的主页。第一个是body.dart,它是我的主要主页所在的位置。它使用接收屏幕类型来根据设备的大小调整屏幕大小。这可以很好地工作,但我想添加对body.dart中的数据进行排序的功能。但启动此更改的按钮位于另一个类home.dart中。在这两者之间的是一个ResponsiveLayout类,它处理计算屏幕大小并调用具有屏幕大小的主体构造函数。
Here are my classes:
以下是我的课程:
body.dart:
身体.省道:
class Body extends StatefulWidget {
final service = IsarService();
final int screenType;
Body({super.key, required this.screenType});
@override
State<Body> createState() => _BodyState();
}
class _BodyState extends State<Body> {
Sort _s = Sort.desc;
SortField _sortField = SortField.name;
void _changeSort(Sort s) {
setState(() {
_s = s;
});
}
void _changeSortField(SortField sortField) {
setState(() {
_sortField = sortField;
});
}
ScreenSize _getScreenSize(context) {
switch (widget.screenType) {
case 0:
return ScreenSize(
MediaQuery.of(context).size.width * 0.3,
MediaQuery.of(context).size.height * 0.4,
MediaQuery.of(context).size.width * 0.325,
100.0,
10.0);
case 1:
return ScreenSize(
MediaQuery.of(context).size.width * 0.325,
MediaQuery.of(context).size.height * 0.425,
MediaQuery.of(context).size.width * 0.325,
100.0,
10.0);
default: //desktop
return ScreenSize(200.0, 320.0, 200.0, 100.0, 12.0);
}
}
late ScreenSize screenSize;
late Offset tapXY;
late RenderBox overlay;
@override
Widget build(BuildContext context) {
screenSize = _getScreenSize(context);
overlay = Overlay.of(context).context.findRenderObject() as RenderBox;
return Column(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: StreamBuilder<List<Plant>>(
stream: widget.service.listenToPlantsWithSort(_s, _sortField), //I want to change _s and _sortField from home.dart
builder: (context, snapshot) => Wrap(
children: snapshot.hasData
? snapshot.data!.map((plant) {
return InkWell(
borderRadius: BorderRadius.circular(15.0),
onTapDown: getPosition,
onLongPress: () => showMenu(
context: context,
position: relRectSize,
items: <PopupMenuEntry>[
PopupMenuItem(
child: const Text('Edit'),
onTap: () => {},
),
PopupMenuItem(
child: const Text('Delete'),
onTap: () =>
{widget.service.deletePlant(plant.id)},
),
],
useRootNavigator: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Card(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
children: [
Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: const Color.fromARGB(
255, 161, 160, 159),
borderRadius:
BorderRadius.circular(5.0),
),
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: screenSize.imgMaxWidth,
maxHeight: screenSize.imgMaxHeight,
),
child: ClipRRect(
borderRadius:
BorderRadius.circular(3),
child: plant.image!.length > 1
? Image.memory(
Uint8List.fromList(
plant.image!),
fit: BoxFit.cover)
: Image.asset(
'assets/img/test.jpg',
fit: BoxFit.cover)),
),
),
Container(
constraints: BoxConstraints(
maxWidth: screenSize.tagsMaxWidth,
maxHeight: screenSize.tagsMaxHeight,
),
child: CardTags(
plant: plant,
fontSize: screenSize.fontSize,
),
),
],
),
),
),
],
),
);
}).toList()
: [],
),
),
),
),
],
);
}
responsive_layout.dart:
响应布局.DART:
class ResponsiveLayout extends StatelessWidget {
ResponsiveLayout({super.key});
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
double width = constraints.maxWidth;
switch (width) {
case < 400:
return Body(screenType: ScreenType.mobile.index);
case < 600:
return Body(screenType: ScreenType.tablet.index);
default:
return Body(screenType: ScreenType.desktop.index);
}
});
}
}
home.dart (Where I want to be able to change the state of Body):
Home.Dart(我希望能够在其中更改身体状态):
class HomePage extends StatelessWidget {
void _showSimpleModalDialog(context) {
showDialog(
context: context,
builder: (BuildContext context) {
return const CreatePlantForm();
});
}
HomePage({super.key});
SortField sortField = SortField.name;
Sort s = Sort.desc;
final service = IsarService();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(MediaQuery.of(context).size.width.toString()),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const SettingsScreen(),
),
);
},
),
IconButton(
icon: const Icon(Icons.filter_alt),
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.filter_list_rounded),
onPressed: () {
s == Sort.desc ? s = Sort.asc : s = Sort.desc;
//Where I want to redraw the Body
print(s);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
service.deleteDB();
},
),
],
),
body: ResponsiveLayout(),
floatingActionButton: FloatingActionButton(
onPressed: () => {
//open modal
_showSimpleModalDialog(context)
},
tooltip: 'Add Plant',
child: const Icon(Icons.add),
),
);
}
}
I tried looking at examples but many of them are one class to another, and I'm not sure how that applies in my case since I have the ResposiveLayout.
我尝试查看示例,但其中许多都是一个类对另一个类,我不确定这是否适用于我的情况,因为我有ResposveLayout。
更多回答
I was able to solve this by using riverpod to create providers for both the s and sortField. Code below:
我能够通过使用Riverpod为S和sortfield创建提供程序来解决这个问题。代码如下:
final sProvider = StateProvider<Sort>((ref) => Sort.desc);
final sortFieldProvider = StateProvider<SortField>((ref) => SortField.name);
And then I changed the onPressed of the sort button in the Home widget to:
然后,我将Home小部件中的Sort按钮的onPress更改为:
onPressed: () {
ref.watch(sProvider) == Sort.desc
? ref.read(sProvider.notifier).state = Sort.asc
: ref.read(sProvider.notifier).state = Sort.desc;
print(ref.watch(sProvider));
},
Finally, I changed Body from a stateful widget to extend ConsumerWidget and could then access the providers from my stream:
最后,我将Body从有状态小部件更改为扩展Consumer erWidget,然后可以从我的流访问提供者:
stream: service.listenToPlantsWithSort(ref.watch(sProvider), ref.watch(sortFieldProvider))
更多回答
我是一名优秀的程序员,十分优秀!