0

My goal is to make the Floating Action Buttons (FABs) animate smoothly to fill the empty space when I pick one up using Draggable. However, I haven’t been able to achieve this.

I want to create an animation similar to iOS, where when you long-press and start dragging an app, the other apps smoothly slide into the empty space.

Likewise, when a FAB is dropped into the DragTarget area, instead of snapping into place instantly, I want it to animate smoothly into position.

You can watch a screen recording of my current progress at this link. However, I am unable to add animations. Right now, everything is rendered instantly in the widget tree without smooth transitions. Should I use a different widget for this

https://www.dosya.tc/server3/ss463k/Screen_Recording_2025-02-20_at_13.01.10.mov.html

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:rey_bank/UI/Widget/animated_fab.dart';
import 'package:rey_bank/UI/Widget/home_page_widget.dart';
import 'package:rey_bank/UI/Widget/no_animation_fab_widget.dart';
import 'package:rey_bank/core/cubits/setting_cubit.dart';

class ModifyQuickTransactionPage extends StatefulWidget {
  const ModifyQuickTransactionPage({super.key});

  @override
  State<ModifyQuickTransactionPage> createState() =>
      _ModifyQuickTransactionPageState();
}

class _ModifyQuickTransactionPageState
    extends State<ModifyQuickTransactionPage> {
  @override
  void initState() {
    super.initState();
    getLanguage();
  }

  getLanguage() {
    final state = context.read<SettingsCubit>().state;
    if (state.language == 'English') {
      setState(() {
        labelContent = ['Deposit', 'Withdraw', 'Transfer'];
      });
    } else if (state.language == 'Türkçe') {
      setState(() {
        labelContent = ['Para Yatır', 'Para Çek', 'Para gönder'];
      });
    }
  }

  Widget buildDraggableFab(String tag) {
    IconData icon;
    String label;
    switch (tag) {
      case 'Deposit':
        icon = Icons.arrow_upward;
        label = labelContent[0];
        break;
      case 'Withdraw':
        icon = Icons.arrow_downward;
        label = labelContent[1];
        break;
      case 'Transfer':
        icon = Icons.autorenew_outlined;
        label = labelContent[0];
        break;
      default:
        icon = Icons.abc;
        label = '';
    }

    return Draggable<String>(
      onDragStarted: () {
        sizedBoxFuction();
      },
      data: tag,
      feedback: Material(
        color: Colors.transparent,
        child: animatedFabWidget(() {}, icon, label),
      ),
      childWhenDragging: SizedBox(
        width: sizaedBox,
      ),
      child: animatedFabWidget(() {}, icon, label),
    );
  }

  Widget buildDroppedFab(String tag) {
    IconData icon;
    String label;
    switch (tag) {
      case 'Deposit':
        icon = Icons.arrow_upward;
        label = labelContent[0];
        break;
      case 'Withdraw':
        icon = Icons.arrow_forward;
        label = labelContent[1];
        break;
      case 'Transfer':
        icon = Icons.autorenew_outlined;
        label = labelContent[2];
        break;
      default:
        icon = Icons.abc;
        label = '';
    }

    return Draggable<String>(
      data: tag,
      feedback: Material(
        color: Colors.transparent,
        child: animatedFabWidget(() {}, icon, label),
      ),
      childWhenDragging: const SizedBox(),
      child: noAnimationFabWidget(() {}, icon, label),
    );
  }

  sizedBoxFuction() async {
    for (var i = 50; i > 0; i--) {
      await Future.delayed(const Duration(milliseconds: 10));
      setState(() {
        sizaedBox = i.toDouble();
      });
      print(i);
      print(sizaedBox);
    }
  }

  List<String> labelContent = [];

  List<String> draggableFabList = ['Deposit', 'Withdraw', 'Transfer'];

  List<String> droppedFabList = [];

  double sizaedBox = 50;

  @override
  Widget build(BuildContext context) {
    return ConstrainedBox(
        constraints: BoxConstraints(
          minWidth: MediaQuery.of(context).size.width,
          minHeight: MediaQuery.of(context).size.height -
              MediaQuery.of(context).padding.bottom -
              kBottomNavigationBarHeight -
              MediaQuery.of(context).padding.top,
        ),
        child: Center(
            child:
                Column(mainAxisAlignment: MainAxisAlignment.center, children: [
          DragTarget<String>(
            onAcceptWithDetails: (details) {
              setState(() {
                draggableFabList.remove(details.data);
                droppedFabList.add(details.data);
              });
            },
            builder: (context, candidateData, rejectedData) {
              return containerWidget(
                  context: context,
                  height: 150,
                  child: Row(
                    children: droppedFabList
                        .map((element) => buildDroppedFab(element))
                        .toList(),
                  ));
            },
          ),
          const SizedBox(
            height: 20,
          ),
          containerWidget(
              context: context,
              height: 150,
              child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: draggableFabList
                      .map((element) => buildDraggableFab(element))
                      .toList()))
        ])));
  }
}
1
  • Ali , the link you have shared is not working and the code you have posted cannot be run since its incomplete code. Upload the code which can executed on your device and post a video of it too. Commented Feb 21 at 4:57

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.