Giter VIP home page Giter VIP logo

Comments (5)

huycozy avatar huycozy commented on July 21, 2024 1

I meant changing the feedback signature from Widget feedback to WidgetBuilder feedback

I think it will need to refactor the current existing code/solution. I will mark this as a proposal to have other's thoughts.

from flutter.

huycozy avatar huycozy commented on July 21, 2024

Hi @cachapa
feedback is inserted inside an OverlayEntry which has its context with its Builder. You can try applying the given solution from this detailed answer to see if it works for your case.

from flutter.

cachapa avatar cachapa commented on July 21, 2024

Thank you for the suggestion.

I managed to fix this two ways: using a GlobalKey and wrapping feedback with a StreamBuilder.

To me both solutions seem like hacky workarounds to the issue: the API doesn't follow Flutter convention and has unpredictable behaviour, especially when compared to the neighbouring child and childWhenDrawing.

Would using a builder pattern solve the issue?

from flutter.

huycozy avatar huycozy commented on July 21, 2024

child and childWhenDragging live in a different context while feedback is on an OverlayEntry:

_entry = OverlayEntry(builder: _build);

Widget _build(BuildContext context) {
final RenderBox box = overlayState.context.findRenderObject()! as RenderBox;
final Offset overlayTopLeft = box.localToGlobal(Offset.zero);
return Positioned(
left: _lastOffset!.dx - overlayTopLeft.dx,
top: _lastOffset!.dy - overlayTopLeft.dy,
child: ExcludeSemantics(
excluding: ignoringFeedbackSemantics,
child: IgnorePointer(
ignoring: ignoringFeedbackPointer,
child: feedback,
),
),
);
}

I provide a simple example of Overlay here, hope it will be clearer. In this example, I trigger rebuild from ancestor widget to update Overlay data, but the data on Overlay persists (expected):

Sample code with Overlay
import 'package:flutter/material.dart';

/// Flutter code sample for [Overlay].

void main() => runApp(const OverlayApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: OverlayExample(),
    );
  }
}

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

  @override
  State<OverlayExample> createState() => _OverlayExampleState();
}

class _OverlayExampleState extends State<OverlayExample> {
  OverlayEntry? overlayEntry;
  String text = 'Explore page';

  void createHighlightOverlay({
    required AlignmentDirectional alignment,
    required Color borderColor,
  }) {
    removeHighlightOverlay();

    assert(overlayEntry == null);

    overlayEntry = OverlayEntry(
      builder: (BuildContext context) {
        return SafeArea(
          child: Align(
            alignment: alignment,
            heightFactor: 1.0,
            child: DefaultTextStyle(
              style: const TextStyle(
                color: Colors.blue,
                fontWeight: FontWeight.bold,
                fontSize: 14.0,
              ),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  const Text('Tap here for'),
                  Builder(builder: (BuildContext context) {
                    return Column(
                      children: <Widget>[
                        Text(
                          text,
                          style: const TextStyle(
                            color: Colors.red,
                          ),
                        ),
                        const Icon(
                          Icons.arrow_circle_up,
                          color: Colors.red,
                        ),
                      ],
                    );
                  }),
                ],
              ),
            ),
          ),
        );
      },
    );

    // Add the OverlayEntry to the Overlay.
    Overlay.of(context, debugRequiredFor: widget).insert(overlayEntry!);
  }

  // Remove the OverlayEntry.
  void removeHighlightOverlay() {
    overlayEntry?.remove();
    overlayEntry?.dispose();
    overlayEntry = null;
  }

  @override
  void dispose() {
    // Make sure to remove OverlayEntry when the widget is disposed.
    removeHighlightOverlay();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Overlay Sample'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () {
                createHighlightOverlay(
                  alignment: AlignmentDirectional.bottomCenter,
                  borderColor: Colors.red,
                );
              },
              child: const Text('Explore'),
            ),
            const SizedBox(height: 10.0),
            ElevatedButton(
              onPressed: () {
                removeHighlightOverlay();
              },
              child: const Text('Remove Overlay'),
            ),
            const SizedBox(height: 10.0),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  text = 'Profile page';
                });
              },
              child: const Text('Update Overlay'),
            ),
          ],
        ),
      ),
    );
  }
}
Screen.Recording.2024-05-10.at.19.00.01.mov

Would using a builder pattern solve the issue?

Could you be more specific?

from flutter.

cachapa avatar cachapa commented on July 21, 2024

child and childWhenDragging live in a different context while feedback is on an OverlayEntry

I understand the problem, my point is that the Draggable constructor doesn't communicate that clearly and behaves differently for feedback than it does for its other child widgets.

Would using a builder pattern solve the issue?

Could you be more specific?

I meant changing the feedback signature from Widget feedback to WidgetBuilder feedback, e.g.:

Draggable(
  […],
  feedback: (context) => Container(
    color: Colors.green,
    width: 100,
    height: 100,
    child: Text(_speed.toString(),
      style: Theme.of(context).textTheme.bodyMedium),
  ),
),

Just a suggestion, I'm not sure that would solve the issue tbh.

from flutter.

Related Issues (20)

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.