当子组件更改状态时,使用通知程序的组件不会更新
state_provider.dart
class StateProvider extends ChangeNotifier {
// user data
String _name = '';
String _phoneNumber = '';
String _email = '';
String? _gender;
String _locationSerachText = '';
Map<String, dynamic> _viewPort = {};
final List<String> _tags = [];
List<LocationCard> _locationCards = [];
// Getters for user data
String get name => _name;
String get phoneNumber => _phoneNumber;
String get email => _email;
String? get gender => _gender;
Map<String, dynamic> get viewPort => _viewPort;
String get locationSerachText => _locationSerachText;
List<String> get tags => _tags;
List<LocationCard> get locationCards => _locationCards;
// Setters for user data
set name(String value) {
_name = value;
notifyListeners();
}
set viewPort(Map<String, dynamic> value) {
_viewPort = value;
notifyListeners();
}
set locationSerachText(String value) {
_locationSerachText = value;
notifyListeners();
}
set locationCards(List<LocationCard> value) {
_locationCards = value;
notifyListeners();
}
set phoneNumber(String value) {
_phoneNumber = value;
notifyListeners();
}
set email(String value) {
_email = value;
notifyListeners();
}
set gender(String? value) {
_gender = value;
notifyListeners();
}
// Method to add tag
void addTag(String tag) {
_tags.add(tag);
notifyListeners();
}
// Method to remove tag
void removeTag(String tag) {
_tags.remove(tag);
notifyListeners();
}
}
powerup_profile_screen.dart
class PowerUpProfileScreen extends StatefulWidget {
@override
_PowerUpProfileScreenState createState() => _PowerUpProfileScreenState();
}
class _PowerUpProfileScreenState extends State<PowerUpProfileScreen> {
@override
Widget build(
BuildContext context,
) {
final stateProvider = Provider.of<StateProvider>(context, listen: true);
bool isAtLeastOneTagSelected() {
return stateProvider.tags.isNotEmpty;
}
Color getFinishButtonColor() {
return isAtLeastOneTagSelected() ? Colors.blue : Colors.grey;
}
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: SvgPicture.asset('assets/icons/back-arrow.svg'),
onPressed: () {
Navigator.of(context).pop();
},
),
actions: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 100.0),
child: buildDotsDecorator(
2,
List.generate(3, (index) => 'Page $index'),
),
)
],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 5.0),
child: Container(
color: GuideroTheme.darkTheme.primaryColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const CustomHeaderText(text: 'Power up your profile'),
const SizedBox(
height: 12,
),
const ParagrapghText(
text: 'Choose tags that match your expertise and interests',
fontSize: 16,
textAlign: TextAlign.left,
),
const SizedBox(
height: 16.0,
),
const ParagrapghText(
text: 'You can select more than one tag',
fontSize: 16,
textAlign: TextAlign.left,
),
const SizedBox(
height: 32.0,
),
buildTagCards([
'Cafes & Pubs',
'Resorts',
'Hotels',
'Social Events',
'Tourist Spots'
]),
const Spacer(),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: CustomTextButton(
text: 'Finish',
onPressed: isAtLeastOneTagSelected()
? () {
print("finish clicked ");
}
: null,
backgroundColor: getFinishButtonColor(),
),
),
],
),
),
),
);
}
Widget buildTagCards(List<String> tagTexts) {
return Wrap(
spacing: 30.0,
runSpacing: 16.0,
alignment: WrapAlignment.start,
children: tagTexts.map((tagText) {
return TagCard(
tagText: tagText,
);
}).toList(),
);
}
}
在 TagCard 小部件内,可以添加和删除标签 👇🏽
class TagCard extends StatefulWidget {
final String tagText;
TagCard({Key? key, required this.tagText}) : super(key: key);
@override
State<TagCard> createState() => _TagCardState();
}
class _TagCardState extends State<TagCard> {
bool isSelected = false;
@override
Widget build(BuildContext context) {
final stateProvider = Provider.of<StateProvider>(context);
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(99),
border: Border.all(
color: isSelected ? Colors.white : Colors.white.withOpacity(0.5),
width: 1),
color: Colors.transparent,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: () {
isSelected = stateProvider.tags.any(
(tag) => tag.toLowerCase() == widget.tagText.toLowerCase());
print('Tag tapped: ${widget.tagText}');
print('Tag selected: $isSelected');
if (isSelected) {
stateProvider.tags.remove(widget.tagText);
} else {
stateProvider.tags.add(widget.tagText);
}
setState(() {
isSelected = !isSelected;
});
print("other tags ${stateProvider.viewPort}");
print('Selcted tags : ${stateProvider.tags}');
},
child: Text(
widget.tagText,
style: const TextStyle(
color: Colors.white,
fontSize: 16.0,
fontWeight: FontWeight.w500),
),
),
],
),
);
}
}
按钮颜色相应改变👇🏽
final stateProvider = Provider.of<StateProvider>(context, listen: true);
bool isAtLeastOneTagSelected() {
return stateProvider.tags.isNotEmpty;
}
Color getFinishButtonColor() {
return isAtLeastOneTagSelected() ? Colors.blue : Colors.grey;
}
当选择/删除标签时,状态不会反映在父组件中。 如何解决这个问题💁🏽u200d♂️
尝试直接获取值
backgroundColor: stateProvider.tags.isNotEmpty ? Colors.blue : Colors.grey;
我会简化你的
TagCard
小部件,并与 Flutter 中具有类似行为的许多其他小部件一样(CheckBox
,Switch
,Radio
,...),使其不保持任何状态。相反,当 TagCard
的状态需要更改时,小部件会调用 [onSelect] 或 [onDeselect] 回调,并且使用标签卡的小部件将侦听回调,相应地更新状态并使用新值重建复选框更新标签卡的视觉外观。
class TagCard extends StatelessWidget {
final String tagText;
final bool isSelected;
final VoidCallback onSelect;
final VoidCallback onDeselect;
TagCard({Key? key, required this.tagText,required this.isSelected, required this.onSelect, required this.onDeselect,}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
...
GestureDetector(
onTap: () {
isSelected ? onDeselect() : onSelect();
},
child: Text(
tagText,
...
}
}
Widget buildTagCards(final stateProvider, List<String> tagTexts) {
return Wrap(
spacing: 30.0,
runSpacing: 16.0,
alignment: WrapAlignment.start,
children: tagTexts.map((tagText) {
return TagCard(
tagText: tagText,
isSelected: stateProvider.tags.contains(tagText),
onSelect: () => stateProvider.tags.add(tagText),
onDeselect: () => stateProvider.tags.remove(tagText),
);
}).toList(),
);
}