chaoperty_floating_loader 0.1.9
chaoperty_floating_loader: ^0.1.9 copied to clipboard
Global overlay loader with transparent overlay and GIF. Motions: once, ping-pong, loop-wrap. Optional dim background/card. Callable from anywhere via navigatorKey.
example/lib/main.dart
import 'dart:math';
import 'package:chaoperty_floating_loader/src/app_loader.dart';
import 'package:flutter/material.dart';
import 'package:chaoperty_floating_loader/chaoperty_floating_loader.dart';
class DemoPage extends StatefulWidget {
const DemoPage({super.key});
@override
State<DemoPage> createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
bool _busy = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Global Floating Loader Demo')),
body: LoadingOverlay(
loading: _busy,
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 520),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 1) Once motion (custom from → to) + bounce at end
// วิ่งครั้งเดียวจากจุดเริ่ม → จุดสิ้นสุด + เด้งเล็กน้อยตอนชนขอบ
FilledButton(
onPressed: () {
ChaoAppLoader.show(
packAsset: ChaoPackAsset.duckFrontWalkGif,
message: 'Once: 0.20 → 0.85 (bounce)',
slideAcross: true,
motion: Motion.once,
fromAt: 0.20,
toAt: 0.85,
bounceAtEdges: true,
slideMs: 4200,
verticalFactor: 0.70,
gifWidth: 120,
gifHeight: 110,
);
Future.delayed(
const Duration(milliseconds: 4300),
ChaoAppLoader.hide,
);
},
child: const Text('Once (fromAt → toAt)'),
),
const SizedBox(height: 10),
// 2) Once motion (toAt only)
// ระบุแค่จุดสิ้นสุด ระบบเลือกจุดเริ่มให้อัตโนมัติ
FilledButton.tonal(
onPressed: () {
ChaoAppLoader.show(
message: 'Once: → 0.05 (auto from right)',
slideAcross: true,
motion: Motion.once,
toAt: 0.05,
slideMs: 1800,
verticalFactor: 0.62,
);
Future.delayed(
const Duration(milliseconds: 1800),
ChaoAppLoader.hide,
);
},
child: const Text('Once (toAt only)'),
),
const SizedBox(height: 10),
// 3) Ping-pong motion (range)
// วิ่งไป-กลับระหว่างช่วงที่กำหนด
OutlinedButton(
onPressed: () {
ChaoAppLoader.show(
message: 'Ping-Pong: 0.30 ↔ 0.80 + bounce',
slideAcross: true,
motion: Motion.pingPong,
rangeMinAt: 0.30,
rangeMaxAt: 0.80,
bounceAtEdges: true,
slideMs: 1400,
verticalFactor: 0.66,
);
Future.delayed(
const Duration(seconds: 5), ChaoAppLoader.hide);
},
child: const Text('Ping-Pong (rangeMin/Max)'),
),
const SizedBox(height: 10),
// 4) Loop wrap (Left → Right)
// วิ่งวนรอบจากซ้ายไปขวา
OutlinedButton(
onPressed: () {
ChaoAppLoader.show(
message: 'Loop wrap (L → R)',
slideAcross: true,
motion: Motion.loopWrap,
slideToRight: true,
startAt: Random().nextDouble(),
slideMs: 2400,
verticalFactor: 0.72,
size: 90,
);
Future.delayed(
const Duration(seconds: 5), ChaoAppLoader.hide);
},
child: const Text('Loop Wrap (Left → Right)'),
),
const SizedBox(height: 16),
const Divider(),
const SizedBox(height: 16),
// 5) Vertical only (Top → Bottom)
// วิ่งแนวตั้งจากบนลงล่าง
FilledButton(
onPressed: () {
ChaoAppLoader.show(
message: 'Vertical once: 0.10 → 0.85',
vSlideAcross: true,
vMotion: Motion.once,
vFromAt: 0.10,
vToAt: 0.85,
slideMs: 2600,
);
Future.delayed(
const Duration(milliseconds: 2600),
ChaoAppLoader.hide,
);
},
child: const Text('Vertical Once'),
),
const SizedBox(height: 10),
// 6) Diagonal (loop X + ping-pong Y)
// ทแยง: แนวนอนวิ่งวน, แนวตั้งเด้งไป-กลับ
FilledButton.tonal(
onPressed: () {
ChaoAppLoader.show(
message: 'Diagonal: loop X + ping-pong Y',
slideAcross: true,
motion: Motion.loopWrap,
slideToRight: true,
startAt: 0.2,
vSlideAcross: true,
vMotion: Motion.pingPong,
vRangeMinAt: 0.65,
vRangeMaxAt: 0.80,
slideMs: 2400,
);
Future.delayed(
const Duration(seconds: 5), ChaoAppLoader.hide);
},
child: const Text('Diagonal (X loop + Y ping-pong)'),
),
const SizedBox(height: 16),
// 7) Center idle with tiny ping-pong
// อยู่นิ่งกลางจอ แต่ขยับเล็กน้อย (range 0.48 ↔ 0.52)
FilledButton(
onPressed: () {
ChaoAppLoader.show(
useCard: false,
dimBackground: true,
message: '',
slideAcross: true,
motion: Motion.pingPong,
rangeMinAt: 0.48,
rangeMaxAt: 0.52,
slideMs: 1800,
verticalFactor: 0.5,
size: 150,
);
Future.delayed(
const Duration(seconds: 3), ChaoAppLoader.hide);
},
child: const Text('Center idle (tiny ping-pong)'),
),
const SizedBox(height: 24),
const Divider(),
const SizedBox(height: 12),
// Local overlay example
// การใช้ Overlay เฉพาะหน้านี้
Text('LoadingOverlay (local page-only)',
style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Busy overlay: '),
Switch(
value: _busy,
onChanged: (v) => setState(() => _busy = v),
),
],
),
const SizedBox(height: 8),
ElevatedButton(
onPressed: () async {
setState(() => _busy = true);
await Future.delayed(const Duration(seconds: 2));
if (mounted) setState(() => _busy = false);
},
child: const Text('Run busy task (2s)'),
),
],
),
),
),
),
);
}
}