flutter_map icon indicating copy to clipboard operation
flutter_map copied to clipboard

InteractiveViewer scrolling scales both the map and the viewport

Open scw67 opened this issue 8 months ago • 6 comments

What is the bug?

When including a FlutterMap inside an InteractiveViewer widget I would expect that scrolling inside the FlutterMap only triggers the scale handler of the map but it seems like the event its not fully consumed and bubbles up to the InteractiveViewer, triggering both handlers. The net result is that the map scales but also does the InteractiveViewer viewport.

Expected behaviour: when scrolling on a FlutterMap inside an InteractiveViewer, only the FlutterMap get scaled, without affecting the InteractiveViewer viewport.

versions used: flutter 3.24.4 flutter_map 7.0.2

How can we reproduce it?

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text("PoC")),
        body: const PoC(),
      )
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 1000,
      height: 1000,
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.black)
        ),
        child: InteractiveViewer(
          child: Stack(
            children: [
              Container(
                width: 50,
                height: 50,
                color: const Color(0xffff0000),
              ),
              Positioned(
                left: 200,
                top: 200,
                child: SizedBox(
                  width: 100,
                  height: 100,
                  child: FlutterMap(
                    options: const MapOptions(
                      initialCenter: LatLng(51.385080, 0.165709),
                      interactionOptions: InteractionOptions(
                        flags: InteractiveFlag.all & ~InteractiveFlag.rotate,
                      ),
                    ),
                    children: [
                      TileLayer(
                        urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                        userAgentPackageName: 'test.test.poc',
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Do you have a potential solution?

No response

scw67 avatar Mar 26 '25 14:03 scw67

Hi @scw67 , Using an InteractiveViewer wrapped around a map doesn't seem quite right to me. Can I ask what you're trying to achieve?

JaffaKetchup avatar Mar 26 '25 14:03 JaffaKetchup

Hey @JaffaKetchup . Yes, I am using the InteractiveViewer as a sort of drawing canvas for placing the nodes of a diagram (think of draw.io, miro board, lucidchart, etc). Besides the basic shapes of a diagram I also want to place widgets like a FlutterMap

scw67 avatar Mar 26 '25 15:03 scw67

I see. You can try to put something 'behind' the FlutterMap to try to absorb events, such as an IgnorePointer or AbsorbPointer?

JaffaKetchup avatar Mar 26 '25 21:03 JaffaKetchup

I'm not sure those would help: wrapping the FlutterMap with either IgnorePointer or AbsorbPointer would just prevent me from interacting with the map altogether Reading flutter_map's code I stumbled upon this piece of code using the PointerSignalResolver precisely to prevent parent/child widgets scrolling simultaneously, which is the behavior I'm reporting. So, it looks like there might be a bug somewhere.

scw67 avatar Mar 26 '25 23:03 scw67

I'll look into whether there's a bug there - the gesture code can be a little messy, so thanks for looking :D. But we've had issues in the past with other types of scrollable: in general it works now.

I meant putting a sized ignore pointer behind the map in the stack, not wrapping the map. I can't remember if Stack itself has a property for changing hit test behaviour? It might.

JaffaKetchup avatar Mar 26 '25 23:03 JaffaKetchup

Tried all the combinations of AbsorbPointer, IgnorePointer and top, bottom of the stack with a sized box that fits the whole viewport to no effect. The behavior persists. To modify the hit test behavior it is needed to extend RenderStack

scw67 avatar Mar 27 '25 08:03 scw67