letsar / flutter_slidable

A Flutter implementation of slidable list item with directional slide actions.
MIT License
2.72k stars 589 forks source link

Animate the slidable slightly to show the hidden feature #288

Open sarbogast opened 2 years ago

sarbogast commented 2 years ago

I love Slidable, but swipe buttons are hidden and I'm looking for ways to show the user those buttons in a showcase. I'm using showcaseview to show overlays for important buttons in the app, but in the case of swipe buttons, I can only show an overlay on the first ListTile in a ListView explaining actions that are available behind a swipe right. It would be much more powerful to be able to animate the Slidable to uncover the slidable actions slightly, to show that there is something hidden behind this ListTile. Is it possible to do that, maybe with a SlidableController? If so, could you please document how to do it?

luciano-cervantes commented 2 years ago

I would like this feature too 😁

ramvdixit commented 2 years ago

A very important and desired feature would be this!

austinn commented 2 years ago

This is what I'm doing

slidable?.openEndActionPane(
  duration: const Duration(milliseconds: 500),
  curve: Curves.decelerate,
);

Future.delayed(const Duration(seconds: 1), () {
  slidable?.close(
    duration: const Duration(milliseconds: 500),
    curve: Curves.bounceInOut,
  );
});
sarbogast commented 2 years ago

@austinn and how do you build the slidable reference? With a GlobalKey?

lucasfcardozo commented 2 years ago

@austinn and how do you build the slidable reference? With a GlobalKey?

Using his code, I made this:


import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: 'Slidable Example',
    home: Scaffold(
      body: SafeArea(
        child: Slidable(
          startActionPane: ActionPane(
            motion: const ScrollMotion(),
            dismissible: DismissiblePane(onDismissed: () {}),
            children: const [
              SlidableAction(
                onPressed: doNothing,
                backgroundColor: Color(0xFFFE4A49),
                foregroundColor: Colors.white,
                icon: Icons.delete,
                label: 'Delete',
              ),
              SlidableAction(
                onPressed: doNothing,
                backgroundColor: Color(0xFF21B7CA),
                foregroundColor: Colors.white,
                icon: Icons.share,
                label: 'Share',
              ),
            ],
          ),
          endActionPane: const ActionPane(
            motion: ScrollMotion(),
            children: [
              SlidableAction(
                flex: 2,
                onPressed: doNothing,
                backgroundColor: Color(0xFF7BC043),
                foregroundColor: Colors.white,
                icon: Icons.archive,
                label: 'Archive',
              ),
              SlidableAction(
                onPressed: doNothing,
                backgroundColor: Color(0xFF0392CF),
                foregroundColor: Colors.white,
                icon: Icons.save,
                label: 'Save',
              ),
            ],
          ),
          child: SlidableTile()
        ),
      ),
    ),
  );
}

void doNothing(BuildContext context) {}

class SlidableTile extends StatefulWidget {
  _SlidableTile createState() => _SlidableTile();
}

class _SlidableTile extends State<SlidableTile> {

  @override
  void initState() {
    super.initState();
    _start();
  }

  // the magic is here
  Future<void> _start() async {
    await Future<void>.delayed(const Duration(seconds: 1));
    var slidable = Slidable.of(context);

    slidable?.openEndActionPane(
      duration: const Duration(milliseconds: 500),
      curve: Curves.decelerate,
    );

    Future.delayed(const Duration(seconds: 1), () {
      slidable?.close(
        duration: const Duration(milliseconds: 500),
        curve: Curves.bounceInOut,
      );
    });
  }

  @override
  Widget build(_) => const ListTile(title: Text('Slide me'));
}
letsar commented 2 years ago

I would be a good feature indeed. We can do it by having a widget which launches an animation on initState and we would put this widget as the child of an ActionPane when needed. Someone want to try to make it and create a PR?

Kiruel commented 1 year ago

@sarbogast Have you find a solution for it ?

wildsurfer commented 1 year ago

+1 for this option