Skip to content

Instantly share code, notes, and snippets.

@slightfoot
Forked from austinstoker/main.dart
Last active July 16, 2025 17:19
Show Gist options
  • Save slightfoot/cac192587f99e84be894e58788e4664f to your computer and use it in GitHub Desktop.
Save slightfoot/cac192587f99e84be894e58788e4664f to your computer and use it in GitHub Desktop.
Zooming and reorderable list :: https://www.youtube.com/watch?v=92TileEhN3g
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class AppState {
AppState();
final zoomScale = ValueNotifier(1.0); // Initial zoom level
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
static AppState appStateOf(BuildContext context) {
return context.findAncestorStateOfType<_MyAppState>()!.state;
}
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final state = AppState();
@override
Widget build(BuildContext context) {
return ZoomScaleChild(
child: MaterialApp(
home: const ZoomableReorderableList(),
),
);
}
}
class ZoomableReorderableList extends StatefulWidget {
const ZoomableReorderableList({super.key});
@override
State<ZoomableReorderableList> createState() => _ZoomableReorderableListState();
}
class _ZoomableReorderableListState extends State<ZoomableReorderableList> {
final List<String> _items = List.generate(10, (index) => 'Item $index');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Zoomable Reorderable List'),
actions: [
IconButton(
icon: const Icon(Icons.zoom_in),
onPressed: () {
final appState = MyApp.appStateOf(context);
appState.zoomScale.value = //
(appState.zoomScale.value + 0.2).clamp(
0.5,
2.0,
);
},
),
IconButton(
icon: const Icon(Icons.zoom_out),
onPressed: () {
final appState = MyApp.appStateOf(context);
appState.zoomScale.value = //
(appState.zoomScale.value - 0.2).clamp(
0.5,
2.0,
);
},
),
],
),
body: SingleChildScrollView(
child: Center(
child: ReorderableListView(
shrinkWrap: true,
// Ensure the list fits within the scaled container
physics: const NeverScrollableScrollPhysics(),
// Disable inner scroll
onReorder: (oldIndex, newIndex) {
setState(() {
if (newIndex > oldIndex) {
newIndex -= 1;
}
final item = _items.removeAt(oldIndex);
_items.insert(newIndex, item);
});
},
children: _items.map((item) {
return Card(
key: ValueKey(item), // Unique key for each item
margin: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 8,
),
child: InkWell(
onTap: () {
showDialog(
context: context,
builder: (_) => TestDialog(),
);
},
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 12.0,
),
child: Text(item),
),
),
);
}).toList(),
),
),
),
);
}
}
class ZoomScaleChild extends StatelessWidget {
const ZoomScaleChild({
super.key,
required this.child,
});
final Widget child;
@override
Widget build(BuildContext context) {
return ZoomScaleBuilder(
builder: (BuildContext context, double zoomScale, Widget? child) {
return MediaQuery(
data:
MediaQuery.of(context) //
.copyWith(textScaler: TextScaler.linear(zoomScale)),
child: child!,
);
// final size = MediaQuery.sizeOf(context);
// return Align(
// alignment: Alignment.topCenter,
// child: Container(
// constraints: BoxConstraints.tightFor(
// width: size.width / zoomScale,
// height: size.height / zoomScale,
// ),
// child: Transform.scale(
// scale: zoomScale,
// alignment: Alignment.topCenter,
// child: child,
// ),
// ),
// );
},
child: child,
);
}
}
class ZoomScaleBuilder extends StatelessWidget {
const ZoomScaleBuilder({
super.key,
required this.builder,
this.child,
});
final Widget Function(BuildContext context, double zoomScale, Widget? child) builder;
final Widget? child;
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: MyApp.appStateOf(context).zoomScale,
builder: builder,
child: child,
);
}
}
class TestDialog extends StatelessWidget {
const TestDialog({super.key});
@override
Widget build(BuildContext context) {
return AlertDialog(
content: Text('hello'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
),
],
);
}
}
@erbolamm
Copy link

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment