admin管理员组

文章数量:1124388

I need this result (The app is just for example)

I tried to use BottomSheet, modal_bottom_sheet and various similar libraries, but they hide the widget completely. I want it to stay above the navigation bar as a small strip and be able to be pulled out with a swipe or tap.

I need this result (The app is just for example)

I tried to use BottomSheet, modal_bottom_sheet and various similar libraries, but they hide the widget completely. I want it to stay above the navigation bar as a small strip and be able to be pulled out with a swipe or tap.

Share Improve this question edited 2 days ago jonrsharpe 122k30 gold badges264 silver badges472 bronze badges asked 2 days ago DimaDima 1,2491 gold badge10 silver badges14 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

This is just an idea to achieve your design and I will made it with GetX if you want to pull out i think you should try GestureDetector to know drag offset

ps.Maybe this is not best practices that why Im just said just an idea hope this will help

result

page widget

class PlaygroundPage extends StatelessWidget {
  const PlaygroundPage({super.key});

  @override
  Widget build(BuildContext context) {
    return GetBuilder<PlaygroundPageController>(
      global: false,
      init: PlaygroundPageController(),
      builder: (controller) => Scaffold(
        backgroundColor: AppColors.white,
        bottomNavigationBar: _Bottombar(
          controller: controller,
        ),
        body: Padding(
          padding: EdgeInsets.fromLTRB(0, Get.mediaQuery.padding.top, 0, 0),
          child: Column(
            children: [
              ToButton(
                onPressed: () {
                  Get.back();
                },
                child: Container(
                  width: 200,
                  height: 50,
                  color: AppColors.green1,
                  child: const Text('back'),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

class _Bottombar extends StatelessWidget {
  final PlaygroundPageController controller;
  const _Bottombar({
    required this.controller,
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      child: Container(
        clipBehavior: Clip.antiAlias,
        decoration: const BoxDecoration(
          boxShadow: [AppShadow.shadowTop],
        ),
        height: (72 + Get.mediaQuery.padding.bottom + 70) + (controller.animation.value * 500),
        child: Stack(
          children: [
            Positioned(
              bottom: 0,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  ToButton(
                    onPressed: () {
                      controller.isCollapsed.toggle();
                      controller.handleToggleExpanded();
                    },
                    child: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.only(
                          topLeft: Radius.circular(0 + (24 * controller.animation.value)),
                          topRight: Radius.circular(0 + (24 * controller.animation.value)),
                        ),
                        color: AppColors.red,
                      ),
                      width: Get.width,
                      height: (72 + Get.mediaQuery.padding.bottom + 70),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.start,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          Container(
                            margin: const EdgeInsets.fromLTRB(0, 8, 0, 0),
                            width: 100,
                            height: 10,
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(24),
                              color: AppColors.grey2,
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                  SizeTransition(
                    axisAlignment: 1.0,
                    sizeFactor: controller.animation,
                    child: Container(
                      width: Get.width,
                      height: 500,
                      color: AppColors.green1,
                    ),
                  ),
                ],
              ),
            ),
            Positioned(
              bottom: ((72 + Get.mediaQuery.padding.bottom) * controller.reverseAnimation.value) - (72 + Get.mediaQuery.padding.bottom),
              child: Container(
                padding: const EdgeInsets.fromLTRB(0, 16, 0, 0),
                width: Get.width,
                height: (72 + Get.mediaQuery.padding.bottom),
                decoration: const BoxDecoration(
                  color: AppColors.grey,
                  boxShadow: [AppShadow.shadowTop],
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      color: Colors.red,
                      width: sizing(20),
                      height: sizing(20),
                      padding: const EdgeInsets.fromLTRB(4, 8, 4, 0).toResponsive(),
                    ),
                    SizedBox(width: sizing(20)),
                    Container(
                      color: Colors.red,
                      width: sizing(20),
                      height: sizing(20),
                      padding: const EdgeInsets.fromLTRB(4, 8, 4, 0).toResponsive(),
                    ),
                    SizedBox(width: sizing(20)),
                    Container(
                      color: Colors.red,
                      width: sizing(20),
                      height: sizing(20),
                      padding: const EdgeInsets.fromLTRB(4, 8, 4, 0).toResponsive(),
                    ),
                    SizedBox(width: sizing(20)),
                    Container(
                      color: Colors.red,
                      width: sizing(20),
                      height: sizing(20),
                      padding: const EdgeInsets.fromLTRB(4, 8, 4, 0).toResponsive(),
                    ),
                    SizedBox(width: sizing(20)),
                    Container(
                      color: Colors.red,
                      width: sizing(20),
                      height: sizing(20),
                      padding: const EdgeInsets.fromLTRB(4, 8, 4, 0).toResponsive(),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

controller

class PlaygroundPageController extends GetxController with GetTickerProviderStateMixin {
  late AnimationController expandController;
  late AnimationController collapseController;

  late Animation<double> animation;
  late Animation<double> reverseAnimation;

  final isCollapsed = true.obs;

  @override
  void onInit() {
    super.onInit();
    prepareAnimations();
    prepareReverseAnimations();
  }

  void handleToggleExpanded() {
    if (!isCollapsed.value) {
      expandController.forward();
      collapseController.forward();
    } else {
      expandController.reverse();
      collapseController.reverse();
    }
  }

  void prepareAnimations() {
    expandController = AnimationController(
      vsync: this,
      duration: const Duration(
        milliseconds: 1500,
      ),
    );
    Animation<double> curve = CurvedAnimation(
      parent: expandController,
      curve: Curves.fastOutSlowIn,
    );
    animation = Tween(begin: 0.0, end: 1.0).animate(curve)..addListener(() => refresh());
  }

  void prepareReverseAnimations() {
    collapseController = AnimationController(
      vsync: this,
      duration: const Duration(
        milliseconds: 1500,
      ),
    );
    Animation<double> curve = CurvedAnimation(
      parent: collapseController,
      curve: Curves.fastOutSlowIn,
    );
    reverseAnimation = Tween(begin: 1.0, end: 0.0).animate(curve)..addListener(() => refresh());
  }
}

本文标签: flutterHow to expand a widget from a small strip to full screen and collapse it backStack Overflow