Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

dart - Circular progress button based on hold (flutter)

I'm trying to make a button where when user hold it, there will be a progress, but if the user unpress the button before it finish, the progress will decrease. somthing like the one on the pictureenter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As said by Arnold Parge, you can use the GestureDetector and listen to onTapDown and onTapUp. To create your desired LoadingButton, you can use the following Widget Structure:

- GetureDetector
  - Stack
    - CircularProgressIndicator // background circle
    - CircularProgressIndicator // foreground circle
    - Icon

To create the animation, you can add an AnimationController and bind the value of the foreground CircularProgressIndicator to AnimationController.value. Now you'll just have to the add the two listeners to to the GestureDetector:

  • onTapDown: When tapping on the button, the animation should start. Therefore we call AnimationController.forward()
  • onTapUp: When releasing the press, we want to check if the animation is already finished. We can use AnimationController.status to check the status. If it is AnimationStatus.forward it is still running. Hence we want to reverse the animation with calling AnimationController.reverse().

Here is the resulting button:

Button Animation

And the complete source code:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(),
      home: Scaffold(
        body: Center(child: LoadingButton()),
      ),
    );
  }
}

class LoadingButton extends StatefulWidget {
  @override
  LoadingButtonState createState() => LoadingButtonState();
}

class LoadingButtonState extends State<LoadingButton>
    with SingleTickerProviderStateMixin {
  AnimationController controller;

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

    controller =
        AnimationController(vsync: this, duration: Duration(seconds: 1));
    controller.addListener(() {
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (_) => controller.forward(),
      onTapUp: (_) {
        if (controller.status == AnimationStatus.forward) {
          controller.reverse();
        }
      },
      child: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          CircularProgressIndicator(
            value: 1.0,
            valueColor: AlwaysStoppedAnimation<Color>(Colors.grey),
          ),
          CircularProgressIndicator(
            value: controller.value,
            valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
          ),
          Icon(Icons.add)
        ],
      ),
    );
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...