- Murattal: Spotify-style 5-button controls [Shuffle, Prev, Play, Next, Playlist] - Murattal: Animated 7-bar equalizer visualization in player circle - Murattal: Unsplash API background with frosted glass player overlay - Murattal: Transparent AppBar with backdrop blur - Murattal: Surah playlist bottom sheet with full 114 Surah list - Murattal: Auto-play disabled on screen open, enabled on navigation - Murattal: Shuffle mode for random Surah playback - Murattal: Photographer attribution per Unsplash guidelines - Dashboard: Auto-scroll prayer schedule to next active prayer - Fix: setState lifecycle errors on Reading & Murattal screens - Setup: flutter_dotenv, cached_network_image, url_launcher deps
59 lines
1.7 KiB
Dart
59 lines
1.7 KiB
Dart
import 'package:flutter/material.dart';
|
||
import '../../app/theme/app_colors.dart';
|
||
|
||
/// Custom iOS-style toggle switch (51×31dp) per PRD §6.9.
|
||
/// Uses AnimatedContainer + GestureDetector for smooth animation.
|
||
class IosToggle extends StatelessWidget {
|
||
const IosToggle({
|
||
super.key,
|
||
required this.value,
|
||
required this.onChanged,
|
||
});
|
||
|
||
final bool value;
|
||
final ValueChanged<bool> onChanged;
|
||
|
||
static const double _width = 51.0;
|
||
static const double _height = 31.0;
|
||
static const double _thumbSize = 27.0;
|
||
static const double _thumbPadding = 2.0;
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return GestureDetector(
|
||
onTap: () => onChanged(!value),
|
||
child: AnimatedContainer(
|
||
duration: const Duration(milliseconds: 200),
|
||
curve: Curves.easeInOut,
|
||
width: _width,
|
||
height: _height,
|
||
decoration: BoxDecoration(
|
||
borderRadius: BorderRadius.circular(_height / 2),
|
||
color: value ? AppColors.primary : AppColors.cream,
|
||
),
|
||
child: AnimatedAlign(
|
||
duration: const Duration(milliseconds: 200),
|
||
curve: Curves.easeInOut,
|
||
alignment: value ? Alignment.centerRight : Alignment.centerLeft,
|
||
child: Container(
|
||
width: _thumbSize,
|
||
height: _thumbSize,
|
||
margin: const EdgeInsets.all(_thumbPadding),
|
||
decoration: BoxDecoration(
|
||
shape: BoxShape.circle,
|
||
color: Colors.white,
|
||
boxShadow: [
|
||
BoxShadow(
|
||
color: Colors.black.withValues(alpha: 0.15),
|
||
blurRadius: 4,
|
||
offset: const Offset(0, 2),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|