Files
intaleq/lib/views/widgets/elevated_btn.dart

183 lines
5.3 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:vibration/vibration.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import '../../main.dart';
class MyElevatedButton extends StatefulWidget {
final String title;
final VoidCallback onPressed;
final Color kolor;
final int vibrateDuration;
final IconData? icon;
final bool isLoading;
final double? height;
final double? fontSize;
const MyElevatedButton({
Key? key,
required this.title,
required this.onPressed,
this.kolor = AppColor.primaryColor,
this.vibrateDuration = 50, // Shorter = crisper feedback
this.icon,
this.isLoading = false,
this.height = 52,
this.fontSize,
}) : super(key: key);
@override
State<MyElevatedButton> createState() => _MyElevatedButtonState();
}
class _MyElevatedButtonState extends State<MyElevatedButton>
with SingleTickerProviderStateMixin {
late final AnimationController _pressController;
bool _isVibrateEnabled = true;
@override
void initState() {
super.initState();
_pressController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 120),
reverseDuration: const Duration(milliseconds: 180),
);
_loadVibratePreference();
}
Future<void> _loadVibratePreference() async {
// Reactive to preference changes if needed later
setState(() {
_isVibrateEnabled = box.read(BoxName.isvibrate) ?? true;
});
}
@override
void dispose() {
_pressController.dispose();
super.dispose();
}
void _triggerHaptic() {
if (!_isVibrateEnabled) return;
// Unified approach: HapticFeedback works well on both platforms
if (Platform.isIOS) {
HapticFeedback.lightImpact();
} else if (Platform.isAndroid) {
// Try native haptic first, fallback to Vibration package if needed
HapticFeedback.mediumImpact();
// Optional stronger feedback:
// Vibration.vibrate(duration: widget.vibrateDuration);
}
}
void _handlePress() {
if (widget.isLoading) return;
_triggerHaptic();
_pressController.forward().then((_) => _pressController.reverse());
// Small delay ensures animation starts before callback
Future.delayed(const Duration(milliseconds: 80), widget.onPressed);
}
@override
Widget build(BuildContext context) {
final isEnabled = !widget.isLoading && widget.onPressed != () {};
return AnimatedBuilder(
animation: _pressController,
builder: (context, child) {
final scale = 1.0 - (_pressController.value * 0.03);
return Transform.scale(
scale: scale,
child: Container(
height: widget.height,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
boxShadow: isEnabled
? [
BoxShadow(
color: widget.kolor.withOpacity(0.25),
blurRadius: 12,
offset: const Offset(0, 4),
),
]
: null,
),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.resolveWith<Color>(
(states) {
if (!isEnabled) return widget.kolor.withOpacity(0.5);
if (states.contains(WidgetState.pressed)) {
return widget.kolor.withOpacity(0.92);
}
return widget.kolor;
},
),
elevation: WidgetStateProperty.resolveWith<double>(
(states) => isEnabled
? (states.contains(WidgetState.pressed) ? 2 : 6)
: 0,
),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
),
),
onPressed: isEnabled ? _handlePress : null,
child: _buildContent(),
),
),
);
},
);
}
Widget _buildContent() {
if (widget.isLoading) {
return SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2.5,
valueColor: AlwaysStoppedAnimation<Color>(AppColor.secondaryColor),
),
);
}
final textStyle = AppStyle.title.copyWith(
color: AppColor.secondaryColor,
fontSize: widget.fontSize,
fontWeight: FontWeight.w600,
letterSpacing: 0.3,
);
if (widget.icon != null) {
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(widget.icon, size: 18, color: AppColor.secondaryColor),
const SizedBox(width: 8),
Text(widget.title, style: textStyle, textAlign: TextAlign.center),
],
);
}
return Text(widget.title, style: textStyle, textAlign: TextAlign.center);
}
}