Überlagern Sie das eingeklemmte Bild über alles

Sep 04 2020

Ich versuche, ein Bild während der maximalen Skalierung (ich verwende die Klasse InteractiveViewer ) über andere Objekte (auch die Statusleiste) zu legen. Grundsätzlich wie auf Instagram. Ich konnte beim Lesen der Dokumente nichts finden. Ein Hinweis zum weiteren Vorgehen?

child: InteractiveViewer(
 transformationController: controller,
 maxScale: 2.0,
 minScale: 2.0,
 child: imageBig,
 fit: BoxFit.fitWidth,
),

Antworten

1 AbdelazeemKuratem Sep 19 2020 at 22:39

Nach diesem Problem im Flatter-Repository:

https://github.com/flutter/flutter/issues/66111

Sie können dies erreichen, indem Sie OverlayEntryClass verwenden, das das Rendern Ihres untergeordneten InteractiveViewerWidgets gegenüber den anderen Widgets übernimmt.

Außerdem finden Sie hier ein Code-Snippet für das InteractiveViewerOverlayWidget, das Sie direkt in Ihrem Projekt verwenden können.

https://gist.github.com/zzterrozz/623531eef065a31470e85175c744c986

erstellt von:

  1. https://github.com/PixelToast
  2. https://github.com/zzterrozz

Bearbeitet: Hier ist ein Beispiel für das InteractiveViewerOverlayWidget und dessen Verwendung.

Zuerst das InteractiveViewerOverlayWidget

class InteractiveViewerOverlay extends StatefulWidget {
  final Widget child;
  final double maxScale;

  const InteractiveViewerOverlay({
    Key key,
    @required this.child,
    this.maxScale,
  }) : super(key: key);

  @override
  _InteractiveViewerOverlayState createState() =>
      _InteractiveViewerOverlayState();
}

class _InteractiveViewerOverlayState extends State<InteractiveViewerOverlay>
    with SingleTickerProviderStateMixin {
  var viewerKey = GlobalKey();
  Rect placeholder;
  OverlayEntry entry;
  var controller = TransformationController();
  Matrix4Tween snapTween;
  AnimationController snap;

  @override
  void initState() {
    super.initState();
    snap = AnimationController(vsync: this);
    snap.addListener(() {
      if (snapTween == null) return;
      controller.value = snapTween.evaluate(snap);
      if (snap.isCompleted) {
        entry.remove();
        entry = null;
        setState(() {
          placeholder = null;
        });
      }
    });
  }

  @override
  void dispose() {
    snap.dispose();
    super.dispose();
  }

  Widget buildViewer(BuildContext context) {
    return InteractiveViewer(
        key: viewerKey,
        transformationController: controller,
        panEnabled: false,
        maxScale: widget.maxScale ?? 2.5,
        child: widget.child,
        onInteractionStart: (details) {
          if (placeholder != null) return;

          setState(() {
            var renderObject =
                viewerKey.currentContext.findRenderObject() as RenderBox;
            placeholder = Rect.fromPoints(
              renderObject.localToGlobal(Offset.zero),
              renderObject
                  .localToGlobal(renderObject.size.bottomRight(Offset.zero)),
            );
          });

          entry = OverlayEntry(
            builder: (context) {
              return Positioned.fromRect(
                rect: placeholder,
                child: buildViewer(context),
              );
            },
          );

          Overlay.of(context).insert(entry);
        },
        onInteractionEnd: (details) {
          snapTween = Matrix4Tween(
            begin: controller.value,
            end: Matrix4.identity(),
          );
          snap.value = 0;
          snap.animateTo(
            1,
            duration: Duration(milliseconds: 250),
            curve: Curves.ease,
          );
        });
  }

  @override
  Widget build(BuildContext context) {
    var viewer = placeholder != null
        ? SizedBox.fromSize(size: placeholder.size)
        : buildViewer(context);

    return Container(
      child: viewer,
    );
  }
}

Als nächstes ein Beispiel für die Implementierung des InteractiveViewerOverlayWidgets.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
          appBar: AppBar(),
          body: ListView(children: [
            Column(
              children: [
                Container(
                    decoration: BoxDecoration(
                        color: Colors.white,
                        border:
                            Border(bottom: BorderSide(color: Colors.green))),
                    width: double.infinity,
                    height: 60,
                    child: Column(children: [
                      Text('Abdelazeem Kuratem',
                          style: TextStyle(color: Colors.black)),
                      Text('5 min', style: TextStyle(color: Colors.black)),
                    ])),
                InteractiveViewerOverlay(
                  child: Image.network(
                    "https://upload.wikimedia.org/wikipedia/commons/6/6a/Mona_Lisa.jpg",
                    fit: BoxFit.contain,
                  ),
                ),
                Container(
                  decoration: BoxDecoration(
                      color: Colors.grey[50],
                      border: Border(top: BorderSide(color: Colors.green))),
                  child: Stack(
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                          _createBottomButton(
                              text: 'Like',
                              icon: Icons.thumb_up,
                              onPressed: () {}),
                          _createBottomButton(
                              text: 'Comment',
                              icon: Icons.comment,
                              onPressed: () {}),
                          _createBottomButton(
                              text: 'Share',
                              icon: Icons.share,
                              onPressed: () {}),
                        ],
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ])),
    );
  }

  Widget _createBottomButton({
    String text,
    IconData icon,
    Null Function() onPressed,
  }) {
    return FlatButton.icon(
      onPressed: onPressed,
      icon: Icon(
        icon,
        color: Colors.green,
        size: 21,
      ),
      label: Text(
        text,
        style: TextStyle(color: Colors.green, fontSize: 14),
      ),
    );
  }
}