Shuttle global levitation button

Time:2022-1-7

Method 1

Shuttle global levitation button

image-20210822124957439
  Offset _offset = Offset.zero;
  Scaffold(
        body: Stack(
          children: [
            _pageList[_currentIndex],
            Positioned(
              left: _offset.dx,
              top: _offset.dy,
              child: GestureDetector(
                onPanUpdate: (d) =>
                    setState(() => _offset += Offset(d.delta.dx, d.delta.dy)),
                child: FloatingActionButton(
                  onPressed: () {},
                  backgroundColor: Colors.orange,
                  child: Icon(Icons.add),
                ),
              ),
            ),
          ],
        ),

Method 2

 WidgetsBinding.instance
        .addPostFrameCallback((_) => _insertOverlay(context));
void _insertOverlay(BuildContext context) {
    return Overlay.of(context).insert(
      OverlayEntry(builder: (context) {
        final size = MediaQuery.of(context).size;
        print(size.width);
        return Positioned(
          width: 56,
          height: 56,
          top: size.height - 72,
          left: size.width - 72,
          child: Material(
            color: Colors.transparent,
            child: GestureDetector(
              onTap: () => print('ON TAP OVERLAY!'),
              child: Container(
                decoration: BoxDecoration(
                    shape: BoxShape.circle, color: Colors.redAccent),
              ),
            ),
          ),
        );
      }),
    );
  }

Method 3

1. Scene
Now you need to make a test button that floats on all pages and can be dragged.

2. Ideas
1) The hover button can be implemented using the overlay + overlayentry combination provided by fluent

2) The drag function can be realized by gesturedetector gesture button or draggable (PS: I made a version of draggable, but I found that the original widget will float in place, which is obviously not the effect I want)

3) When I click, I want it to pop up a pop-up box at the bottom, where you can play freely. There is no redundant description in this article

PubScaffold(
      child: MaterialApp(
        theme: CustomTheme.lightTheme,
        darkTheme: CustomTheme.darkTheme,
        themeMode: currentTheme.currentTheme,
        home: Scaffold(
          body: Stack(
            children: [
              _pageList[_currentIndex],
              // Positioned(
              //   left: _offset.dx,
              //   top: _offset.dy,
              //   child: GestureDetector(
              //     onPanUpdate: (d) =>
              //         setState(() => _offset += Offset(d.delta.dx, d.delta.dy)),
              //     child: FloatingActionButton(
              //       onPressed: () {},
              //       backgroundColor: Colors.orange,
              //       child: Icon(Icons.add),
              //     ),
              //   ),
              // ),
            ],
          ),
          bottomNavigationBar: CurvedNavigationBar(
            // key: _bottomNavigationKey,
            index: 0,
            height: 60.0,
            items: <Widget>[
              Icon(Icons.home, size: 30),
              Icon(Icons.list, size: 30),
              Icon(Icons.compare_arrows, size: 30),
              // Icon(Icons.call_split, size: 30),
            ],
            color: Colors.white,
            buttonBackgroundColor: Colors.white,
            backgroundColor: Colors.blueAccent,
            animationCurve: Curves.easeInOut,
            animationDuration: Duration(milliseconds: 600),
            onTap: (index) {
              setState(() {
                _currentIndex = index;
              });
            },
            // letIndexChange: (index) => true,
          ),
        ),
      ),
    );

therePubScaffoldIt’s a floating button component I encapsulated. By wrapping it outside the materialapp, you can realize a button suspended on all components (of course, it can not be a button, and the specific style can be defined by yourself). Let’s take a lookPubScaffoldCode in ~

import 'dart:math';

import 'package:flutter/material.dart';

class PubScaffold extends StatefulWidget {
  final Widget child;
  PubScaffold({this.child});

  @override
  _PubScaffoldState createState() => _PubScaffoldState();
}

class _PubScaffoldState extends State<PubScaffold> {
  bool draggable = false;

  //Offset at rest
  Offset idleOffset = Offset(0, 0);
  //Offset of this move
  Offset moveOffset = Offset(0, 0);
  //Offset of the last down event
  Offset lastStartOffset = Offset(0, 0);

  int count = 0;

  final List<String> testWidgetList = [
    'test 1 ',
    'test 2 ',
  ];

  testAppFun(e) {
    //Todo: your code logic
  }

  //A pop-up window at the bottom is displayed. Here is a test list
  showTestList() {
    showModalBottomSheet(
      context: context,
      enableDrag: false,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(20.0),
          topRight: Radius.circular(20.0),
        ),
      ),
      builder: (BuildContext context) {
        return ListView(
          children: testWidgetList
              .map(
                (e) => Container(
                  decoration: BoxDecoration(
                    border: Border(
                      bottom: BorderSide(color: Color(0xFFe3e3e3)),
                    ),
                  ),
                  child: ListTile(
                    onTap: () => testAppFun(e),
                    title: Text(e),
                  ),
                ),
              )
              .toList(),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        //Display hover button
        WidgetsBinding.instance
            .addPostFrameCallback((_) => _insertOverlay(context));
        return widget.child;
      },
    );
  }

  //Floating button, drag and drop (customizable style)
  void _insertOverlay(BuildContext context) {
    return Overlay.of(context).insert(
      OverlayEntry(builder: (context) {
        final size = MediaQuery.of(context).size;
        print(size.width);
        return Positioned(
          top: draggable ? moveOffset.dy : size.height - 102,
          left: draggable ? moveOffset.dx : size.width - 72,
          child: GestureDetector(
            //Move start
            onPanStart: (DragStartDetails details) {
              setState(() {
                lastStartOffset = details.globalPosition;
                draggable = true;
              });
              if (count <= 1) {
                count++;
              }
            },
            //Moving
            onPanUpdate: (DragUpdateDetails details) {
              setState(() {
                moveOffset =
                    details.globalPosition - lastStartOffset + idleOffset;
                if (count > 1) {
                  moveOffset = Offset(max(0, moveOffset.dx), moveOffset.dy);
                } else {
                  moveOffset = Offset(max(0, moveOffset.dx + (size.width - 72)),
                      moveOffset.dy + (size.height - 102));
                }
              });
            },
            //End of move
            onPanEnd: (DragEndDetails detail) {
              setState(() {
                idleOffset = moveOffset * 1;
              });
            },
            child: TestContainer(
              onPress: () => showTestList(),
            ),
          ),
        );
      }),
    );
  }
}

//The style of the hover button
class TestContainer extends StatelessWidget {
  final Function onPress;
  TestContainer({this.onPress});
  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.transparent,
      child: GestureDetector(
        onTap: onPress,
        child: Container(
          width: 56,
          height: 56,
          alignment: Alignment.center,
          decoration: BoxDecoration(
            shape: BoxShape.circle,
            color: Colors.green[600],
          ),
          child: Text(
            "Test",
            style: TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }
}

1. Global levitation button

Here, we use the overlay component in the material library of fluent. The specific use method is as follows:

void _insertOverlay(BuildContext context) {
    return Overlay.of(context).insert(
      OverlayEntry(builder: (context) {
        final size = MediaQuery.of(context).size;
        print(size.width);
        return Positioned(
          top: draggable ? moveOffset.dy : size.height - 102,
          left: draggable ? moveOffset.dx : size.width - 72,
          child: GestureDetector(
            //Move start
            onPanStart: (DragStartDetails details) {
              setState(() {
                lastStartOffset = details.globalPosition;
                draggable = true;
              });
              if (count <= 1) {
                count++;
              }
            },
            //Moving
            onPanUpdate: (DragUpdateDetails details) {
              setState(() {
                moveOffset =
                    details.globalPosition - lastStartOffset + idleOffset;
                if (count > 1) {
                  moveOffset = Offset(max(0, moveOffset.dx), moveOffset.dy);
                } else {
                  moveOffset = Offset(max(0, moveOffset.dx + (size.width - 72)),
                      moveOffset.dy + (size.height - 102));
                }
              });
            },
            //End of move
            onPanEnd: (DragEndDetails detail) {
              setState(() {
                idleOffset = moveOffset * 1;
              });
            },
            child: TestContainer(
              onPress: () => showTestList(),
            ),
          ),
        );
      }),
    );
  }

Recommended Today

Proper memory alignment in go language

problem type Part1 struct { a bool b int32 c int8 d int64 e byte } Before we start, I want you to calculatePart1What is the total occupancy size? func main() { fmt.Printf(“bool size: %d\n”, unsafe.Sizeof(bool(true))) fmt.Printf(“int32 size: %d\n”, unsafe.Sizeof(int32(0))) fmt.Printf(“int8 size: %d\n”, unsafe.Sizeof(int8(0))) fmt.Printf(“int64 size: %d\n”, unsafe.Sizeof(int64(0))) fmt.Printf(“byte size: %d\n”, unsafe.Sizeof(byte(0))) fmt.Printf(“string size: %d\n”, […]