如何在此头像上创建选区?
How do I create a selection on this avatar?
我正在创建一个用户最多可以选择三个头像的应用程序,我的问题是如何使头像具有以下状态:选中时,它们具有蓝色边框并且文本变为灰色 (未选中)选中后变黑?
下面是选中后的头像图片。
代码:
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'
),
),
],
),
],
),
),
),
这是每个头像和文本在被选中时的行为方式。
使用 Focus
和 Builder
使小部件可聚焦。检查下面的这个例子。
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(),
),
);
}
}
我正在创建一个用户最多可以选择三个头像的应用程序,我的问题是如何使头像具有以下状态:选中时,它们具有蓝色边框并且文本变为灰色 (未选中)选中后变黑?
下面是选中后的头像图片。
代码:
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'
),
),
],
),
],
),
),
),
这是每个头像和文本在被选中时的行为方式。
使用 Focus
和 Builder
使小部件可聚焦。检查下面的这个例子。
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(),
),
);
}
}