티스토리 뷰
The "Checkbox" is a default widget which displays a "V" sign, based on its bool value. Its customizable feature makes it a go-to choice for many people, eliminating the need to create a totally new widget. However, one downside that its tap area is limited with its borders that might make users feel uncomfortable to touch. You rarely make its size to the maximum, as it is checkbox which is usually small-ones (with 48 being the recommended size for touchable widgets).
I have already a general checkbox class which is called for app’s permissions and policies. It was necessary to make the entire row(where checkbox and some text belonging to it) recognizes all gestures with implementing the main business logics from the parent component.
For implementing this, Listener was used instead of GestureDetector/InkWell. It passes down its functions to the DefaultCheckBox.
Widget _chkBox(
PermissionModel model,
WidgetRef ref,
int idx,
ValueNotifier<Map<PermissionType, bool>> permList,
ValueNotifier<bool> allClicked,
) {
final type = model.type;
return Listener(
onPointerDown: (_) {
// permList.value[type] is a bool value whether it is checked.
final newValue = !permList.value[type]!;
permList.value = permList.value.map((key, value) {
if (key == model.type) {
return MapEntry(key, newValue);
} else {
return MapEntry(key, value);
}
}).cast<PermissionType, bool>();
// Specify whether all permissions items are clicked or not to give a color/text effect for "Allow all"
final clicked = permList.value.entries.where((e) => e.value).toList();
if (clicked.length < permList.value.length) {
allClicked.value = false;
} else {
allClicked.value = true;
}
},
child: Padding(
padding: EdgeInsets.fromLTRB(42.r, 15.r, 20.r, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Column(
children: [
DefaultCheckbox(
isChecked: permList.value[type]!,
// The avobe logis were here before expanding a tap area.
onChange: null,
),
SizedBox(width: 20.r, height: 20.r),
],
),
SizedBox(width: 5.r),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'(${Translator.optional}) ${model.title}',
style: $styles.text.sp14.copyWith(color: Colors.black),
),
SizedBox(height: 6.r),
Text(
model.desc,
style: $styles.text.sp12.copyWith(color: AppColors.hint02),
),
],
)
],
),
),
);
}
The ”onChange" function must be null for the Checkbox for setup, but assign your “onChange" to “Listener” so that it interacts with the upper one.
class DefaultCheckbox extends HookConsumerWidget {
DefaultCheckbox({
Key? key,
required this.isChecked,
this.onChange,
this.size,
this.checkColor,
this.fillColor1,
this.fillColor2,
this.borderColor,
});
bool isChecked;
ValueChanged<bool?>? onChange;
double? size;
Color? checkColor;
Color? fillColor1;
Color? fillColor2;
Color? borderColor;
@override
Widget build(BuildContext context, WidgetRef ref) {
return Listener(
onPointerDown: (_) => onChange?.call(!isChecked),
child: SizedBox(
width: size ?? 15.r,
height: size ?? 15.r,
child: Checkbox(
value: isChecked,
onChanged: (value) {},
side: BorderSide(
color: borderColor ?? AppColors.main03,
width: 1.w,
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(100)),
checkColor: checkColor ?? Colors.white,
fillColor: MaterialStateColor.resolveWith(
(states) {
if (states.contains(MaterialState.pressed) || states.contains(MaterialState.selected)) {
return fillColor1 ?? AppColors.main03;
}
return fillColor2 ?? Colors.white;
},
),
),
),
);
}
}
I found this way a great workaround to expand tap area without using specific libraries designed for that, however keep in mind that the best solution depends on your specific case. Choose the method that best fits your need and preferences. 🥺
'App > Flutter' 카테고리의 다른 글
- Total
- Today
- Yesterday
- retrofit_generator_conflicts_with_freezed
- KotlinFlow
- android_domain
- Kotlin
- Laravel
- Android
- phplaravel
- FlutterWirelessDebuginAOS
- dagger-hilt
- WirelessDebug
- FirebaseConfigurationForMultipleBuildTypes
- android_app_links_domain
- flutter_storage_not_working_for_the_first_time
- MultipleFirebaseEnvironments
- retrofit_generator
- laravel9
- android_app_link_domain_works_with_adb_but_not_works_with_browser
- flutter_secure_storage_issue_iOS
- querydsl5.0.0jakarta
- querydslKotlinError
- futter_api
- AndroidWirelessDebug
- querydslQclass
- RunAFlutterProjectIniPhoneFromVSCode
- unsplashAPI
- mvvm
- retrofit_toJson()_error
- flutter
- android_app_links
- flutter_android_app_links
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |