Flutter: How to get the pixel color when tapping somewhere on an image?

142

Solution 1

You can get the touch position by using a GestureDetector, and then the pixel color by using the ImagePixels widget from the image_pixels package:

ImagePixels(
   imageProvider: ...,
   builder: (BuildContext context, ImgDetails img) {
      var color = img.pixelColorAt(x, y);

This is a working example:

import 'package:image_pixels/image_pixels.dart';
...

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, this.title}) : super(key: key);
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final AssetImage flutter = const AssetImage("lib/images/FlutterLogo.jpg");

  Offset localPosition = const Offset(-1, -1);
  Color color = const Color(0x00000000);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SizedBox.expand(
        child: Column(
          children: [
            const Expanded(
              flex: 1,
              child: Center(
                child: Text('Tap the image to see the pixel color:'),
              ),
            ),
            Expanded(
                flex: 4,
                child: Padding(
                    padding: const EdgeInsets.all(40.0),
                    child: Center(
                        child: Container(
                            color: Colors.grey,
                            child: Listener(
                                onPointerMove: (PointerMoveEvent details) {
                                  setState(() {
                                    localPosition = details.localPosition;
                                  });
                                },
                                onPointerDown: (PointerDownEvent details) {
                                  setState(() {
                                    localPosition = details.localPosition;
                                  });
                                },
                                child: ImagePixels(
                                    imageProvider: flutter,
                                    builder: (BuildContext context, ImgDetails img) {
                                      var color = img.pixelColorAt!(
                                        localPosition.dx.toInt(),
                                        localPosition.dy.toInt(),
                                      );

                                      WidgetsBinding.instance!.addPostFrameCallback((_) {
                                        if (mounted)
                                          setState(() {
                                            if (color != this.color) this.color = color;
                                          });
                                      });

                                      return SizedBox(
                                        width: 150,
                                        height: 213,
                                        child: Image(image: flutter),
                                      );
                                    })))))),
            
            Expanded(
              flex: 2,
              child: Column(
                children: [
                  Container(width: 75, height: 55, color: color),
                  Container(height: 20),
                  Text(localPosition.toString()),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Get the code from GitHub.

Note: I am the author of the package.

Solution 2

You can use/add a GestureDetector as parent of stack, and register onTapDownDetails listener. This will call the listenr on every tap down and will give you the offset of the tap. Use the TapDownDetail Parameter of that event listener.

Code you can use :

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  MyHomePageState createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('Popup Demo'),
        ),
        body: new MyWidget());
  }
}

class MyWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new MyWidgetState();
  }
}

class MyWidgetState extends State<MyWidget> {
  double posx = 100.0;
  double posy = 100.0;

  void onTapDown(BuildContext context, TapDownDetails details) {
    print('${details.globalPosition}');
    final RenderBox box = context.findRenderObject();
    final Offset localOffset = box.globalToLocal(details.globalPosition);
    setState(() {
      posx = localOffset.dx;
      posy = localOffset.dy;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTapDown: (TapDownDetails details) => onTapDown(context, details),
      child: new Stack(fit: StackFit.expand, children: <Widget>[
        // Hack to expand stack to fill all the space. There must be a better
        // way to do it.
        new Container(color: Colors.white),
        new Positioned(
          child: new Text('hello'),
          left: posx,
          top: posy,
        )
      ]),
    );
  }
}
Share:
142
NuttA
Author by

NuttA

Updated on January 03, 2023

Comments

  • NuttA
    NuttA about 1 year

    Flutter: How to get the pixel color when tapping somewhere on an image?