Skip to content

Commit

Permalink
feat: Progress Bar (#29)
Browse files Browse the repository at this point in the history
* Add Progress bar

* Remove fixed with for progress bar

* Respond to comments

---------

Co-authored-by: Osman <AO3856@zebra.com>
  • Loading branch information
ahmed-osman3 and Osman authored Feb 29, 2024
1 parent e017809 commit d18dbd2
Show file tree
Hide file tree
Showing 5 changed files with 379 additions and 4 deletions.
18 changes: 14 additions & 4 deletions example/lib/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import 'package:zeta_example/pages/components/checkbox_example.dart';
import 'package:zeta_example/pages/components/chip_example.dart';
import 'package:zeta_example/pages/theme/color_example.dart';
import 'package:zeta_example/pages/components/password_input_example.dart';
import 'package:zeta_example/pages/components/progress_example.dart';

import 'package:zeta_example/pages/assets/icons_example.dart';
import 'package:zeta_example/widgets.dart';
import 'package:zeta_flutter/zeta_flutter.dart';
Expand All @@ -30,7 +32,9 @@ final List<Component> components = [
Component(ButtonExample.name, (context) => const ButtonExample()),
Component(CheckBoxExample.name, (context) => const CheckBoxExample()),
Component(ChipExample.name, (context) => const ChipExample()),
Component(PasswordInputExample.name, (context) => const PasswordInputExample()),
Component(
PasswordInputExample.name, (context) => const PasswordInputExample()),
Component(ProgressExample.name, (context) => const ProgressExample())
];

final List<Component> theme = [
Expand Down Expand Up @@ -92,21 +96,27 @@ class _HomeState extends State<Home> {
title: Text('Widgets'),
backgroundColor: Zeta.of(context).colors.warm.shade30,
children: _components
.map((item) => ListTile(title: Text(item.name), onTap: () => context.go('/${item.name}')))
.map((item) => ListTile(
title: Text(item.name),
onTap: () => context.go('/${item.name}')))
.toList(),
),
ExpansionTile(
title: Text('Theme'),
backgroundColor: Zeta.of(context).colors.warm.shade30,
children: _theme
.map((item) => ListTile(title: Text(item.name), onTap: () => context.go('/${item.name}')))
.map((item) => ListTile(
title: Text(item.name),
onTap: () => context.go('/${item.name}')))
.toList(),
),
ExpansionTile(
title: Text('Assets'),
backgroundColor: Zeta.of(context).colors.warm.shade30,
children: _assets
.map((item) => ListTile(title: Text(item.name), onTap: () => context.go('/${item.name}')))
.map((item) => ListTile(
title: Text(item.name),
onTap: () => context.go('/${item.name}')))
.toList(),
),
],
Expand Down
135 changes: 135 additions & 0 deletions example/lib/pages/components/progress_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import 'package:flutter/material.dart';
import 'package:zeta_example/widgets.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

class ProgressExample extends StatefulWidget {
static const String name = 'Progress';

const ProgressExample({super.key});

@override
State<ProgressExample> createState() => ProgressExampleState();
}

class ProgressExampleState extends State<ProgressExample> {
@override
Widget build(BuildContext context) {
return ExampleScaffold(
name: 'Progress',
child: Center(
child: SingleChildScrollView(
child: SizedBox(
width: double.infinity,
child: Column(children: [
Wrapper(
stepsCompleted: 10,
isThin: true,
),
SizedBox(
height: 20,
),
Wrapper(
stepsCompleted: 0,
type: ZetaBarType.standard,
isThin: false,
stateChangeable: true),
SizedBox(
height: 20,
),
Wrapper(
stepsCompleted: 0,
type: ZetaBarType.indeterminate,
isThin: false,
label: "UPLOADING ...",
),
]),
),
),
),
);
}
}

class Wrapper extends StatefulWidget {
const Wrapper(
{super.key,
required this.stepsCompleted,
this.type = ZetaBarType.standard,
this.isThin = false,
this.rounded = true,
this.stateChangeable = false,
this.label});

final int stepsCompleted;
final bool rounded;
final ZetaBarType type;
final bool isThin;
final String? label;
final bool stateChangeable;

@override
State<Wrapper> createState() => _WrapperState();
}

class _WrapperState extends State<Wrapper> {
late int stepsCompleted;
late double progress;
late ZetaBarType type;

@override
void initState() {
super.initState();
type = widget.type;
stepsCompleted = widget.stepsCompleted;
progress = stepsCompleted / 10;
}

///Function to increase percentage of progress.
void increasePercentage() {
setState(() {
stepsCompleted++;
progress = stepsCompleted / 10;
});
}

void setLoading() {
setState(() {
type = type == ZetaBarType.buffering
? ZetaBarType.standard
: ZetaBarType.buffering;
});
}

@override
Widget build(BuildContext context) {
return Column(
// Replace with a Column for vertical
children: [
SizedBox(
width: 400,
child: ZetaProgressBar(
progress: progress,
rounded: widget.rounded,
type: type,
isThin: widget.isThin,
label: widget.label),
),
const SizedBox(width: 40),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
widget.type != ZetaBarType.indeterminate
? FilledButton(
onPressed: increasePercentage, child: Text("Increase"))
: Container(),
const SizedBox(width: 40),
widget.stateChangeable
? FilledButton(
onPressed: setLoading, child: Text("Start Buffering"))
: Container()
],
)
],
);
}
}
85 changes: 85 additions & 0 deletions lib/src/components/progress/progress.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

/// Super class for [ZetaProgress] widgets.
/// Handles state for progress of [ZetaProgress] widgets.
abstract class ZetaProgress extends StatefulWidget {
/// Constructor for abstract [ZetaProgress] class.
const ZetaProgress({super.key, this.progress = 0});

/// ZetaProgress value, decimal value ranging from 0.0 - 1.0, 0.5 = 50%
final double progress;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DoubleProperty('progress', progress));
}
}

/// Super class for [ZetaProgressState]
/// Defines functions that deal with state change of progress value and
/// animation changing.
abstract class ZetaProgressState<T extends ZetaProgress> extends State<T>
with TickerProviderStateMixin {
/// Decimal progress value
late double progress;

///Animation controller for [ZetaProgressState]
late AnimationController controller;

///Animation for [ZetaProgressState]
late Animation<double> animation;

@override
void initState() {
super.initState();
progress = widget.progress;
controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 200));
animation = Tween<double>(
begin: widget.progress, // Start value
end: widget.progress, // End value (initially same as start value)
).animate(controller)
..addListener(() {
setState(() {
progress = animation.value;
});
});
}

@override
void dispose() {
controller.dispose();
super.dispose();
}

///Update animation with new progress value to give animation effect for progress changing.
void updateProgress(double newProgress) {
// Update the Tween with new start and end value

setState(() {
animation = Tween<double>(
begin: progress,
end: newProgress,
).animate(controller);
controller.forward(from: progress);
});
}

@override
void didUpdateWidget(T oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.progress != widget.progress) {
updateProgress(widget.progress);
}
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DoubleProperty('progress', progress))
..add(DiagnosticsProperty<AnimationController>('controller', controller))
..add(DiagnosticsProperty<Animation<double>>('animation', animation));
}
}
Loading

0 comments on commit d18dbd2

Please sign in to comment.