147 lines
3.9 KiB
Dart
147 lines
3.9 KiB
Dart
/// Custom App Bar Widget
|
|
///
|
|
/// Reusable app bar with consistent styling across the app
|
|
library;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|
import '../../core/constants/ui_constants.dart';
|
|
|
|
/// Custom app bar with consistent styling
|
|
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
final String title;
|
|
final List<Widget>? actions;
|
|
final Widget? leading;
|
|
final bool centerTitle;
|
|
final Color? backgroundColor;
|
|
final Color? foregroundColor;
|
|
final double elevation;
|
|
final PreferredSizeWidget? bottom;
|
|
final bool automaticallyImplyLeading;
|
|
|
|
const CustomAppBar({
|
|
super.key,
|
|
required this.title,
|
|
this.actions,
|
|
this.leading,
|
|
this.centerTitle = true,
|
|
this.backgroundColor,
|
|
this.foregroundColor,
|
|
this.elevation = AppElevation.none,
|
|
this.bottom,
|
|
this.automaticallyImplyLeading = true,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AppBar(
|
|
title: Text(title),
|
|
actions: actions,
|
|
leading: leading,
|
|
centerTitle: centerTitle,
|
|
backgroundColor: backgroundColor,
|
|
foregroundColor: foregroundColor,
|
|
elevation: elevation,
|
|
bottom: bottom,
|
|
automaticallyImplyLeading: automaticallyImplyLeading,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Size get preferredSize =>
|
|
Size.fromHeight(AppBarSpecs.height + (bottom?.preferredSize.height ?? 0));
|
|
}
|
|
|
|
/// Transparent app bar for overlay scenarios
|
|
class TransparentAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
final String? title;
|
|
final List<Widget>? actions;
|
|
final Widget? leading;
|
|
final bool centerTitle;
|
|
final Color? foregroundColor;
|
|
|
|
const TransparentAppBar({
|
|
super.key,
|
|
this.title,
|
|
this.actions,
|
|
this.leading,
|
|
this.centerTitle = true,
|
|
this.foregroundColor,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AppBar(
|
|
title: title != null ? Text(title!) : null,
|
|
actions: actions,
|
|
leading: leading,
|
|
centerTitle: centerTitle,
|
|
backgroundColor: Colors.transparent,
|
|
foregroundColor: foregroundColor ?? Colors.white,
|
|
elevation: 0,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Size get preferredSize => const Size.fromHeight(AppBarSpecs.height);
|
|
}
|
|
|
|
/// Search app bar with search field
|
|
class SearchAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
final String hintText;
|
|
final ValueChanged<String>? onChanged;
|
|
final ValueChanged<String>? onSubmitted;
|
|
final VoidCallback? onClear;
|
|
final TextEditingController? controller;
|
|
final bool autofocus;
|
|
final Widget? leading;
|
|
|
|
const SearchAppBar({
|
|
super.key,
|
|
this.hintText = 'Tìm kiếm...',
|
|
this.onChanged,
|
|
this.onSubmitted,
|
|
this.onClear,
|
|
this.controller,
|
|
this.autofocus = false,
|
|
this.leading,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AppBar(
|
|
leading:
|
|
leading ??
|
|
IconButton(
|
|
icon: const FaIcon(FontAwesomeIcons.arrowLeft, size: 20),
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
),
|
|
title: TextField(
|
|
controller: controller,
|
|
autofocus: autofocus,
|
|
onChanged: onChanged,
|
|
onSubmitted: onSubmitted,
|
|
style: const TextStyle(color: Colors.white),
|
|
decoration: InputDecoration(
|
|
hintText: hintText,
|
|
hintStyle: TextStyle(color: Colors.white.withOpacity(0.7)),
|
|
border: InputBorder.none,
|
|
suffixIcon: controller?.text.isNotEmpty ?? false
|
|
? IconButton(
|
|
icon: const FaIcon(FontAwesomeIcons.xmark, color: Colors.white, size: 18),
|
|
onPressed: () {
|
|
controller?.clear();
|
|
onClear?.call();
|
|
},
|
|
)
|
|
: null,
|
|
),
|
|
),
|
|
elevation: AppElevation.none,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Size get preferredSize => const Size.fromHeight(AppBarSpecs.height);
|
|
}
|