transparent_tap 0.1.0
transparent_tap: ^0.1.0 copied to clipboard
A Flutter widget that lets taps pass through the transparent pixels of an image, so only the visible (opaque) part of it is tappable.
transparent_tap #
A Flutter widget that makes an image "click-through" on its transparent pixels. Wrap any widget with it and taps landing on a transparent part of the overlaid image pass straight through to whatever is behind it, while taps on opaque (visible) pixels are handled normally.
Useful for things like:
- Irregularly shaped buttons or map pins (PNG with alpha) sitting on top of other tappable content
- Custom-shaped overlays or badges that shouldn't block interaction with what's underneath
- Interactive illustrations where only the "drawn" part should respond
How it works #
TransparentTapresolves the image you give it (either a decodedui.Imageor anImageProvider) once, and caches its raw RGBA pixel bytes.- On every tap, it maps the tap position into the image's own pixel
coordinates — honoring
fitandalignmentthe same wayImagedoes — and reads that pixel's alpha byte. - If the alpha is above
alphaThreshold, the tap is handled normally. OtherwisehitTestreturnsfalseand the tap passes through to whatever is behind this widget in the tree.
Hit-testing itself is a synchronous byte lookup — the only async work is the one-time image decode when the widget mounts or the image changes.
Installation #
dependencies:
transparent_tap: ^0.1.0
Usage #
import 'package:transparent_tap/transparent_tap.dart';
TransparentTap(
imageProvider: AssetImage('assets/pin_shape.png'),
child: Image.asset('assets/pin_shape.png'),
)
Or, if you already have a decoded image:
TransparentTap(
image: myDecodedUiImage,
fit: BoxFit.contain,
child: myVisibleWidget,
)
Wrap it around anything — an Image, an Icon, a CustomPaint — as long
as the image you pass in matches what's visually rendered by child, so
the alpha lookup lines up with what the user sees.
Example: overlay pin that shouldn't block a map underneath #
Stack(
children: [
GoogleMap(...),
Positioned(
left: 100,
top: 200,
child: TransparentTap(
imageProvider: const AssetImage('assets/custom_pin.png'),
child: Image.asset('assets/custom_pin.png'),
),
),
],
)
Taps on the transparent margins of custom_pin.png fall through to the
map beneath; taps on the visible pin itself are captured by the overlay.
See example/ for a fully self-contained runnable demo (it draws its own
test image at runtime, so no image assets are needed to try it).
API #
TransparentTap #
| Parameter | Type | Default | Description |
|---|---|---|---|
image |
ui.Image? |
— | A pre-decoded image to sample. Provide this or imageProvider. |
imageProvider |
ImageProvider? |
— | An image provider (e.g. AssetImage) to resolve and sample. |
child |
Widget |
required | The widget actually rendered. |
alphaThreshold |
double |
50 |
Alpha value (0–255) above which a pixel counts as "solid"/tappable. |
fit |
BoxFit |
BoxFit.contain |
How the image is fitted within the widget's bounds; should match child's fit. |
alignment |
Alignment |
Alignment.center |
How the fitted image is aligned within the widget's bounds. |
Exactly one of image / imageProvider must be provided. If image data
isn't loaded yet (e.g. still resolving), the widget falls back to standard
hit-testing behavior for child.
Limitations #
- Only pixel alpha drives the decision — color/luminance-based hit testing isn't supported.
- The sampled image and the visual
childmust correspond to the same picture and the samefit/alignment, or the hit-test region will be misaligned with what's on screen.
Contributing #
Issues and PRs welcome.
License #
MIT