我使用 InkWell 制作了一個按鈕,如果觸摸它會顯示一個 showModalBottomSheet,其中包含 ListView 內的 RadioListTile。默認情況下,該按鈕將顯示文本“Pilih Pedagang”,它會根據我選擇的 RadioListTile 進行更改。
這是代碼:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:untitled/application_color.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int selectedValue = -1;
List<String> merchants = ['Bang Ongot', 'Bang Kotan', 'Bang Bangtut', 'Bang BCA'];
String merchantName = 'Pilih Pedagang';
merchantList() {
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
builder: (context) {
return StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
return SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(children: [
Padding(
padding: const EdgeInsets.only(top: 5, right: 10),
child: Align(
alignment: Alignment.topRight,
child: IconButton(
padding: EdgeInsets.zero,
onPressed: () => Navigator.pop(context),
icon: const Icon(
Icons.close,
color: Color(0xff31708F),
),
),
),
),
SingleChildScrollView(
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.47,
child: ListView.builder(
itemCount: merchants.length,
itemBuilder: (context, index) {
return RadioListTile(
value: index,
groupValue: selectedValue,
title: Text(merchants.elementAt(index)),
secondary: OutlinedButton(
onPressed: () {},
child: const Text('View Profile'),
),
onChanged: (value) {
setState(() =>
selectedValue = value as int);
merchantName = merchants.elementAt(index);
Navigator.pop(context);
},
);
}
),
),
),
]),
);
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChangeNotifierProvider<ApplicationColor>(
create: (BuildContext context) => ApplicationColor(),
child: Scaffold(
appBar: AppBar(
title: const Text(
"Test",
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.black,
),
body: Container(
padding: const EdgeInsets.only(top: 20,),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Align(
alignment: Alignment.topCenter,
child: InkWell(
onTap: merchantList,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
merchantName,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Color(0xff31708F)),
),
const SizedBox(
width: 5,
),
const Icon(
Icons.expand_more,
color: Color(0xff31708F),
),
],
),
),
),
),
),
),
);
}
}
問題是,直到我 CTRL S AndroidStudio 中的代碼,按鈕的文本才會更新。我該如何解決這個問題?
uj5u.com熱心網友回復:
當您setState在模態框內使用時,它只會重建模態框內受影響的小部件,而不是外面的小部件。這是因為您使用的是StatefulBuilder帶有自己的a ,它setState會遮蔽外部。一種方法是洗掉StatefulBuilder或使用另一個名稱,StateSetter以便它不會影響外部setState。雖然這看起來很奇怪,但最好洗掉StatefulBuilder或使merchantList方法異步并await呼叫showModalBottomSheet. setState之后使用更新模態外受影響的小部件。
另一種方法是從您的模式中取回選定的名稱,然后用于setState更新您的螢屏。你這樣做的方法是,當你打電話Navigator.pop,你喜歡這個背景后,提供選擇的名稱:Navigator.pop(context, merchantName);。然后await在呼叫時使用showModalBottomSheet并將回傳的值保存在變數中。之后,setState如果用戶選擇了商家并且回傳的值不為空,則您只需使用更新文本即可。對于您的情況,第一種方法效果很好。但是,如果您需要將代碼從您的小部件中分離出來以顯示模式,那么您可以這樣做。這是完整的代碼:
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int selectedValue = -1;
List<String> merchants = ['Bang Ongot', 'Bang Kotan', 'Bang Bangtut', 'Bang BCA'];
String merchantName = 'Pilih Pedagang';
merchantList() async {
final name = await showModalBottomSheet<String>(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
builder: (context) {
return StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
return SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(children: [
Padding(
padding: const EdgeInsets.only(top: 5, right: 10),
child: Align(
alignment: Alignment.topRight,
child: IconButton(
padding: EdgeInsets.zero,
onPressed: () => Navigator.pop(context),
icon: const Icon(
Icons.close,
color: Color(0xff31708F),
),
),
),
),
SingleChildScrollView(
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.47,
child: ListView.builder(
itemCount: merchants.length,
itemBuilder: (context, index) {
return RadioListTile(
value: index,
groupValue: selectedValue,
title: Text(merchants.elementAt(index)),
secondary: OutlinedButton(
onPressed: () {},
child: const Text('View Profile'),
),
onChanged: (value) {
setState(() => selectedValue = value as int);
merchantName = merchants.elementAt(index);
Navigator.pop(context, merchantName);
},
);
}),
),
),
]),
);
});
});
if (name != null) {
setState(() {
merchantName = name;
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text(
"Test",
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.black,
),
body: Container(
padding: const EdgeInsets.only(
top: 20,
),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Align(
alignment: Alignment.topCenter,
child: InkWell(
onTap: merchantList,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
merchantName,
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.w500, color: Color(0xff31708F)),
),
const SizedBox(
width: 5,
),
const Icon(
Icons.expand_more,
color: Color(0xff31708F),
),
],
),
),
),
),
),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int selectedValue = -1;
List<String> merchants = ['Bang Ongot', 'Bang Kotan', 'Bang Bangtut', 'Bang BCA'];
String merchantName = 'Pilih Pedagang';
merchantList() async {
final name = await showModalBottomSheet<String>(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
builder: (context) {
return StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
return SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(children: [
Padding(
padding: const EdgeInsets.only(top: 5, right: 10),
child: Align(
alignment: Alignment.topRight,
child: IconButton(
padding: EdgeInsets.zero,
onPressed: () => Navigator.pop(context),
icon: const Icon(
Icons.close,
color: Color(0xff31708F),
),
),
),
),
SingleChildScrollView(
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.47,
child: ListView.builder(
itemCount: merchants.length,
itemBuilder: (context, index) {
return RadioListTile(
value: index,
groupValue: selectedValue,
title: Text(merchants.elementAt(index)),
secondary: OutlinedButton(
onPressed: () {},
child: const Text('View Profile'),
),
onChanged: (value) {
setState(() => selectedValue = value as int);
merchantName = merchants.elementAt(index);
Navigator.pop(context, merchantName);
},
);
}),
),
),
]),
);
});
});
if (name != null) {
setState(() {
merchantName = name;
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text(
"Test",
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.black,
),
body: Container(
padding: const EdgeInsets.only(
top: 20,
),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Align(
alignment: Alignment.topCenter,
child: InkWell(
onTap: merchantList,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
merchantName,
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.w500, color: Color(0xff31708F)),
),
const SizedBox(
width: 5,
),
const Icon(
Icons.expand_more,
color: Color(0xff31708F),
),
],
),
),
),
),
),
);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/408833.html
標籤:
