forked from suesitran/public_chat
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
1,537 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
class ButtonWithPopup<T> extends StatefulWidget { | ||
const ButtonWithPopup( | ||
{ | ||
// required this.onChanged, | ||
required this.items, | ||
this.onTap, | ||
required this.child}); | ||
// final Function(T) onChanged; | ||
final List<DropdownMenuItem<T>> items; | ||
final Widget child; | ||
final Function()? onTap; | ||
@override | ||
_ButtonWithPopupState<T> createState() => _ButtonWithPopupState<T>(); | ||
} | ||
|
||
class _ButtonWithPopupState<T> extends State<ButtonWithPopup<T>> { | ||
String? selectedItem; | ||
final LayerLink _layerLink = LayerLink(); | ||
|
||
void _onDropdownTap() async { | ||
print('onDropdownTap'); | ||
// Khi đã có dữ liệu, hiển thị dropdown items | ||
if (widget.items.isNotEmpty) { | ||
print('items không rỗng'); | ||
_showOverlay(); //ko do day | ||
} else { | ||
print('items rỗng'); | ||
// MsgDialog.showError(msg: 'Không tải được dữ liệu!'); | ||
} | ||
} | ||
|
||
final GlobalKey _key = GlobalKey(); | ||
OverlayEntry? _overlayEntry; | ||
void _showOverlay() { | ||
print('show overlay'); | ||
//null check | ||
final renderBox = _key.currentContext!.findRenderObject() as RenderBox; | ||
final size = renderBox.size; | ||
print('size (dropdownNoFetchItems): $size'); | ||
final position = renderBox.localToGlobal(Offset.zero); | ||
|
||
// Tính chiều cao của popup dựa trên số lượng items | ||
double popupHeight = widget.items.length * 50.0; // Giả sử mỗi item cao 58px | ||
// final offset = renderBox.localToGlobal(Offset.zero); | ||
// Lấy chiều cao màn hình | ||
// Tính khoảng cách từ vị trí widget đến mép trên | ||
double distanceToTop = position.dy; | ||
|
||
// Tính khoảng cách offset để giữ popup cách mép trên 100 pixels nếu cần thiết | ||
double offsetY = -popupHeight; | ||
if (distanceToTop - popupHeight < 20) { | ||
//cach mep tren man hinh 20 | ||
offsetY = -distanceToTop + 20; | ||
} | ||
_overlayEntry = OverlayEntry( | ||
builder: (context) => Stack( | ||
children: [ | ||
GestureDetector( | ||
onTap: () { | ||
_removeOverlay(); // Call this when tapping outside | ||
}, | ||
child: Container( | ||
color: Colors.transparent, // Transparent barrier | ||
), | ||
), | ||
Positioned( | ||
// left: offset.dx, | ||
// top: offset.dy + size.height, | ||
width: size.width, | ||
// width: _key.currentContext!.size!.width, | ||
child: CompositedTransformFollower( | ||
//để popup luôn di chuyển theo field khi cuộn | ||
link: _layerLink, | ||
showWhenUnlinked: false, | ||
offset: Offset(0, offsetY), | ||
// offset: Offset(0, -popupHeight), | ||
// offset: Offset(0, _key.currentContext!.size!.height), | ||
child: Material( | ||
elevation: 2.0, | ||
child: ConstrainedBox( | ||
constraints: BoxConstraints( | ||
maxHeight: popupHeight, // Đặt chiều cao tối đa của popup | ||
), | ||
child: ListView( | ||
padding: EdgeInsets.zero, | ||
shrinkWrap: true, | ||
children: widget.items.map((item) { | ||
return SizedBox( | ||
height: 50, | ||
child: ListTile( | ||
title: item.child, | ||
onTap: () { | ||
item.onTap?.call(); | ||
// setState(() { | ||
// selectedItem = (item.child as Text).data; | ||
// }); | ||
// if (item.value != null) { | ||
// widget.onChanged(item.value!); | ||
// } | ||
_removeOverlay(); | ||
}, | ||
), | ||
); | ||
}).toList(), | ||
), | ||
), | ||
), | ||
), | ||
), | ||
], | ||
), | ||
); | ||
|
||
Overlay.of(context).insert(_overlayEntry!); | ||
} | ||
|
||
void _removeOverlay() { | ||
_overlayEntry?.remove(); | ||
_overlayEntry = null; | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
// const lightgrey = const Color.fromRGBO(237, 237, 237, 1); | ||
// const darkgrey = const Color.fromRGBO(104, 102, 102, 1); | ||
return CompositedTransformTarget( | ||
link: _layerLink, | ||
child: GestureDetector( | ||
key: _key, | ||
onTap: widget.onTap, | ||
onLongPress: _onDropdownTap, | ||
behavior: HitTestBehavior.opaque, | ||
onTapDown: (details) { | ||
if (_overlayEntry != null) { | ||
_removeOverlay(); | ||
} | ||
}, // Điều khiển khi tap vào dropdown | ||
child: Material( | ||
child: widget.child, | ||
)), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
class MyFilterChipButton extends StatelessWidget { | ||
const MyFilterChipButton({ | ||
super.key, | ||
required this.onSelected, | ||
required this.label, | ||
required this.selected, | ||
}); | ||
final void Function(bool) onSelected; | ||
final String label; | ||
final bool selected; | ||
@override | ||
Widget build(BuildContext context) { | ||
return FilterChip( | ||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), | ||
label: Text(label), | ||
selected: selected, //t//bloc.hasLyric && | ||
// selected: bloc.isHighLightMode,//f | ||
disabledColor: Colors.grey, | ||
selectedColor: Colors.black, | ||
onSelected: (bool value) { | ||
onSelected(value); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
class MyCloseButton extends StatelessWidget { | ||
const MyCloseButton({super.key, required this.onPressed}); | ||
final void Function() onPressed; | ||
@override | ||
Widget build(BuildContext context) { | ||
return IconButton( | ||
icon: Container( | ||
decoration: const BoxDecoration( | ||
shape: BoxShape.circle, | ||
color: Colors.grey, | ||
), | ||
child: const Icon(Icons.close, size: 20)), //24 | ||
padding: EdgeInsets.zero, // Không có padding | ||
constraints: const BoxConstraints(), // Loại bỏ các ràng buộc mặc định | ||
onPressed: onPressed, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
// ignore: must_be_immutable | ||
class MyElevatedButton extends StatelessWidget { | ||
const MyElevatedButton( | ||
{super.key, | ||
required this.onPressed, | ||
required this.buttonName, | ||
this.textColor, | ||
this.backgroundColor, | ||
this.width, | ||
this.height}); | ||
final String buttonName; | ||
final Function()? onPressed; | ||
final Color? textColor; | ||
final Color? backgroundColor; | ||
final double? width; | ||
final double? height; | ||
@override | ||
Widget build(BuildContext context) { | ||
return ElevatedButton( | ||
style: ButtonStyle( | ||
// fixedSize:MaterialStatePropertyAll(Size(width??,height)), | ||
// textStyle: MaterialStatePropertyAll( | ||
// GoogleFonts.sarabun( | ||
// color: textColor, fontWeight: FontWeight.bold, fontSize: 12) | ||
// ), | ||
elevation: WidgetStateProperty.all(6), | ||
backgroundColor: | ||
WidgetStatePropertyAll(backgroundColor ?? Colors.transparent), | ||
), | ||
onPressed: onPressed, | ||
child: Text(buttonName)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import 'package:flutter/cupertino.dart'; | ||
import '../../config/routes/navigator.dart'; | ||
import '../../main.dart'; | ||
|
||
class LoadingDialog { | ||
static showLoading({BuildContext? context}) { | ||
showCupertinoDialog( | ||
context: globalAppContext ?? context!, | ||
builder: (context) { | ||
return const CupertinoAlertDialog( | ||
content: LoadingState(), | ||
); | ||
}); | ||
} | ||
|
||
static hideLoading() { | ||
pop(); | ||
} | ||
} | ||
|
||
class LoadingState extends StatelessWidget { | ||
const LoadingState({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return const Center(child: CupertinoActivityIndicator()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import 'package:flutter/cupertino.dart'; | ||
import 'package:flutter/material.dart'; | ||
import '../../config/routes/navigator.dart'; | ||
import '../../main.dart'; | ||
|
||
class MessageDialog { | ||
static void showMessageDialog({ | ||
Widget? contentWidget, | ||
String? contentText, | ||
String? closeText = 'Close', | ||
List<Widget>? actions, | ||
bool tapOutsideToClose = false, | ||
Color? color, | ||
Widget? titleWidget, | ||
String? titleText, | ||
Function()? onTapClose, | ||
bool showCloseButton = true, | ||
}) { | ||
showCupertinoModalPopup<void>( | ||
context: globalAppContext!, | ||
barrierDismissible: tapOutsideToClose, | ||
builder: (BuildContext context) { | ||
return CupertinoAlertDialog( | ||
title: titleWidget ?? | ||
Text( | ||
titleText ?? '', | ||
style: const TextStyle( | ||
color: Colors.blue, fontWeight: FontWeight.bold), | ||
), | ||
content: Material( | ||
color: Colors.transparent, | ||
child: contentWidget ?? | ||
Text(contentText ?? '', | ||
textAlign: TextAlign.start, | ||
style: const TextStyle(fontSize: 16)), | ||
), | ||
actions: showCloseButton | ||
? actions ?? | ||
[ | ||
TextButton( | ||
onPressed: onTapClose ?? | ||
() { | ||
pop(); | ||
}, | ||
child: Text(closeText ?? 'OK')) | ||
] | ||
: [], | ||
); | ||
}, | ||
); | ||
} | ||
|
||
static void showError( | ||
String err, { | ||
Widget? contentWidget, | ||
String? closeText = 'Close', | ||
List<Widget>? actions, | ||
bool tapOutsideToClose = false, | ||
String? titleText, | ||
}) { | ||
showMessageDialog( | ||
color: Colors.red, | ||
contentText: err, | ||
titleWidget: Text(titleText ?? 'Error', | ||
style: const TextStyle(color: Colors.red, fontSize: 20)), | ||
contentWidget: contentWidget, | ||
closeText: closeText, | ||
actions: actions, | ||
tapOutsideToClose: tapOutsideToClose); | ||
} | ||
} |
Oops, something went wrong.