Git Product home page Git Product logo

minikin / popover Goto Github PK

View Code? Open in Web Editor NEW
140.0 3.0 50.0 3.26 MB

Popover for Flutter. A popover is a transient view that appears above other content onscreen when you tap a control or in an area.

Home Page: https://pub.dev/packages/popover

License: MIT License

Dart 47.51% Kotlin 0.15% Swift 1.71% Objective-C 0.04% HTML 1.78% CMake 18.37% C++ 28.76% C 1.69%
flutter dart ios ipados android webapp widget popover modal-dialog pub

popover's Introduction

Popover

Popover screenshots

Popover for Flutter

Supported platforms Popover is released under the MIT license. Effective Dart PRs welcome!
Current Build Status.

Content

Features

A popover is a transient view that appears above other content onscreen when you tap a control or in an area. Typically, a popover includes an arrow pointing to the location from which it emerged. Popovers can be nonmodal or modal. A nonmodal popover is dismissed by tapping another part of the screen or a button on the popover. A modal popover is dismissed by tapping a Cancel or other button on the popover.

Source: Human Interface Guidelines.

Requirements

  • Dart: 3.2.0+
  • Flutter: 3.16.0+

Install

dependencies:
  popover: ^0.3.0

Example

See example/lib/main.dart.

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

class PopoverExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Popover Example')),
        body: const SafeArea(
          child: Padding(
            padding: EdgeInsets.all(16),
            child: Button(),
          ),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 80,
      height: 40,
      decoration: const BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.all(Radius.circular(5)),
        boxShadow: [BoxShadow(color: Colors.black26, blurRadius: 5)],
      ),
      child: GestureDetector(
        child: const Center(child: Text('Click Me')),
        onTap: () {
          showPopover(
            context: context,
            bodyBuilder: (context) => const ListItems(),
            onPop: () => print('Popover was popped!'),
            direction: PopoverDirection.bottom,
            width: 200,
            height: 400,
            arrowHeight: 15,
            arrowWidth: 30,
          );
        },
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Padding(
        padding: const EdgeInsets.symmetric(vertical: 8),
        child: ListView(
          padding: const EdgeInsets.all(8),
          children: [
            InkWell(
              onTap: () {
                Navigator.of(context)
                  ..pop()
                  ..push(
                    MaterialPageRoute<SecondRoute>(
                      builder: (context) => SecondRoute(),
                    ),
                  );
              },
              child: Container(
                height: 50,
                color: Colors.amber[100],
                child: const Center(child: Text('Entry A')),
              ),
            ),
            const Divider(),
            Container(
              height: 50,
              color: Colors.amber[200],
              child: const Center(child: Text('Entry B')),
            ),
            const Divider(),
            Container(
              height: 50,
              color: Colors.amber[300],
              child: const Center(child: Text('Entry C')),
            ),
          ],
        ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Second Route'),
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('Go back!'),
        ),
      ),
    );
  }
}

To see examples of the following package on a device or simulator:

cd example && flutter run

Support

Post issues and feature requests on the GitHub issue tracker.

License

The source code of Popover project is available under the MIT license. See the LICENSE file for more info.

popover's People

Contributors

aliaknsadr-litskevich1-epam avatar kasyanyukd1995 avatar minikin avatar moescs avatar sanjidbillah avatar zwett avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

popover's Issues

Popover not visible on screen if called inside of SliverAppBar action

Describe the bug
I'm calling the showPopover function from an action of the SliverAppBar but the Popover is not shown on the screen. I guess that it is positioned outside of the screen.

Code:

class ManageDocuments extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final sessionState = context.watch<Verified>();
    return CustomScrollView(
      physics: const BouncingScrollPhysics(),
      slivers: <Widget>[
        SliverAppBar(
          // if floating is true the appbar becomes instantly visible if scrolled towards top
          // if it's false the appbar is only visible if completly scrolled back to top
          floating: true,
          expandedHeight: 60.0,
          backgroundColor: Theme.of(context).scaffoldBackgroundColor,
          title: Text(
            "Manage Documents",
            style: TextStyle(color: Theme.of(context).colorScheme.onBackground),
          ),
          centerTitle: true,
          actions: [
            IconButton(
              icon: Icon(
                Icons.add,
                color: Theme.of(context).colorScheme.onBackground,
              ),
              onPressed: () => showPopover(
                context: context,
                bodyBuilder: (context) => Column(
                  children: [
                    Text(L.of(context).patientQuestionnaire),
                    Text(L.of(context).patientQuestionnaire),
                    Text(L.of(context).patientQuestionnaire),
                  ],
                ),
                direction: PopoverDirection.bottom,
              ),
            ),
          ],
        ),
      ],
    );
  }
}

Expected behavior
I expected the Popover to be positioned below the IconButton in the appBar, with the direction of PopoverDirection.bottom

Screenshots
I already clicked on the action IconButton and the background get's dimmed but the popover is out of screen.
Unbenannt

Smartphone (please complete the following information):

  • Device: Pixel C API 30
  • OS: Android 11.0

Space between popover and widget that fired popover

Describe the bug
Space between popover and child.

To Reproduce
Source:

  final bool isStop;
  final ComponentData componentData;
  final NodeData nodeData;
  final ComponentDesignPolicy policy;

  XBaseNode(
      {Key? key,
      required this.nodeData,
      required this.componentData,
      this.isStop = false,
      required this.policy})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
          borderRadius: BorderRadius.all(
            Radius.circular(10),
          ),
          boxShadow: [
            BoxShadow(
              color: Colors.black,
              blurRadius: 2.0,
              spreadRadius: 0.0,
              offset: Offset(2.0, 2.0), // shadow direction: bottom right
            )
          ],
          color: Colors.white),
      child: isStop
          ? Container(
              width: 35,
              height: 35,
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(
                    Radius.circular(10),
                  ),
                  color: Colors.green),
              child: Center(
                child: Icon(
                  nodeData.iconData,
                  color: Colors.white,
                ),
              ),
            )
          : Column(
              children: [
                Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Container(
                        width: 35,
                        height: 35,
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.all(
                              Radius.circular(10),
                            ),
                            color: Colors.green),
                        child: Center(
                          child: Icon(
                            nodeData.iconData,
                            color: Colors.white,
                          ),
                        ),
                      ),
                    ),
                    SizedBox(
                      width: 30,
                    ),
                    Text(
                      nodeData.title,
                      style: TextStyle(fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
                Divider(),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(nodeData.description),
                ),
                SizedBox(
                  height: 30,
                ),
                if ((componentData.data as NodeData)
                    .possibleTriggers
                    .contains(WorkflowNodeConnectorTrigger.Receive))
                  addTrigger(),
                Visibility(
                  visible: showMessageText(componentData.data),
                  child: addMessageNodeContent(
                    (componentData.data as NodeData),
                  ),
                ),
                Container(
                  width: 80,
                  height: 40,
                  decoration: const BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.all(Radius.circular(5)),
                    boxShadow: [
                      BoxShadow(color: Colors.black26, blurRadius: 5)
                    ],
                  ),
                  child: GestureDetector(
                    child: const Center(child: Text('Click Me')),
                    onTap: () {
                      showPopover(
                        context: context,
                        transitionDuration: const Duration(milliseconds: 150),
                        bodyBuilder: (context) => EditNodeDataDialog(
                            componentData: componentData,
                            data: componentData.data as NodeData),
                        onPop: () => print('Popover was popped!'),
                        direction: PopoverDirection.right,
                        width: 300,
                        height: 500,
                      );
                    },
                  ),
                )
              ],
            ),
    );
  }

  bool showMessageText(NodeData data) {
    return data.data is MessageNodeData;
  }

  Widget addMessageNodeContent(NodeData data) {
    if (data.data is MessageNodeData) {
      var messageData = data.data as MessageNodeData;
      return Text(messageData.text);
    }
    return Container();
  }

  Widget addTrigger() {
    return XConnectToMenu(
      child: Padding(
        padding:
            const EdgeInsets.only(left: 16.0, right: 16.0, top: 8, bottom: 8),
        child: Row(
          children: [
            Icon(
              Icons.input,
              color: Colors.green,
            ),
            SizedBox(
              width: 30,
            ),
            Text(
              "On receive",
              style: TextStyle(
                  color: nodeData.hasLinkedTrigger(
                          WorkflowNodeConnectorTrigger.Receive,
                          componentData.id)
                      ? Colors.red
                      : Colors.blue,
                  fontWeight: nodeData.hasLinkedTrigger(
                          WorkflowNodeConnectorTrigger.Receive,
                          componentData.id)
                      ? FontWeight.bold
                      : FontWeight.normal),
            ),
          ],
        ),
      ),
      possibleConnections: possibleConnections(),
      sourceId: componentData.id,
    );
  }

  List<WorkflowNodeType> possibleConnections() {
    var currentComponentData = componentData.data as NodeData;
    var currentComponentType = currentComponentData.type;
    var possibleConnections = WorkflowNodeType.values.where((element) =>
        element != WorkflowNodeType.Start && element != currentComponentType);
    return possibleConnections.toList();
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scrollbar(
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 8),
        child: ListView(
          padding: const EdgeInsets.all(8),
          children: [
            InkWell(
              onTap: () {},
              child: Container(
                height: 50,
                color: Colors.amber[100],
                child: const Center(child: Text('Entry A')),
              ),
            ),
            const Divider(),
            Container(
              height: 50,
              color: Colors.amber[200],
              child: const Center(child: Text('Entry B')),
            ),
            const Divider(),
            Container(
              height: 50,
              color: Colors.amber[300],
              child: const Center(child: Text('Entry C')),
            ),
          ],
        ),
      ),
    );
  }
} 

Expected behavior
Popover next to calling widget

Screenshots
image

Desktop (please complete the following information):

  • OS: macOs

Any suggestions?

[Bug]: Doesn't show the body of popover

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

There were existing bugs on this, but none were from the body of the scaffold. This is happening even in the body of a scaffold. When, I am clicking the button, I just see the app becoming grayish and that's all. No popup menu. This happens with my code only. How ever I try. Even if I just copy paste the code from the example folder. But, when I run from the example folder everything is fine.

Expected Behavior

There should be a popup.

What operating system are you seeing the problem on?

Linux, Android

Relevant log output

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

void main() {
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // TRY THIS: Try running your application with "flutter run". You'll see
        // the application has a purple toolbar. Then, without quitting the app,
        // try changing the seedColor in the colorScheme below to Colors.green
        // and then invoke "hot reload" (save your changes or press the "hot
        // reload" button in a Flutter-supported IDE, or press "r" if you used
        // the command line to start the app).
        //
        // Notice that the counter didn't reset back to zero; the application
        // state is not lost during the reload. To reset the state, use hot
        // restart instead.
        //
        // This works for code too, not just values: Most code changes can be
        // tested with just a hot reload.
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // TRY THIS: Try changing the color here to a specific color (to
        // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
        // change color while the other colors stay the same.
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Center(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          //
          // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
          // action in the IDE, or press "p" in the console), to see the
          // wireframe for each widget.

          child: IconButton(
            onPressed: () {
              showPopover(
                backgroundColor: Colors.red,
                height: 100,
                width: 100,
                context: context,
                bodyBuilder: (context) => const Dialog(
                  backgroundColor: Colors.red,
                ),
              );
            },
            icon: const Icon(Icons.add),
          ),
        ),
      ),
    );
  }
}

Anything else?

My pubspec.yaml file

name: test
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1

environment:
  sdk: '>=3.2.3 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  popover: ^0.2.8+2

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0

flutter:
  uses-material-design: true

And my flutter doctor output

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.16.3, on Ubuntu 23.10 6.5.0-13-generic, locale
    en_US.UTF-8)
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/linux#android-setup for
      more details.
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2023.1)
[✓] Connected device (2 available)
[✓] Network resources

! Doctor found issues in 1 category.

Code of Conduct

  • I agree to follow this project's Code of Conduct

arrowDyOffset not work

Does arrowDyOffset mean the space that between arrow top and button bottom ?

It looks like not work.

showPopover(
    context: context,
    backgroundColor: Colors.black.withOpacity(0.9),
    barrierColor: Colors.transparent,
    bodyBuilder: (context) => const ListItems(),
    onPop: () => print('Popover was popped!'),
    direction: PopoverDirection.bottom,
    width: 136,
    height: 252,
    arrowHeight: 6,
    arrowWidth: 12,
    arrowDyOffset: 10,
);

[minikin-patch-1] is STALE

minikin-patch-1 has had no activity for 769 days.

This branch will be automatically deleted in 0 days.

Removal of isParentAlive

With the upgrade to 0.2.8 is the property isParentAlive deprecated / unusable. We used this property to prevent a error when resizing the screen. For example on web you can you resize your window. based on the size of the window certain elements will be shown or hidden. The error happens when the popover widget is active and with a resize of the window the anchor/parent widget is removed.

This will cause the following error:

══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞══════════════════════
The following assertion was thrown during a scheduler callback:
Cannot get renderObject of inactive element.
In order for an element to have a valid renderObject, it must be
active, which means it is part of the tree.
Instead, this element is in the _ElementLifecycle.defunct state.
If you called this method from a State object, consider guarding
it with State.mounted.
The findRenderObject() method was called for the following
element:
  StatefulElement#8e63d(DEFUNCT)
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49      throw_
packages/flutter/src/widgets/framework.dart 4186:9                                <fn>
packages/flutter/src/widgets/framework.dart 4198:14                               findRenderObject
packages/popover/src/utils/build_context_extension.dart 10:24                     BuildContextExtension.getWidgetLocalToGlobal
packages/popover/src/popover_item.dart 137:42                                     [_configureRect]
packages/flutter/src/widgets/framework.dart 1133:30                               setState
packages/popover/src/popover_item.dart 89:14                                      <fn>
packages/flutter/src/scheduler/binding.dart 1289:15                               [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1227:9                                handleDrawFrame
packages/flutter/src/scheduler/binding.dart 1076:5                                [_handleDrawFrame]
dart-sdk/lib/async/zone.dart 1398:13                                              _rootRun
dart-sdk/lib/async/zone.dart 1300:19                                              run
dart-sdk/lib/async/zone.dart 1208:7                                               runGuarded
lib/_engine/engine/platform_dispatcher.dart 1170:9                                invoke
lib/_engine/engine/platform_dispatcher.dart 218:5                                 invokeOnDrawFrame
lib/_engine/engine/initialization.dart 190:45                                     <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 367:37  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 372:39  dcall

backgrounColor only effects arrow

Describe the bug
A clear and concise description of what the bug is.
Set the background color, only the arrow part takes effect.

To Reproduce
Steps to reproduce the behavior:

  1. download example;
  2. set backgroundColor to Colors.red;
  3. run example;

Expected behavior
the popover is red

Screenshots

showPopover(
  context: context,
  /// change here
  bodyBuilder: (context) => const SizedBox(
    width: 200,
    height: 400,
  ),
  onPop: () => print('Popover was popped!'),
  direction: PopoverDirection.bottom,
  /// change here
  backgroundColor: Colors.red,
  width: 200,
  height: 400,
  arrowHeight: 15,
  arrowWidth: 30,
);

Popover breaks when opened to the right

Describe the bug
When I try to open the popover to the right it breaks

To Reproduce
Steps to reproduce the behavior:

  1. Download example repo
  2. Set PopoverDirection.right in direction

Expected behavior
Displayed popover don't breaks

Screenshots
Снимок экрана 2021-02-07 в 22 50 18

Desktop (please complete the following information):

  • OS: Mac OS
  • Browser Chrome
  • Version 88.0.4324.150

Additional context
Add any other context about the problem here.

Popover is pointing incorrectly

Describe the bug
Whenever I use responsive_framework or add packages like window_manager (for Desktop to add borders in the app window) the popup arrow points incorrectly and to the wrong place (see Screenshot section and Additional context section for problem and possible solution).

To Reproduce
Steps to reproduce the behavior:

  1. Add responsive_framework and set it up for rescaling (you can also try in the example of it)
  2. Add popover to a widget
  3. Click on that widget
  4. See that popover is shifted

Expected behavior
It should exactly point to the widget.

Screenshots
popoverss
.

Desktop (please complete the following information):

  • OS: Windows 11
  • Browser N.A.
  • Version Latest

Smartphone (please complete the following information):

  • Device: any
  • OS: Android, iOS both
  • Browser N.A.
  • Version Latest

Additional context
On the other hand super_tooltip works perfectly and points exactly to the widget, Here is the link where they do the computing.
https://github.com/escamoteur/super_tooltip/blob/40ca162d284a6f665880dea03ac28cea3c040966/lib/super_tooltip.dart#L236-L239

Error when parent is removed even with isParentAlive: () => mounted

Describe the bug
the "red screen of death" appears when parent widget is removed and popover is shown.

To Reproduce
Steps to reproduce the behavior:

  1. a ListView.builder generates a variable number of stateful widgets based on a list (provided by a BlocBuilder). Each of these widgets contains an InkWell with showPopover associated to the onTap parameter. in the body of the popover a BlocListener is present to ensure that, if the list changes and the parent widget is removed, the popover uses navigator.pop to pop itself immediately;
  2. the user taps on one of the InkWell and the popover appears;
  3. the list updates, the parent widget should be removed;
  4. ListView.builder rebuilds, removing the appropriate element;
  5. popover throws the following error just before popping itself, even if isParentAlive is set to () => mounted. The same error happens when, without using navigator.pop inside the BlocListener, is the user that taps outside the popover area after parent is removed;

`======== Exception caught by widgets library =======================================================
The following assertion was thrown building LayoutBuilder:
Cannot get renderObject of inactive element.

In order for an element to have a valid renderObject, it must be active, which means it is part of the tree.
Instead, this element is in the _ElementLifecycle.inactive state.
If you called this method from a State object, consider guarding it with State.mounted.
The findRenderObject() method was called for the following element: PlayerStory
dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#e783b]]
state: _PlayerStoryState#a1542
The relevant error-causing widget was:
MaterialApp MaterialApp:file:///Users/gianlucagalli/AndroidStudioProjects/hero_realms_life_counter/lib/main.dart:104:18
When the exception was thrown, this was the stack:
#0 Element.findRenderObject. (package:flutter/src/widgets/framework.dart:4039:9)
#1 Element.findRenderObject (package:flutter/src/widgets/framework.dart:4052:6)
#2 _PopoverItemState._configure (package:popover/src/popover_item.dart:100:32)
#3 _PopoverItemState.build. (package:popover/src/popover_item.dart:57:9)
#4 _LayoutBuilderElement._layout.layoutCallback (package:flutter/src/widgets/layout_builder.dart:119:77)
#5 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2597:19)
#6 _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:153:12)
#7 RenderObject.invokeLayoutCallback. (package:flutter/src/rendering/object.dart:2025:59)
#8 PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:918:15)
#9 RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2025:14)
#10 RenderConstrainedLayoutBuilder.rebuildIfNecessary (package:flutter/src/widgets/layout_builder.dart:227:7)
#11 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:316:5)
#12 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1757:7)
#13 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:887:18)
#14 RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:504:19)
#15 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:892:13)
#16 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#17 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#18 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#19 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997:5)
#23 _invoke (dart:ui/hooks.dart:151:10)
#24 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#25 _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
====================================================================================================`
Expected behavior
popover not throwing exceptions

Smartphone (please complete the following information):

  • Device: OnePlus 5T
  • OS: Android 10

Additional context
here is the code:

//...
ListView.builder(
                physics: const BouncingScrollPhysics(),
                scrollDirection: Axis.horizontal,
                //shrinkWrap: true,
                controller: _scrollController,
                itemCount: playersList.length,
                itemBuilder: (BuildContext context, int index) {
                  return PlayerStory(user: playersList[index].user);
                },
              ),
//...
class PlayerStory extends StatefulWidget {
  const PlayerStory({
    super.key,
    required this.user,
  });

  final User user;

  @override
  State<PlayerStory> createState() => _PlayerStoryState();
}

class _PlayerStoryState extends State<PlayerStory> {
  @override
  Widget build(BuildContext context) {
    double avancedAvatarSize = 17.w;
    double dyOffset = -10.0;
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: InkWell(
        onTap: () {
          showPopover(
            context: context,
            transitionDuration: const Duration(milliseconds: 150),
            backgroundColor: Theme.of(context).primaryColor,
            bodyBuilder: (ctx) {
              return MultiBlocProvider(
                providers: [
                  BlocProvider.value(
                    value: BlocProvider.of<HealthCalculationCubit>(context),
                  ),
                  BlocProvider.value(
                    value: BlocProvider.of<UserBloc>(context),
                  ),
                  BlocProvider.value(
                    value: BlocProvider.of<PlayersBloc>(context),
                  ),
                  BlocProvider.value(
                    value: BlocProvider.of<GameBloc>(context),
                  ),
                ],
                child: Padding(
                  padding: const EdgeInsets.all(30.0),
                  child: BlocListener<PlayersBloc, PlayersState>(
                    listener: (ctx, state) {
                      if (state.players!.every(
                          (player) => player!.user!.id != widget.user.id)) {
                        Navigator.pop(ctx);
                      }
                    },
                    child: Container(//...
                    ),
                  ),
                ),
              );
            },
            onPop: () => print('Popover was popped!'),
            isParentAlive: () => mounted,
            direction: PopoverDirection.bottom,
            radius: 5.w,
            width: 90.w,
            arrowDyOffset: dyOffset,
            contentDyOffset: dyOffset,
          );
        },
        child: AnimatedContainer(//...
        ),
      ),
    );
  }
}

Error setting full screen width display

1、The pop-up box displayed an error when I set this code:width: MediaQuery.of(context).size.width,as follow:
2、
1619607442(1)

How do I set this to get rid of this distance?

Cannot dismiss popover when accessibility mode enabled (Android Only)

Describe the bug
Currently, we are implementing accessibility in our project, and we found out that, we cannot dismiss popover in accessibility mode on android (on iOS it works ok)

To Reproduce
Steps to reproduce the behavior:

  1. Add tooltip, open tooltip
  2. Swipe till you reach last element of accessibility, after last element it should focus on outside of popover and speak out dismiss
  3. Try this on Android and on iOS to see the difference

Expected behavior
It should focus outside of popover and on double tap it should dismiss popover
Desktop (please complete the following information):

  • OS: Android

Smartphone (please complete the following information):

  • Device: Pixel C
  • OS: Android

Additional context
You can move accessibility focus by doing horizontal swipe in accessibility mode

popover ^0.2.8 which doesn't match any versions

I tried to install popover of version 0.2.8
But showing error as "example depends on popover ^0.2.8 which doesn't match any versions, version solving failed.
popover: ^0.2.8)" on after flutter pub get

is this version not available?

popOver triangle position not changing on device orientation changed

Describe the bug
popOver triangle position not changing on device orientation changed, works only on item tap

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: Nexus 10
  • OS: Android API 29

type 'RenderSliverList' is not a subtype of type 'RenderBox' in type cast

When the exception was thrown, this was the stack:
#0 _PopoverItemState._configure (package:popover/src/popover_item.dart:86:51)
#1 _PopoverItemState.build. (package:popover/src/popover_item.dart:55:9)
#2 _LayoutBuilderElement._layout. (package:flutter/src/widgets/layout_builder.dart:121:31)
#3 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2535:19)
#4 _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:118:12)

I called it on e button in a list item like:
IconButton(
splashRadius: 24,
icon: Image.asset(
'assets/images/icon_more.png',
width: 20,
),
onPressed: () {
showPopover(
context: context,
transitionDuration: const Duration(milliseconds: 150),
bodyBuilder: (context) => const ListItems(),
onPop: () => print('Popover was popped!'),
direction: PopoverDirection.top,
width: 200,
height: 400,
arrowHeight: 15,
arrowWidth: 30,
);
},
),

Screen Transition inside the popover?

Is there a way to transition to the next screen inside Popover?

In terms of example of this repository, I'd like to push SecondRoute over the ListItems inside the shown popover, and enable pop from SecondRoute to ListItems also still inside the popover.

Popover doesn't show up from AppBar

when the showPopOver method is called from an IconButton placed in the AppBar the popover doesn't show up, my app bar looks like this:

AppBar(
          title: const Text('Popover Example'),
          actions: [
            IconButton(
              icon: Icon(Icons.sort),
              onPressed: () {
                showPopover(
                  context: context,
                  bodyBuilder: (context) => const ListItems(),
                  onPop: () => print('Popover was popped!'),
                  direction: PopoverDirection.top,
                  width: 200,
                  height: 400,
                  arrowHeight: 15,
                  arrowWidth: 30,
                );
              },
            ),
          ],
        )

PopoverItem._configureRect() throws trying to access unmounted context when popover is open

Describe the bug
If you enable widget selection mode in VSCode's Widget Inspector while the popover is open, it triggers didChangeDependencies to schedule a _configureRect in PopoverItem. The problem is that the BuildContext becomes unmounted between didChangeDependencies and the post frame callback.

To Reproduce
Steps to reproduce the behavior:

  1. Use VSCode.

  2. Add a popover using showPopover().

  3. Run the app using VSCode's debugger.

  4. Open the Widget Inspector.

  5. Open the popover in the app (trigger a call to showPopover()).

  6. Click the toggle button to turn select widget mode on in the Widget Inspector.

  7. BuildContextExtension.getWidgetLocalToGlobal() in _configureRect() throws the following error:

    FlutterError (Cannot get renderObject of inactive element.
    In order for an element to have a valid renderObject, it must be active, which means it is part of the tree.
    Instead, this element is in the _ElementLifecycle.defunct state.
    If you called this method from a State object, consider guarding it with State.mounted.
    The findRenderObject() method was called for the following element:
    StatelessElement#7e777(DEFUNCT))

Expected behavior
No error should be thrown.

Desktop (please complete the following information):

  • OS: Windows 11
  • Desktop app
  • Version 10.0.22621 Build 22621

Additional comments
A possible solution is to add if (!widget.context.mounted) return; at the top of _configureRect(). I would generate a pull request, but I'm not sure if this would be exempt from testing when reading your guidelines. I can't think of a good way to test it.

[Bug]: Popover not centered

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

I'm not sure that's a bug, but I need help. I'm trying to centered (or at least change position) of the popover in x axis. how could I do it?

Simulator Screenshot - iPhone 14 - 2023-12-14 at 15 29 23

Expected Behavior

No response

What operating system are you seeing the problem on?

iOS

Relevant log output

No response

Anything else?

`showPopover(

          context: context,
          width: 150,
          height: 100,
          direction: PopoverDirection.bottom,
          backgroundColor: Theme.of(context).colorScheme.primaryContainer,
          bodyBuilder: (context) {
            return Column(children: [
              Container(
                height: 50,
                decoration: BoxDecoration(
                  color: Theme.of(context).colorScheme.primaryContainer,
                ),
                child: Padding(
                  padding: const EdgeInsets.only(
                      left: 5, right: 5, top: 2, bottom: 2),
                  child: Row(children: [
                    Icon(Icons.edit),
                    SizedBox(width: 5),
                    Text("Modifica",
                        style: GoogleFonts.montserrat(
                          color: Colors.white,
                          fontSize: 16,
                          fontWeight: FontWeight.w500,
                        ))
                  ]),
                ),
              ),
              Container(
                height: 50,
                decoration: BoxDecoration(
                  color: Theme.of(context).colorScheme.primaryContainer,
                ),
              ),
            ]);
          });`

Code of Conduct

  • I agree to follow this project's Code of Conduct

Open a popover without user interaction

Great package guys. Thanks!

One of the things I'd like to use Popover for is to display information to the user without them needing to tap on a button to see it. Then the user can tap the button to toggle the popover closed.

Is there a way to do this?

Popover should adjust its size when keyboard is shown/hidden

Native iOS popovers track the software keyboard events and reposition themselves if necessary, when the keyboard is shown/hidden.
If the popover overlaps with the keyboard it is:

  • moved above the keyboard, if there is enough room to show it
  • resized to fit the area over the keyboard, if the original popover was too big to fit

Your popover implementation does a great job in showing the popovers that do not have input fields. E.g. lists of choices.
But if popover needs to collect some user's input, we still have to use flutter dialog.
It could be great if we could use popovers, as they feel more at home, when on iOS.

I do not know if it helps, but we use keyboard_avoider in our application to make the parts that should not overlap with keyboard auto-resize. It is abandoned and not-null safe. But perhaps could be used as a reference.

How to set the popover's location?

If a widget's width is large, the popover will be shown from the widget's bottom left, not center.
How can I choose to show the popover's location?
Thanks.

[Bug]: half of the widget is not shown

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

The popover widget doesn't abide by the constraints of the screen, half of it is not shown when the button is at the edge of the screen..
1101bf63-0a8d-4899-8acb-bac0902bcecc

Expected Behavior

This only happened when I updated to the latest flutter version and updated the package to the lastest version, it used to work correctly before now I'm experiencing this issue even when used the code shown in the example of the package..

What operating system are you seeing the problem on?

Android

Relevant log output

No response

Anything else?

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

not showing any popover

when i try to show by calling showPopOver()
i got just effect like alert dialog box not and popover
so pls solve this issue i searched lots of but i can not find solution out there.

Example throws error on desktop

Describe the bug
An error regarding scroll controllers is thrown by the framework when attempting to move the mouse inside a popover.

To Reproduce
Steps to reproduce the behavior:

  1. Launch as desktop app on Windows.
  2. Click on top left expander.
  3. Move mouse to the right, down, and back to come into the popover from the right side (not sure this is necessary).
  4. See error.

Expected behavior
No exception should be thrown.

Exception

FlutterError (The Scrollbar's ScrollController has no ScrollPosition attached.
A Scrollbar cannot be painted without a ScrollPosition.
The Scrollbar attempted to use the PrimaryScrollController. This ScrollController should be associated with the ScrollView that the Scrollbar is being applied to.A ScrollView with an Axis.vertical ScrollDirection on mobile platforms will automatically use the PrimaryScrollController if the user has not provided a ScrollController. To use the PrimaryScrollController explicitly, set ScrollView.primary to true for the Scrollable widget.)

Video
https://user-images.githubusercontent.com/3419440/221957134-6f36dbab-35b3-4c93-a4f7-d1082b41887d.mp4

Desktop (please complete the following information):

  • OS: Windows
  • Browser: Desktop app
  • Version 11

Additional context
The problem is caused because the Flutter team decided to have ListViews create their own ScrollBars on desktop apps. So you have an extra one.

The fix
Just don't create the extra ScrollBar for desktop apps.
https://user-images.githubusercontent.com/3419440/221979365-b5e629ff-0626-48b6-a673-9f670f6ab7f5.mp4

How to manually turn it off

Is your feature request related to a problem? Please describe.
How to manually turn it off
Describe the solution you'd like
click a button hide popover .

Add fade animation as an alternative to default scale one

Is your feature request related to a problem? Please describe.
Popover used in gtk apps has a fade transition to open instead of scale one, So this package doesn't match consisitency.

Describe the solution you'd like
Add a way for users to specify there own transitions or add default transitions enum which contains Scale and Fade as a value and user can choose that when calling showPopover.

Describe alternatives you've considered
...

Additional context
Libadwaita library uses fade animation for the popover so we need it.

Odd/broken box shadow

There're gaps in the shadow:

shadow: [const BoxShadow(blurRadius: 40)],
image

and to make it more pronounced:

  shadow: [
    const BoxShadow(
        offset: Offset(30, 30), blurRadius: 0)
  ],
image

Enable usage of PopOver as a widget

Thanks for your work first of all.

If I'm not mistaken, we can currently, only use the showPopover() method to show a Popover.
It would be really nice, however, if there was a Popover widget we could use in our build methods.

The reason I'm asking for this is, that I would like to create a size-aware widget that would render a Scaffold on smaller devices and a Popover on larger devices. Currently, I'd have to make the differentiation in the onTap() method but I'd prefer to do it in my SizeAwarePopover widget's build method.

[Bug]: Theme is not being captured before popover is pushed

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

The bodyBuilder provides a context that is not inherited from the context parameter of the showPopover() function, resulting in Material's default colors being used instead of the app's theme colors.

Expected Behavior

As done in dialog.dart of Google's Material package, the theme from the context should be captured and passed to the RawDialogRoute.push()
Exemple from the Material lib:

final CapturedThemes themes = InheritedTheme.capture(
    from: context,
    to: Navigator.of(
      context,
      rootNavigator: useRootNavigator,
    ).context,
  );

What operating system are you seeing the problem on?

macOS, iOS, Android, Windows

Relevant log output

No response

Anything else?

Work around would be to wrap the return of the bodyBuilder in a Theme widget using the previous context, like so:

showPopover(
      context: context,
      direction: PopoverDirection.bottom,
      arrowHeight: 8.0,
      arrowWidth: 16.0,
      radius: 12.0,
      width: 740.0,
      height: 400.0,
      bodyBuilder: (final ctx) {
        return Theme(
          data: context.theme,
          child: const MyWidgetInsidePopover(),
        );
      },
    );

Code of Conduct

  • I agree to follow this project's Code of Conduct

How to close the popover by pressed a close button in body Widget?

something like this

Widget _test(){
 return OutlinedButton(
        child: Text("close this popover"),
        onPressed: () {
           // close this popover
          // ....?
        }
  )
}

Widget _show(){
  return GestureDetector(
      onTap: () {
        showPopover(
            width: ScreenUtil.getScreenW(context),
            context: context,
            radius: 0,
            arrowHeight: 0,
            arrowWidth: 0,
            bodyBuilder: (context) =>  _test(counter));
   })
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.