Skip to content

Instantly share code, notes, and snippets.

@epatel
Created February 26, 2024 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save epatel/d9236484817e3995e933954387822d3a to your computer and use it in GitHub Desktop.
Save epatel/d9236484817e3995e933954387822d3a to your computer and use it in GitHub Desktop.
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(const AnimatedContainerExampleApp());
class AnimatedContainerExampleApp extends StatelessWidget {
const AnimatedContainerExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: OrderToolScrollTest(),
);
}
}
class OrderToolScrollTest extends StatefulWidget {
const OrderToolScrollTest({super.key});
@override
State<OrderToolScrollTest> createState() => _OrderToolScrollTestState();
}
class _OrderToolScrollTestState extends State<OrderToolScrollTest> {
int sections = 6;
ScrollController controller = ScrollController();
final double offsetTop = 134 /**ORDER_TOOL_TOP_PADDING */;
final double sectionSpacing = 24; //Insets.insets5;
final double buttonHeight = 56;
final double buttonWidth =
330 /**ORDER_TOOL_SIDE_MENU_WIDTH */ - (24 /**Insets.insets5 */ * 3);
int sectionsPassed = 0;
List<GlobalKey> keys = [];
List<Color> colors = [];
List<bool> completed = [];
double scrollIndicatorAlignment = -1;
double scrollViewHeight = 0;
@override
void initState() {
for (var i = 0; i < sections; i++) {
keys.add(GlobalKey());
colors.add(
Color((Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1),
);
completed.add(false);
}
controller.addListener(() {
setState(
() => scrollIndicatorAlignment =
((controller.offset / controller.position.maxScrollExtent) * 2) - 1,
);
// debugPrint(controller.offset.toString());
// debugPrint('max:${controller.position.maxScrollExtent}');
// debugPrint('alignment:${scrollIndicatorAlignment}');
sectionsPassed = 0;
for (int i = 0; i < keys.length; i++) {
var box = keys[i].currentContext!.findRenderObject()! as RenderBox;
var yPosition = box.localToGlobal(Offset.zero).dy;
// debugPrint('Height of key section $i: ${yPosition}');
if (yPosition < 100 && i != 0) {
sectionsPassed++;
}
}
// debugPrint('Sections passed ${sectionsPassed}');
});
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// debugPrint('$scrollViewHeight');
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
controller: controller,
child: Center(
child: SizedBox(
width: 1440 /**LARGE_SCREEN_MAX_WIDTH */,
child: Padding(
padding: EdgeInsets.only(
top: offsetTop - sectionSpacing,
left: 330 /**ORDER_TOOL_SIDE_MENU_WIDTH */ +
32 /**Insets.insets6 */ * 2,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (var i = 0; i < sections; i++) _section(index: i),
const SizedBox(height: 900),
],
),
),
),
),
),
),
Center(
child: Container(
width: 1440 /**LARGE_SCREEN_MAX_WIDTH */,
padding: EdgeInsets.only(
left: 32,
/**Insets.insets6 */
top: offsetTop,
),
child: Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: 330 /**ORDER_TOOL_SIDE_MENU_WIDTH */,
child: Container(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Rubrik'),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: Column(
children: [
for (var i = 0; i < sections; i++)
GestureDetector(
onTap: () {
Scrollable.ensureVisible(
keys[i].currentContext!,
duration: Durations.medium1,
);
},
child: _jumpButton(i, colors[i]),
),
],
),
),
AnimatedContainer(
margin: EdgeInsets.only(
left: 4,
top: sectionsPassed * buttonHeight,
),
duration: const Duration(
milliseconds: 150,
) /**SHORT_DURATION */,
curve: Curves.easeOut,
width: 12,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(3)),
height: buttonHeight,
),
],
)
],
),
),
),
),
),
),
],
),
);
}
Widget _jumpButton(int index, Color color) {
return Container(
height: buttonHeight,
width: buttonWidth,
decoration: BoxDecoration(
color: color,
border: Border.all(
color: completed[index] ? Colors.green : Colors.white,
width: completed[index] ? 8 : 1,
),
),
child: Center(child: Text('Go to section $index')),
);
}
Widget _section({required int index}) {
final hasBox = Random(colors[index].hashCode).nextDouble() > 0.7;
const boxHeight = 200.0;
var width = 684.0 /**WEB_LAYOUT_CONTENT_WIDTH*/;
if (hasBox) width += 330 /**ORDER_TOOL_SIDE_MENU_WIDTH */ + 24;
// Insets.insets5;
return Column(
children: [
// Necessary to ensure the alignment is always the same
SizedBox(
height: sectionSpacing,
key: keys[index],
),
SizedBox(
height: 700,
width: width,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 684 /**WEB_LAYOUT_CONTENT_WIDTH */,
child: Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: colors[index],
),
child: Column(
children: [
Text('Section $index'),
Text('Description of section $index'),
TextButton(
onPressed: () => setState(
() => completed[index] = !completed[index],
),
child: Text(
completed[index]
? 'The section is completed!'
: 'Complete section',
),
),
],
),
),
),
if (hasBox)
Padding(
padding: const EdgeInsets.only(left: 24 /**Insets.insets5 */),
child: SizedBox(
width: 330 /**ORDER_TOOL_SIDE_MENU_WIDTH */,
height: boxHeight,
child: Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: colors[index],
),
child: const Column(
children: [
Text('Im a box'),
Text('yay'),
],
),
),
),
),
],
),
),
],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment