I'm creating an app where the user can choose up to three avatars, my question is how do I make the avatars have the following state: when selected, they have a blue border and the text changes to gray (not selected) to black when selected?
Below is an image of the avatar when selected.
code:
body: GestureDetector(
onTap: () {},
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children: [
SizedBox(
child: CircleAvatar(
backgroundColor: Color(0xfff3e0a6),
radius: 30.0,
backgroundImage: AssetImage('image/person.jpg'),
child: Align(
alignment: Alignment.bottomRight,
child: CircleAvatar(
backgroundColor: Colors.blue,
radius: 12.0,
child: Icon(
Icons.camera_alt,
size: 12.0,
color: Colors.white,
),
),
),
),
),
Padding(
padding: EdgeInsets.all(8),
child: Text(
'avatar1'
),
),
],
),
SizedBox(width: 20,),
Column(
children: [
SizedBox(
child: CircleAvatar(
backgroundColor: Color(0xfff3e0a6),
radius: 30.0,
backgroundImage: AssetImage('image/person.jpg'),
child: Align(
alignment: Alignment.bottomRight,
child: CircleAvatar(
backgroundColor: Colors.blue,
radius: 12.0,
child: Icon(
Icons.camera_alt,
size: 12.0,
color: Colors.white,
),
),
),
),
),
Padding(
padding: EdgeInsets.all(8),
child: Text(
'avatar1'
),
),
],
),
SizedBox(width: 20,),
Column(
children: [
SizedBox(
child: CircleAvatar(
backgroundColor: Color(0xfff3e0a6),
radius: 30.0,
backgroundImage: AssetImage('image/person.jpg'),
child: Align(
alignment: Alignment.bottomRight,
child: CircleAvatar(
backgroundColor: Colors.blue,
radius: 12.0,
child: Icon(
Icons.camera_alt,
size: 12.0,
color: Colors.white,
),
),
),
),
),
Padding(
padding: EdgeInsets.all(8),
child: Text(
'avatar1'
),
),
],
),
],
),
),
),
CodePudding user response:
this is how each avatar and text should behave when selected.
CodePudding user response:
Use Focus
and Builder
to make widget focusable. Check this example below.
import 'package:flutter/material.dart';
void main() {
renderContainer(Widget child) {
return SizedBox(height: 200, width: 200, child: Center(child: child));
}
;
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Row(
children: [
renderContainer(SelectableAvatar()),
renderContainer(SelectableAvatar()),
renderContainer(SelectableAvatar()),
],
),
),
),
);
}
class SelectableAvatar extends StatefulWidget {
const SelectableAvatar({Key? key, this.url}) : super(key: key);
final String? url;
@override
State<SelectableAvatar> createState() => _SelectableAvatarState();
}
class _SelectableAvatarState extends State<SelectableAvatar> {
@override
Widget build(BuildContext context) {
return FocusScope(
child: Focus(
child: Builder(builder: (context) {
final FocusNode focusNode = Focus.of(context);
final bool hasFocus = focusNode.hasFocus;
return GestureDetector(
onTap: () {
if (hasFocus) {
focusNode.unfocus();
} else {
focusNode.requestFocus();
}
},
child: _renderAvatar(hasFocus),
);
}),
),
);
}
Widget _renderAvatar(bool hasFocus) {
final uri = widget.url != null ? Uri.tryParse(widget.url!) : null;
final useDefault = uri == null;
ImageProvider getProvider() {
if (useDefault) {
return const AssetImage('');
}
return NetworkImage(widget.url!);
}
// Render base on hasFocus state
return AnimatedContainer(
duration: const Duration(milliseconds: 100),
width: hasFocus ? 120 : 100,
height: hasFocus ? 120 : 100,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
width: hasFocus ? 5 : 3,
color: hasFocus ? Colors.blue : Colors.black,
),
),
child: CircleAvatar(
foregroundColor: Colors.white,
backgroundImage: getProvider(),
),
);
}
}