Наложение ущемленного изображения поверх всего

#flutter

#трепетание

Вопрос:

Я пытаюсь наложить изображение во время максимального масштабирования (я использую класс InteractiveViewer) поверх других объектов (также строки состояния). В основном, как в Instagram. Я ничего не смог найти, читая документы. Подсказка о том, как действовать дальше?

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

Комментарии:

1. Вы хотите отображать Instagram таким образом, чтобы он отображался во всплывающем окне при длительном нажатии?

2. @Aman Verma: нет. Я просто хочу изменить размер изображения, как это делается в Instagram. Когда вы увеличиваете масштаб изображения в Instagram, оно перекрывает другие объекты, даже строку состояния.

3. хорошо, что эффект масштабирования, я попробую

4. Вы можете увеличить maxScale до большего значения, чтобы получить этот эффект @spamup

5. @void: это не работает. Изображение не накладывается поверх других объектов.

Ответ №1:

Согласно этой проблеме в репозитории flutter:

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

Вы можете достичь этого, используя OverlayEntry класс, который будет обрабатывать рендеринг вашего InteractiveViewer дочернего виджета поверх других виджетов.

Кроме того, вы можете найти здесь фрагмент кода для InteractiveViewerOverlay виджета, который вы можете использовать непосредственно в своем проекте.

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

создано:

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

Отредактировано: Вот пример InteractiveViewerOverlay виджета и как его использовать.

Во-первых, InteractiveViewerOverlay виджет

 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,
    );
  }
}
  

Далее, пример реализации InteractiveViewerOverlay виджета.

 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),
      ),
    );
  }
}
  

Комментарии:

1. Не могли бы вы привести пример того, как реализовать виджет InteractiveViewerOverLay? Спасибо.

2. Спасибо. Но моя строка состояния все еще видна, хотя и прозрачна. Я использовал » onInteractionStart: (подробности) { systemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);…», но это приводит к тому, что весь экран на короткое время дрожит.

3. Кроме того, где находится метод remove()? «Метод ‘remove’ был вызван при null. Получатель: null Пытался вызвать: remove()»

4. InteractiveViewer по-прежнему не поддерживает наложение в строке состояния и панели навигации, поэтому проблема все еще открыта на Github. но это решение для наложения InteractiveViewer поверх любого другого виджета внутри дерева, поэтому при масштабировании он займет все пространство экрана. мы ждем, пока команда Futter добавит эту функцию в виджет «InteractiveViewer».

5. Спасибо за разъяснение. Как насчет отсутствующего метода?