Skip to content

Commit

Permalink
Merge pull request #20 from splashbyte/18-declarative-slidermode
Browse files Browse the repository at this point in the history
18 declarative slidermode
  • Loading branch information
maeddin authored Sep 21, 2024
2 parents c69dc97 + 85f49b0 commit 55b4ffb
Show file tree
Hide file tree
Showing 18 changed files with 1,542 additions and 848 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
## 0.8.0-beta.3

- adds `childPosition` to `ActionSlider.standard`
- adds `childClip` parameter to `ActionSlider.standard` and `ActionSlider.dual`
- adds `childAnimation` parameter to `ActionSlider.standard` and `ActionSlider.dual`
- migrates from `SliderMode` to `SliderStatus`
- adds `status` to all constructors
- adds `expanded`, `highlighted` and `side` parameters to `SliderMode.loading`, `SliderMode.success`
and `SliderMode.failure`
- BREAKING: renames `customForegroundBuilder` to `customIconBuilder`
- BREAKING: changes default background color from `ThemeData.cardColor` to `ThemeData.colorScheme.surface`
- BREAKING: removes `rolling` in favor of the new `iconAnimation` parameter
- BREAKING: renames `SlidingState` to `SlidingStatus`
- BREAKING: moves parameters in `ActionSlider.standard` and `ActionSlider.dual` to `style`:
- `backgroundColor`
- `backgroundBorderRadius` (renamed to `borderRadius`)
- `toggleColor`
- `boxShadow`
- adds option to add `SliderStyle` to `extensions` of `ThemeData`

## 0.8.0-beta.2 [2024-07-31]

Expand All @@ -16,6 +30,7 @@

## 0.8.0-beta.0 [2024-07-30]

- BREAKING: increases minimum SDK to 3.0.0
- BREAKING: renames `movementCurve` to `anchorPositionCurve`
- BREAKING: renames `movementDuration` to `anchorPositionDuration`
- BREAKING: renames `SliderDirection.begin` to `SliderDirection.start`
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 3-Clause License

Copyright (c) 2022, SplashByte GbR
Copyright (c) 2024, Martin Klüpfel
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

### If you like this package, please leave a like there on [pub.dev](https://pub.dev/packages/action_slider) and star on [GitHub](https://github.com/SplashByte/action_slider).

A slider to confirm actions and provide feedback on the success of these after subsequent loading.
A fully customizable slider to confirm actions and provide feedback on the success. It supports different states like loading, success and failure.

`LTR` and `RTL` are both supported.
For a switch with a similar look, you can check out [animated_toggle_switch](https://pub.dev/packages/animated_toggle_switch).

Expand All @@ -25,10 +26,10 @@ For a switch with a similar look, you can check out [animated_toggle_switch](htt
`ActionSlider.standard()` with `TextDirection.rtl`
![action_slider_example_rtl](https://github.com/splashbyte/action_slider/assets/43761463/5d81d3d2-ca52-4eb5-93b3-fada883a6a4f)

`ActionSlider.standard()` with `rolling = true`
`ActionSlider.standard()` with `SliderIconAnimation.roll`
![action_slider_example_rolling](https://github.com/splashbyte/action_slider/assets/43761463/0a5010e2-d369-46d3-bdfb-0df5832125ed)

`ActionSlider.standard()` with `SliderBehavior.stretch` and `rolling = true`
`ActionSlider.standard()` with `SliderBehavior.stretch` and `SliderIconAnimation.roll`
![action_slider_example_rolling_snake](https://github.com/splashbyte/action_slider/assets/43761463/e4f27603-83db-412a-8777-c737a9c55b14)

You can build your own sliders with `ActionSlider.custom()`
Expand Down Expand Up @@ -56,7 +57,7 @@ Two directions with `ActionSlider.dual`
ActionSlider.dual(
child: const Text('Slide to confirm'),
startAction: (controller) async {
controller.successExpanded(side: SliderSide.start); //starts success animation with an expanded slider
controller.success(expanded: true, side: SliderSide.start); //starts success animation with an expanded slider
},
endAction: (controller) async {
controller.success(); //starts success animation
Expand Down
2 changes: 1 addition & 1 deletion example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
Expand Down
144 changes: 111 additions & 33 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import 'dart:math';

import 'package:action_slider/action_slider.dart';
import 'package:cross_fade/cross_fade.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
runApp(const MyApp());
runApp(const ExampleApp());
}

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});

@override
Widget build(BuildContext context) {
Expand All @@ -18,21 +20,21 @@ class MyApp extends StatelessWidget {
primarySwatch: Colors.blue,
scaffoldBackgroundColor: Colors.white,
),
home: const MyHomePage(title: 'Action Slider Example'),
home: const ExamplePage(title: 'Action Slider Example'),
);
}
}

class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
class ExamplePage extends StatefulWidget {
const ExamplePage({super.key, required this.title});

final String title;

@override
State<MyHomePage> createState() => _MyHomePageState();
State<ExamplePage> createState() => _ExamplePageState();
}

class _MyHomePageState extends State<MyHomePage> {
class _ExamplePageState extends State<ExamplePage> {
final _controller = ActionSliderController();

@override
Expand All @@ -51,17 +53,16 @@ class _MyHomePageState extends State<MyHomePage> {
style: const TextStyle(color: Colors.white),
child: ActionSlider.dual(
anchorPosition: 0.7,
backgroundBorderRadius: BorderRadius.circular(10.0),
style: SliderStyle(
borderRadius: BorderRadius.circular(10.0),
backgroundColor: Colors.black,
),
width: 300.0,
backgroundColor: Colors.black,
startChild: const Text('Start'),
endChild: const Text('End'),
icon: Padding(
padding: const EdgeInsets.only(right: 2.0),
child: Transform.rotate(
angle: 0.5 * pi,
child: const Icon(Icons.unfold_more_rounded, size: 28.0)),
),
icon: const RotatedBox(
quarterTurns: 1,
child: Icon(Icons.unfold_more_rounded, size: 28.0)),
startAction: (controller) async {
controller.loading(); //starts loading animation
await Future.delayed(const Duration(seconds: 3));
Expand All @@ -70,25 +71,27 @@ class _MyHomePageState extends State<MyHomePage> {
controller.reset(); //resets the slider
},
endAction: (controller) async {
controller.loadingExpanded(); //starts loading animation
controller.loading(expanded: true); //starts loading animation
await Future.delayed(const Duration(seconds: 3));
controller.successExpanded(); //starts success animation
controller.success(expanded: true); //starts success animation
await Future.delayed(const Duration(seconds: 1));
controller.reset(); //resets the slider
},
),
),
const SizedBox(height: 24.0),
ActionSlider.standard(
resultToggleMargin: EdgeInsets.zero,
resultBorderWidth: 0.0,
sliderBehavior: SliderBehavior.stretch,
width: 300.0,
backgroundColor: Colors.white,
toggleColor: Colors.lightGreenAccent,
style: const SliderStyle(
backgroundColor: Colors.white,
toggleColor: Colors.lightGreenAccent,
),
action: (controller) async {
controller.loadingExpanded(); //starts loading animation
controller.loading(expanded: true); //starts loading animation
await Future.delayed(const Duration(seconds: 3));
controller.successExpanded(); //starts success animation
controller.success(expanded: true); //starts success animation
await Future.delayed(const Duration(seconds: 1));
controller.reset();
},
Expand All @@ -109,12 +112,14 @@ class _MyHomePageState extends State<MyHomePage> {
),
const SizedBox(height: 24.0),
ActionSlider.standard(
rolling: true,
iconAnimation: SliderIconAnimation.roll,
width: 300.0,
backgroundColor: Colors.black,
style: const SliderStyle(
backgroundColor: Colors.black,
toggleColor: Colors.purpleAccent,
),
reverseSlideAnimationCurve: Curves.easeInOut,
reverseSlideAnimationDuration: const Duration(milliseconds: 500),
toggleColor: Colors.purpleAccent,
icon: const Icon(Icons.add),
action: (controller) async {
controller.loading(); //starts loading animation
Expand All @@ -129,10 +134,12 @@ class _MyHomePageState extends State<MyHomePage> {
const SizedBox(height: 24.0),
ActionSlider.standard(
sliderBehavior: SliderBehavior.stretch,
rolling: true,
iconAnimation: SliderIconAnimation.roll,
width: 300.0,
backgroundColor: Colors.white,
toggleColor: Colors.amber,
style: const SliderStyle(
backgroundColor: Colors.white,
toggleColor: Colors.amber,
),
iconAlignment: Alignment.centerRight,
loadingIcon: SizedBox(
width: 55,
Expand Down Expand Up @@ -163,7 +170,6 @@ class _MyHomePageState extends State<MyHomePage> {
height: 60.0,
toggleWidth: 60.0,
toggleMargin: EdgeInsets.zero,
backgroundColor: Colors.green,
foregroundChild: DecoratedBox(
decoration: BoxDecoration(
color: Colors.black,
Expand All @@ -177,7 +183,6 @@ class _MyHomePageState extends State<MyHomePage> {
child: Text(state.position.toStringAsFixed(2),
style: theme.textTheme.titleMedium)),
),
backgroundBorderRadius: BorderRadius.circular(5.0),
action: (controller) async {
controller.loading(); //starts loading animation
await Future.delayed(const Duration(seconds: 3));
Expand All @@ -193,7 +198,6 @@ class _MyHomePageState extends State<MyHomePage> {
controller: _controller,
toggleWidth: 60.0,
height: 60.0,
backgroundColor: Colors.green,
foregroundChild: Container(
decoration: const BoxDecoration(
color: Colors.black,
Expand All @@ -212,14 +216,88 @@ class _MyHomePageState extends State<MyHomePage> {
minWidth: state.standardSize.width,
minHeight: state.toggleSize.height,
child: child!)),
backgroundBorderRadius: BorderRadius.circular(5.0),
action: (controller) async {
controller.loading(); //starts loading animation
await Future.delayed(const Duration(seconds: 3));
controller.success(); //starts success animation
await Future.delayed(const Duration(seconds: 1));
controller.reset(); //resets the slider
},
outerBackgroundBuilder: (context, state, _) => DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.green)),
),
const SizedBox(height: 24.0),
ActionSlider.custom(
width: 300.0,
controller: _controller,
sizeAnimationDuration: const Duration(milliseconds: 700),
sizeAnimationCurve:
const Interval(0.6, 1.0, curve: Curves.easeInOut),
foregroundBuilder: (context, state, _) {
final status = state.status;
return Stack(
fit: StackFit.passthrough,
children: [
Opacity(
opacity: 1.0 - state.relativeSize,
child: AnimatedCheckIcon(
icon: const Icon(Icons.check_rounded,
color: Colors.white, size: 32.0),
visible: status is SliderStatusSuccess,
animationCurve: const Interval(0.8, 1.0),
animationDuration: const Duration(milliseconds: 1000),
),
),
Opacity(
opacity: 1.0 - state.relativeSize,
child: CrossFade(
value: status,
builder: (context, status) =>
status is SliderStatusLoading
? const Center(
child: CupertinoActivityIndicator(
color: Colors.white))
: const SizedBox()),
),
Opacity(
opacity: state.relativeSize,
child: ScaleAppearingWidget(
animationDuration: const Duration(milliseconds: 1000),
animationCurve:
const Interval(0.7, 1.0, curve: Curves.easeOutBack),
visible: status.expanded,
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.all(Radius.circular(30.0)),
),
child: Transform.rotate(
angle: -state.position * pi,
child: const Icon(Icons.arrow_forward,
color: Colors.pinkAccent))),
),
),
],
);
},
backgroundBuilder: (context, state, _) => Center(
child: Text('Highly Customizable :)',
style: theme.textTheme.titleSmall?.copyWith(
color: Colors.white.withOpacity(1.0 - state.position))),
),
action: (controller) async {
controller.success(); //starts success animation
await Future.delayed(const Duration(seconds: 3));
controller.reset(); //resets the slider
},
outerBackgroundBuilder: (context, state, _) => DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40.0),
color: Colors.pinkAccent,
)),
),
],
),
Expand Down
Loading

0 comments on commit 55b4ffb

Please sign in to comment.