imagewidget 1.2.1 copy "imagewidget: ^1.2.1" to clipboard
imagewidget: ^1.2.1 copied to clipboard

Fighttech Flutter Image Widget

imagewidget #

Fighttech Flutter Image Widget

setup #

  • Not use package design_system

  • Can define default pacakge name in file main.dart

  ImageWidget.packageDefault = null;

Alt text

Easy render image widget #

ImageWidget(
    pathIcon,
    color: Colors.white,
    height: size,
    width: size,
  ),
ImageWidget.errorWidgetBuilder = () => LayoutBuilder(
          builder: (ctx, contrain) {
            final width = contrain.maxWidth > 240.0 ? 240.0 : contrain.maxWidth;
            return Container(
              width: width,
              alignment: Alignment.center,
              child: SizedBox(
                width: width,
                child: ImageWidget(
                  ImageConstants.imgdefault,
                ),
              ),
            );
          },
        );

Support image string #

SvgImage('string')

import 'dart:async';

import 'package:extended_image/extended_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import '../imagewidget.dart';
import 'widgets/hero_widget.dart';

class ImageListsWidget extends StatefulWidget {
  final Widget? header;
  final double aspectRatio;
  final List<ImageInfoData> images;
  final Color? themeColor;
  final Widget Function(String url)? videoBuilder;
  final Widget Function(String url)? imageBuilder;
  final Widget Function(String url)? imageBuilderFullScreen;
  final bool isShowTitle;
  final bool shrinkWrap;
  final StreamController<void>? onShowFullController;
  final bool isEnableTapFull;

  const ImageListsWidget({
    Key? key,
    this.header,
    this.aspectRatio = 1,
    required this.images,
    this.themeColor,
    this.videoBuilder,
    this.imageBuilder,
    this.imageBuilderFullScreen,
    this.isShowTitle = false,
    this.shrinkWrap = true,
    this.onShowFullController,
    this.isEnableTapFull = true,
  }) : super(key: key);

  @override
  State<ImageListsWidget> createState() => _ImageListsWidgetState();
}

class _ImageListsWidgetState extends State<ImageListsWidget> {
  late StreamController<void> _onShowFull;

  void _onTapDetail(String url, int index) {
    Navigator.of(context).push(
      PageRouteBuilder(
        opaque: false,
        barrierColor: Colors.transparent,
        barrierDismissible: true,
        pageBuilder: (c, a1, a2) => SlidePage(
          url: url,
          images: widget.images,
          header: widget.header,
          index: index,
          themeColor: widget.themeColor,
          isShowTitle: widget.isShowTitle,
          imageBuilderFullScreen: widget.imageBuilderFullScreen,
        ),
        transitionsBuilder: (c, anim, a2, child) =>
            FadeTransition(opacity: anim, child: child),
        transitionDuration: const Duration(milliseconds: 200),
      ),
    );
  }

  @override
  void initState() {
    _onShowFull = widget.onShowFullController ?? StreamController<void>();

    _onShowFull.stream.listen((event) {
      _onTapDetail(widget.images[0].url, 0);
    });
    super.initState();
  }

  @override
  void dispose() {
    _onShowFull.close();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (widget.images.length == 1) {
      final item = widget.images.first;

      return AspectRatio(
        aspectRatio: widget.aspectRatio,
        child: GestureDetector(
          onTap: widget.isEnableTapFull == false
              ? null
              : () {
                  _onTapDetail(item.url, 0);
                },
          child: Hero(
            tag: widget.images.first,
            child: item.type == 'video'
                ? widget.videoBuilder != null
                    ? widget.videoBuilder!(item.url)
                    : Container(
                        alignment: Alignment.center,
                        child: const Text('This is an video'),
                      )
                : widget.imageBuilder != null
                    ? widget.imageBuilder!(item.url)
                    : ImageWidget(item.url),
          ),
        ),
      );
    }

    return GridView.builder(
      primary: false,
      shrinkWrap: widget.shrinkWrap,
      gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
        maxCrossAxisExtent: 300,
        crossAxisSpacing: 6,
        mainAxisSpacing: 6,
      ),
      itemBuilder: (BuildContext context, int index) {
        final String url = widget.images[index].url;

        return GestureDetector(
          onTap: widget.isEnableTapFull == false
              ? null
              : () {
                  _onTapDetail(url, index);
                },
          child: Hero(
            tag: url,
            child: url == 'This is an video'
                ? widget.videoBuilder != null
                    ? widget.videoBuilder!(url)
                    : Container(
                        alignment: Alignment.center,
                        child: const Text('This is an video'),
                      )
                : ImageWidget(url),
          ),
        );
      },
      itemCount: widget.images.length,
    );
  }
}

class SlidePage extends StatefulWidget {
  final Widget? header;

  final String url;
  final List<ImageInfoData> images;
  final int index;
  final Color? themeColor;
  final Widget Function(String url)? videoBuilder;
  final bool isShowTitle;
  final Widget Function(String url)? imageBuilderFullScreen;

  const SlidePage({
    Key? key,
    required this.images,
    this.header,
    required this.index,
    this.themeColor,
    this.videoBuilder,
    required this.isShowTitle,
    required this.url,
    this.imageBuilderFullScreen,
  }) : super(key: key);

  @override
  State<SlidePage> createState() => _SlidePageState();
}

class _SlidePageState extends State<SlidePage> {
  final slidePagekey = GlobalKey<ExtendedImageSlidePageState>();
  late PageController _pageController;
  int pageCurrent = 0;
  bool isShowTitle = true;

  @override
  void initState() {
    pageCurrent = widget.index;
    isShowTitle = widget.isShowTitle;

    _pageController = PageController(initialPage: widget.index);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.transparent,
      child: GestureDetector(
        onTap: () {
          setState(() {
            isShowTitle = !isShowTitle;
          });
        },
        child: Stack(
          children: [
            if (widget.imageBuilderFullScreen != null)
              widget.imageBuilderFullScreen!(widget.url),
            ExtendedImageSlidePage(
              key: slidePagekey,
              slideAxis: SlideAxis.both,
              slideType: SlideType.onlyImage,
              child: GestureDetector(
                child: widget.url == 'This is an video'
                    ? ExtendedImageSlidePageHandler(
                        child: Material(
                          child: widget.videoBuilder != null
                              ? widget.videoBuilder!(widget.url)
                              : Container(
                                  alignment: Alignment.center,
                                  color: Colors.yellow,
                                  child: const Text('This is an video'),
                                ),
                        ),

                        ///make hero better when slide out
                        heroBuilderForSlidingPage: (Widget result) {
                          return Hero(
                            tag: widget.url,
                            child: result,
                            flightShuttleBuilder: (BuildContext flightContext,
                                Animation<double> animation,
                                HeroFlightDirection flightDirection,
                                BuildContext fromHeroContext,
                                BuildContext toHeroContext) {
                              final hero =
                                  (flightDirection == HeroFlightDirection.pop
                                      ? fromHeroContext.widget
                                      : toHeroContext.widget) as Hero;

                              return hero.child;
                            },
                          );
                        },
                      )
                    : HeroWidget(
                        tag: widget.url,
                        slideType: SlideType.onlyImage,
                        slidePagekey: slidePagekey,
                        child: PageView.builder(
                          controller: _pageController,
                          itemCount: widget.images.length,
                          itemBuilder: (context, index) {
                            return ImageZoom(
                              url: widget.images[index].url,
                            );
                          },
                          onPageChanged: (index) {
                            setState(() {
                              pageCurrent = index;
                            });
                          },
                        ),
                      ),
                onTap: () {
                  slidePagekey.currentState!.popPage();
                  Navigator.pop(context);
                },
              ),
            ),
            if (isShowTitle)
              IgnorePointer(
                ignoring: true,
                child: Align(
                  alignment: Alignment.bottomLeft,
                  child: SafeArea(
                    child: Padding(
                      padding: const EdgeInsets.only(bottom: 16.0, left: 16),
                      child: Row(
                        crossAxisAlignment: CrossAxisAlignment.end,
                        children: [
                          Expanded(
                            child: Text(
                              widget.images[pageCurrent].caption ?? '',
                              style: TextStyle(
                                  color: widget.themeColor ?? Colors.black),
                            ),
                          ),
                          Container(
                            color: (widget.themeColor ?? Colors.black)
                                .withOpacity(0.08),
                            margin: const EdgeInsets.only(left: 5, right: 16),
                            padding: const EdgeInsets.symmetric(
                                horizontal: 12, vertical: 2),
                            child: Text(
                              '${pageCurrent + 1}/${widget.images.length}',
                              style: TextStyle(
                                  color: widget.themeColor ?? Colors.black),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
            if (isShowTitle)
              Align(
                alignment: Alignment.topRight,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    Align(
                      alignment: Alignment.bottomRight,
                      child: Padding(
                        padding:
                            const EdgeInsets.only(top: 50, right: 16, left: 16),
                        child: IconButton(
                          onPressed: Navigator.of(context).pop,
                          icon: Icon(
                            CupertinoIcons.clear_circled_solid,
                            color: widget.themeColor ?? Colors.black,
                            size: 30,
                          ),
                        ),
                      ),
                    ),
                    if (widget.header != null) widget.header!
                  ],
                ),
              ),
          ],
        ),
      ),
    );
  }
}
4
likes
140
pub points
73%
popularity
screenshot

Publisher

unverified uploader

Fighttech Flutter Image Widget

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

extended_image, flutter, flutter_svg, lottie

More

Packages that depend on imagewidget