`
iaiai
  • 浏览: 2203282 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Flutter使用Https加载图片

阅读更多
Flutter使用Https加载图片

使用http加载图片出现
CERTIFICATE_VERIFY_FAILED: self signed certificate(handshake.cc:352

表示HTTPS项目不可使用官网的加载图片组件
需要自定义一个图片加载组件
自定义两个类,
建议存放在一起,以后有HTTPS加载可以直接使用

文件名自定义
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui show Codec;
import 'dart:ui' show Size, Locale, TextDirection, hashValues;

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class NetworkImageWithoutAuth extends ImageProvider<NetworkImageWithoutAuth> {
  /// Creates an object that fetches the image at the given URL.
  ///
  /// The arguments must not be null.
  const NetworkImageWithoutAuth(this.url, { this.scale = 1.0 , this.headers })
      : assert(url != null),
        assert(scale != null);

  /// The URL from which the image will be fetched.
  final String url;

  /// The scale to place in the [ImageInfo] object of the image.
  final double scale;

  /// The HTTP headers that will be used with [HttpClient.get] to fetch image from network.
  final Map<String, String> headers;

  @override
  Future<NetworkImageWithoutAuth> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<NetworkImageWithoutAuth>(this);
  }

  @override
  ImageStreamCompleter load(NetworkImageWithoutAuth key,DecoderCallback decode) {
    return MultiFrameImageStreamCompleter(
        codec: _loadAsync(key),
        scale: key.scale,
        informationCollector: () sync* {
          yield DiagnosticsProperty<ImageProvider>('Image provider', this);
          yield DiagnosticsProperty<NetworkImageWithoutAuth>('Image key', key);
        },
    );
  }

  static final HttpClient _httpClient = HttpClient();

  Future<ui.Codec> _loadAsync(NetworkImageWithoutAuth key) async {
    assert(key == this);
    //解决不安全证书校验通不过的问题
    _httpClient.badCertificateCallback = (X509Certificate cert,String host,int port){
      return true;
    };
    final Uri resolved = Uri.base.resolve(key.url);
    //todo:打开https请求
    final HttpClientRequest request = await _httpClient.getUrl(resolved);
    //todo:设置请求头
    request.headers.add("token", "token");
    final HttpClientResponse response = await request.close();
    if (response.statusCode != HttpStatus.ok)
      throw Exception('HTTP request failed, statusCode: ${response?.statusCode}, $resolved');

    final Uint8List bytes = await consolidateHttpClientResponseBytes(response);
    if (bytes.lengthInBytes == 0)
      throw Exception('NetworkImage is an empty file: $resolved');

    return PaintingBinding.instance.instantiateImageCodec(bytes);
  }

  @override
  bool operator ==(dynamic other) {
    if (other.runtimeType != runtimeType)
      return false;
    final NetworkImageWithoutAuth typedOther = other;
    return url == typedOther.url
        && scale == typedOther.scale;
  }

  @override
  int get hashCode => hashValues(url, scale);

  @override
  String toString() => '$runtimeType("$url", scale: $scale)';
}

第二个类
import 'package:flutter/material.dart';
import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

//import 'basic.dart';
//import 'framework.dart';
//import 'image.dart';
//import 'ticker_provider.dart';
import 'image_provider_without_auth.dart';

// Examples can assume:
// Uint8List bytes;

/// An image that shows a [placeholder] image while the target [image] is
/// loading, then fades in the new image when it loads.
///
/// Use this class to display long-loading images, such as [new NetworkImage],
/// so that the image appears on screen with a graceful animation rather than
/// abruptly pops onto the screen.
///
/// If the [image] emits an [ImageInfo] synchronously, such as when the image
/// has been loaded and cached, the [image] is displayed immediately and the
/// [placeholder] is never displayed.
///
/// [fadeOutDuration] and [fadeOutCurve] control the fade-out animation of the
/// placeholder.
///
/// [fadeInDuration] and [fadeInCurve] control the fade-in animation of the
/// target [image].
///
/// Prefer a [placeholder] that's already cached so that it is displayed in one
/// frame. This prevents it from popping onto the screen.
///
/// When [image] changes it is resolved to a new [ImageStream]. If the new
/// [ImageStream.key] is different this widget subscribes to the new stream and
/// replaces the displayed image with images emitted by the new stream.
///
/// When [placeholder] changes and the [image] has not yet emitted an
/// [ImageInfo], then [placeholder] is resolved to a new [ImageStream]. If the
/// new [ImageStream.key] is different this widget subscribes to the new stream
/// and replaces the displayed image to images emitted by the new stream.
///
/// When either [placeholder] or [image] changes, this widget continues showing
/// the previously loaded image (if any) until the new image provider provides a
/// different image. This is known as "gapless playback" (see also
/// [Image.gaplessPlayback]).
///
/// {@tool sample}
///
/// ```dart
/// FadeInImage(
///   // here `bytes` is a Uint8List containing the bytes for the in-memory image
///   placeholder: MemoryImage(bytes),
///   image: NetworkImage('https://backend.example.com/image.png'),
/// )
/// ```
/// {@end-tool}
class FadeInImageWithoutAuth extends StatefulWidget {
  /// Creates a widget that displays a [placeholder] while an [image] is loading
  /// then cross-fades to display the [image].
  ///
  /// The [placeholder], [image], [fadeOutDuration], [fadeOutCurve],
  /// [fadeInDuration], [fadeInCurve], [alignment], [repeat], and
  /// [matchTextDirection] arguments must not be null.
  const FadeInImageWithoutAuth({
    Key key,
    @required this.placeholder,
    @required this.image,
    this.fadeOutDuration = const Duration(milliseconds: 300),
    this.fadeOutCurve = Curves.easeOut,
    this.fadeInDuration = const Duration(milliseconds: 700),
    this.fadeInCurve = Curves.easeIn,
    this.width,
    this.height,
    this.fit,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.matchTextDirection = false,
  }) : assert(placeholder != null),
        assert(image != null),
        assert(fadeOutDuration != null),
        assert(fadeOutCurve != null),
        assert(fadeInDuration != null),
        assert(fadeInCurve != null),
        assert(alignment != null),
        assert(repeat != null),
        assert(matchTextDirection != null),
        super(key: key);

  /// Creates a widget that uses a placeholder image stored in memory while
  /// loading the final image from the network.
  ///
  /// [placeholder] contains the bytes of the in-memory image.
  ///
  /// [image] is the URL of the final image.
  ///
  /// [placeholderScale] and [imageScale] are passed to their respective
  /// [ImageProvider]s (see also [ImageInfo.scale]).
  ///
  /// The [placeholder], [image], [placeholderScale], [imageScale],
  /// [fadeOutDuration], [fadeOutCurve], [fadeInDuration], [fadeInCurve],
  /// [alignment], [repeat], and [matchTextDirection] arguments must not be
  /// null.
  ///
  /// See also:
  ///
  ///  * [new Image.memory], which has more details about loading images from
  ///    memory.
  ///  * [new Image.network], which has more details about loading images from
  ///    the network.
  FadeInImageWithoutAuth.memoryNetwork({
    Key key,
    @required Uint8List placeholder,
    @required String image,
    double placeholderScale = 1.0,
    double imageScale = 1.0,
    this.fadeOutDuration = const Duration(milliseconds: 300),
    this.fadeOutCurve = Curves.easeOut,
    this.fadeInDuration = const Duration(milliseconds: 700),
    this.fadeInCurve = Curves.easeIn,
    this.width,
    this.height,
    this.fit,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.matchTextDirection = false,
  }) : assert(placeholder != null),
        assert(image != null),
        assert(placeholderScale != null),
        assert(imageScale != null),
        assert(fadeOutDuration != null),
        assert(fadeOutCurve != null),
        assert(fadeInDuration != null),
        assert(fadeInCurve != null),
        assert(alignment != null),
        assert(repeat != null),
        assert(matchTextDirection != null),
        placeholder = MemoryImage(placeholder, scale: placeholderScale),
        image = NetworkImage(image, scale: imageScale),
        super(key: key);

  /// Creates a widget that uses a placeholder image stored in an asset bundle
  /// while loading the final image from the network.
  ///
  /// [placeholder] is the key of the image in the asset bundle.
  ///
  /// [image] is the URL of the final image.
  ///
  /// [placeholderScale] and [imageScale] are passed to their respective
  /// [ImageProvider]s (see also [ImageInfo.scale]).
  ///
  /// If [placeholderScale] is omitted or is null, the pixel-density-aware asset
  /// resolution will be attempted for the [placeholder] image. Otherwise, the
  /// exact asset specified will be used.
  ///
  /// The [placeholder], [image], [imageScale], [fadeOutDuration],
  /// [fadeOutCurve], [fadeInDuration], [fadeInCurve], [alignment], [repeat],
  /// and [matchTextDirection] arguments must not be null.
  ///
  /// See also:
  ///
  ///  * [new Image.asset], which has more details about loading images from
  ///    asset bundles.
  ///  * [new Image.network], which has more details about loading images from
  ///    the network.
  FadeInImageWithoutAuth.assetNetwork({
    Key key,
    @required String placeholder,
    @required String image,
    AssetBundle bundle,
    double placeholderScale,
    double imageScale = 1.0,
    this.fadeOutDuration = const Duration(milliseconds: 300),
    this.fadeOutCurve = Curves.easeOut,
    this.fadeInDuration = const Duration(milliseconds: 700),
    this.fadeInCurve = Curves.easeIn,
    this.width,
    this.height,
    this.fit,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.matchTextDirection = false,
  }) : assert(placeholder != null),
        assert(image != null),
        placeholder = placeholderScale != null
            ? ExactAssetImage(placeholder, bundle: bundle, scale: placeholderScale)
            : AssetImage(placeholder, bundle: bundle),
        assert(imageScale != null),
        assert(fadeOutDuration != null),
        assert(fadeOutCurve != null),
        assert(fadeInDuration != null),
        assert(fadeInCurve != null),
        assert(alignment != null),
        assert(repeat != null),
        assert(matchTextDirection != null),
        image = NetworkImageWithoutAuth(image, scale: imageScale),
        super(key: key);

  /// Image displayed while the target [image] is loading.
  final ImageProvider placeholder;

  /// The target image that is displayed.
  final ImageProvider image;

  /// The duration of the fade-out animation for the [placeholder].
  final Duration fadeOutDuration;

  /// The curve of the fade-out animation for the [placeholder].
  final Curve fadeOutCurve;

  /// The duration of the fade-in animation for the [image].
  final Duration fadeInDuration;

  /// The curve of the fade-in animation for the [image].
  final Curve fadeInCurve;

  /// If non-null, require the image to have this width.
  ///
  /// If null, the image will pick a size that best preserves its intrinsic
  /// aspect ratio. This may result in a sudden change if the size of the
  /// placeholder image does not match that of the target image. The size is
  /// also affected by the scale factor.
  final double width;

  /// If non-null, require the image to have this height.
  ///
  /// If null, the image will pick a size that best preserves its intrinsic
  /// aspect ratio. This may result in a sudden change if the size of the
  /// placeholder image does not match that of the target image. The size is
  /// also affected by the scale factor.
  final double height;

  /// How to inscribe the image into the space allocated during layout.
  ///
  /// The default varies based on the other fields. See the discussion at
  /// [paintImage].
  final BoxFit fit;

  /// How to align the image within its bounds.
  ///
  /// The alignment aligns the given position in the image to the given position
  /// in the layout bounds. For example, an [Alignment] alignment of (-1.0,
  /// -1.0) aligns the image to the top-left corner of its layout bounds, while an
  /// [Alignment] alignment of (1.0, 1.0) aligns the bottom right of the
  /// image with the bottom right corner of its layout bounds. Similarly, an
  /// alignment of (0.0, 1.0) aligns the bottom middle of the image with the
  /// middle of the bottom edge of its layout bounds.
  ///
  /// If the [alignment] is [TextDirection]-dependent (i.e. if it is a
  /// [AlignmentDirectional]), then an ambient [Directionality] widget
  /// must be in scope.
  ///
  /// Defaults to [Alignment.center].
  ///
  /// See also:
  ///
  ///  * [Alignment], a class with convenient constants typically used to
  ///    specify an [AlignmentGeometry].
  ///  * [AlignmentDirectional], like [Alignment] for specifying alignments
  ///    relative to text direction.
  final AlignmentGeometry alignment;

  /// How to paint any portions of the layout bounds not covered by the image.
  final ImageRepeat repeat;

  /// Whether to paint the image in the direction of the [TextDirection].
  ///
  /// If this is true, then in [TextDirection.ltr] contexts, the image will be
  /// drawn with its origin in the top left (the "normal" painting direction for
  /// images); and in [TextDirection.rtl] contexts, the image will be drawn with
  /// a scaling factor of -1 in the horizontal direction so that the origin is
  /// in the top right.
  ///
  /// This is occasionally used with images in right-to-left environments, for
  /// images that were designed for left-to-right locales. Be careful, when
  /// using this, to not flip images with integral shadows, text, or other
  /// effects that will look incorrect when flipped.
  ///
  /// If this is true, there must be an ambient [Directionality] widget in
  /// scope.
  final bool matchTextDirection;

  @override
  State<StatefulWidget> createState() => _FadeInImageState();
}


/// The phases a [FadeInImage] goes through.
@visibleForTesting
enum FadeInImagePhase {
  /// The initial state.
  ///
  /// We do not yet know whether the target image is ready and therefore no
  /// animation is necessary, or whether we need to use the placeholder and
  /// wait for the image to load.
  start,

  /// Waiting for the target image to load.
  waiting,

  /// Fading out previous image.
  fadeOut,

  /// Fading in new image.
  fadeIn,

  /// Fade-in complete.
  completed,
}

typedef _ImageProviderResolverListener = void Function();

class _ImageProviderResolver {
  _ImageProviderResolver({
    @required this.state,
    @required this.listener,
    this.imageStreamListener
  });

  final _FadeInImageState state;
  final _ImageProviderResolverListener listener;
  final ImageStreamListener imageStreamListener;

  FadeInImageWithoutAuth get widget => state.widget;

  ImageStream _imageStream;
  ImageInfo _imageInfo;

  void resolve(ImageProvider provider) {
    final ImageStream oldImageStream = _imageStream;
    final ImageStreamListener listener = ImageStreamListener(_handleImageChanged);
    _imageStream = provider.resolve(createLocalImageConfiguration(
        state.context,
        size: widget.width != null && widget.height != null ? Size(widget.width, widget.height) : null
    ));
    assert(_imageStream != null);

    if (_imageStream.key != oldImageStream?.key) {
      oldImageStream?.removeListener(listener);
      _imageStream.addListener(listener);
    }
  }

  void _handleImageChanged(ImageInfo imageInfo, bool synchronousCall) {
    _imageInfo = imageInfo;
    listener();
  }

  void stopListening() {
    _imageStream?.removeListener(imageStreamListener);
  }
}

class _FadeInImageState extends State<FadeInImageWithoutAuth> with TickerProviderStateMixin {
  _ImageProviderResolver _imageResolver;
  _ImageProviderResolver _placeholderResolver;

  AnimationController _controller;
  Animation<double> _animation;

  FadeInImagePhase _phase = FadeInImagePhase.start;
  FadeInImagePhase get phase => _phase;

  @override
  void initState() {
    _imageResolver = _ImageProviderResolver(state: this, listener: _updatePhase);
    _placeholderResolver = _ImageProviderResolver(state: this, listener: () {
      setState(() {
        // Trigger rebuild to display the placeholder image
      });
    });
    _controller = AnimationController(
      value: 1.0,
      vsync: this,
    );
    _controller.addListener(() {
      setState(() {
        // Trigger rebuild to update opacity value.
      });
    });
    _controller.addStatusListener((AnimationStatus status) {
      _updatePhase();
    });
    super.initState();
  }

  @override
  void didChangeDependencies() {
    _resolveImage();
    super.didChangeDependencies();
  }

  @override
  void didUpdateWidget(FadeInImageWithoutAuth oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.image != oldWidget.image || widget.placeholder != oldWidget.placeholder)
      _resolveImage();
  }

  @override
  void reassemble() {
    _resolveImage(); // in case the image cache was flushed
    super.reassemble();
  }

  void _resolveImage() {
    _imageResolver.resolve(widget.image);

    // No need to resolve the placeholder if we are past the placeholder stage.
    if (_isShowingPlaceholder)
      _placeholderResolver.resolve(widget.placeholder);

    if (_phase == FadeInImagePhase.start)
      _updatePhase();
  }

  void _updatePhase() {
    if(!mounted){
      return;
    }
    setState(() {
      switch (_phase) {
        case FadeInImagePhase.start:
          if (_imageResolver._imageInfo != null)
            _phase = FadeInImagePhase.completed;
          else
            _phase = FadeInImagePhase.waiting;
          break;
        case FadeInImagePhase.waiting:
          if (_imageResolver._imageInfo != null) {
            // Received image data. Begin placeholder fade-out.
            _controller.duration = widget.fadeOutDuration;
            _animation = CurvedAnimation(
              parent: _controller,
              curve: widget.fadeOutCurve,
            );
            _phase = FadeInImagePhase.fadeOut;
            _controller.reverse(from: 1.0);
          }
          break;
        case FadeInImagePhase.fadeOut:
          if (_controller.status == AnimationStatus.dismissed) {
            // Done fading out placeholder. Begin target image fade-in.
            _controller.duration = widget.fadeInDuration;
            _animation = CurvedAnimation(
              parent: _controller,
              curve: widget.fadeInCurve,
            );
            _phase = FadeInImagePhase.fadeIn;
            _placeholderResolver.stopListening();
            _controller.forward(from: 0.0);
          }
          break;
        case FadeInImagePhase.fadeIn:
          if (_controller.status == AnimationStatus.completed) {
            // Done finding in new image.
            _phase = FadeInImagePhase.completed;
          }
          break;
        case FadeInImagePhase.completed:
        // Nothing to do.
          break;
      }
    });
  }

  @override
  void dispose() {
    _imageResolver.stopListening();
    _placeholderResolver.stopListening();
    _controller.dispose();
    super.dispose();
  }

  bool get _isShowingPlaceholder {
    assert(_phase != null);
    switch (_phase) {
      case FadeInImagePhase.start:
      case FadeInImagePhase.waiting:
      case FadeInImagePhase.fadeOut:
        return true;
      case FadeInImagePhase.fadeIn:
      case FadeInImagePhase.completed:
        return false;
    }

    return null;
  }

  ImageInfo get _imageInfo {
    return _isShowingPlaceholder
        ? _placeholderResolver._imageInfo
        : _imageResolver._imageInfo;
  }

  @override
  Widget build(BuildContext context) {
    assert(_phase != FadeInImagePhase.start);
    final ImageInfo imageInfo = _imageInfo;
    return RawImage(
      image: imageInfo?.image,
      width: widget.width,
      height: widget.height,
      scale: imageInfo?.scale ?? 1.0,
      color: Color.fromRGBO(255, 255, 255, _animation?.value ?? 1.0),
      colorBlendMode: BlendMode.modulate,
      fit: widget.fit,
      alignment: widget.alignment,
      repeat: widget.repeat,
      matchTextDirection: widget.matchTextDirection,
    );
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
    super.debugFillProperties(description);
    description.add(EnumProperty<FadeInImagePhase>('phase', _phase));
    description.add(DiagnosticsProperty<ImageInfo>('pixels', _imageInfo));
    description.add(DiagnosticsProperty<ImageStream>('image stream', _imageResolver._imageStream));
    description.add(DiagnosticsProperty<ImageStream>('placeholder stream', _placeholderResolver._imageStream));
  }
}

在项目中导包,注意导包不要错了

自带占位符加载,记得导包别错了,别用源码的
FadeInImageWithoutAuth.assetNetwork(
            placeholder: '占位图片',
            image:‘加载路径’,
            fit: BoxFit.fill,
          )
分享到:
评论

相关推荐

    【Flutter】Image 组件 ( 加载网络图片 加载静态图片 加载本地图片 path_provider 插件 ).zip

    【Flutter】Image 组件 ( 加载网络图片 | 加载静态图片 | 加载本地图片 | path_provider 插件 ) https://hanshuliang.blog.csdn.net/article/details/115112899 博客源码快照

    flutter_inappwebview-master_flutter_WebView.zip

    `flutter_inappwebview-master_flutter_WebView.zip`这个压缩包文件就包含了 Flutter 应用中常用的 `InAppWebView` 插件的相关源码和资源,它为开发者提供了在应用内加载和操作Web页面的强大功能。 `InAppWebView` ...

    flutter版防微信聊天

    3. 热重加载:Flutter的热重载功能有助于快速预览和调试界面更改。 4. 异步操作:充分利用Dart的async/await进行异步处理,避免阻塞主线程。 五、测试与发布 1. 单元测试:使用test库编写单元测试,确保代码质量。 ...

    super_enum:Flutter 2.0 https的错误修复

    将常规的whenX方法与异步回调函数一起使用,而不要使用它们 asyncWhen &gt; when asyncWhenOrElse &gt; whenOrElse 从v0.3.0迁移到v0.4.0 DataField签名已更改。 DataField(String,Type)应替换为DataField(String) ...

    flutter 常用插件整理附加使用实例

    3. **图片加载:image_picker** `image_picker`插件允许用户从相册选择图片或使用相机拍摄。以下是如何使用它的示例: ```dart import 'package:image_picker/image_picker.dart'; Future&lt;void&gt; selectImage() ...

    flutter_app.rar

    Dio是Flutter社区广泛使用的第三方网络请求库,它支持HTTP和HTTPS协议,提供了丰富的功能,如GET、POST、PUT等请求方法,文件上传下载,拦截器,超时处理,自定义请求头等。在项目中,Dio可能被用来实现API接口调用...

    Flutter学习,简单demo应用,网络请求,list列表下拉刷新,上拉加载。

    `cached_network_image` 提供了缓存网络图片的功能,避免每次打开应用时重新加载图片。 ```dart import 'package:cached_network_image/cached_network_image.dart'; // 在你的 widget 中 CachedNetworkImage( ...

    Flutter 完整开发实战详解系列

    这一章节将详细介绍Flutter中图片加载的过程,包括缓存策略、异步加载机制等,以提高应用性能。 #### 十一、全面深入了解Stream Stream是Dart语言中用于处理异步数据流的一种强大工具。这一部分将详细介绍Stream的...

    flutter_animated:动画中的动画图像(gifapng)支持

    flutter_animated Flutter已支持Animaged GIF。 您可能不再需要此插件。 动画图像(GIF / APNG / WebP)支持抖动。 该插件正在建设中,缺乏基本功能。 用法 要求它 在pubspec.yaml : dependencies : flutter ...

    flutter_user_profile_avatar:一个简单的小部件,它显示圆形的个人档案图片,该图片是从网络中获取的,并在加载图像时显示循环进度指示器。 另外,还可以显示通知气泡

    Flutter用户个人资料头像一个简单的小部件,可显示圆形的个人资料图片,从网络中获取图片,并在加载图像时显示圆形的进度指示器。 另外,还可以显示通知气泡。如何使用UserProfileAvatar ( avatarUrl : '...

    移动端:手把手带你入门跨平台UI开发框架Flutter,看完这篇-flutter框架

    - **热重载**: Flutter支持热重载功能,可以在几秒钟内重新加载代码更改,显著加快了开发迭代速度。 - **丰富的组件库**: Flutter提供了大量的预构建组件,使得开发者能够快速构建美观的应用界面。 ##### 4.3 性能...

    flutter.dev-Flutter-Web-Clone:Flutter 官网的克隆 https

    重新加载live link ,以防几张图片无法加载 :memo: 笔记对于开场动画。 目前只有一种动画设计。 将与他人合作并尽快添加他们我已经使用包将页面与原始主页中的其他链接链接起来考虑到Try flutter in your browser的...

    Flutter实战1

    - 当前主流的移动开发平台有iOS(使用Swift或Objective-C)、Android(使用Java或Kotlin)以及跨平台解决方案(如Flutter、React Native等)。 2. **跨平台框架的优势**: - 跨平台框架允许开发者使用单一代码库...

    一个FlutterCarousel控件

    在实际项目中,你可能需要处理更复杂的逻辑,例如加载网络图片、添加过渡动画、嵌套其他Widget等。`carousel_pro`库虽然强大,但也有其局限性,对于更复杂的需求,可能需要结合其他库或者自定义Widget来实现。 在...

    Android 毕业设计仿斗鱼 Flutter 设计(内附源码,下载即可)

    4. 尽可能接入更多功能,方法附带注释,帮助你在使用flutter进行开发新的应用提供实用的借鉴案例 包含功能: - 启动页广告位 - 开播列表上拉加载、下拉刷新、返回顶部 - 列表图片缓存加载优化 - 渐进式头部动画 - ...

    从相册、拍照、比例压缩、上传

    关于图片上传,一般会涉及到HTTP或HTTPS请求。在iOS中,可以使用`NSURLSession`或者`Alamofire`库来发送POST请求,将压缩后的图片数据作为二进制数据附在请求体中。Android则可以使用`HttpURLConnection`或`Volley`...

    一个flutter练习项目

    https://github.com/iotjin/jh_flutter_demo实现的一些效果UI相关ListView相关(上下拉刷新、分组上下拉刷新、分组吸顶)GridView相关弹框封装(中间、底部、toast、自定义弹框)仿微信右上角弹框时间、日期、单列、多列...

    APOD:Flutter Web应用程序显示每日星象图片(APOD)及其详细信息

    在本文中,我们将深入探讨如何使用Flutter框架和Dart编程语言构建一个名为“APOD”的Web应用程序,该程序能够展示每日星象图片(APOD,Astronomy Picture of the Day)及其相关的详细信息。首先,我们需要理解...

    SDWebImage

    1. **异步加载图片** SDWebImage的核心功能是异步下载并缓存网络图片,这意味着在UI线程之外进行图片加载,不会阻塞用户界面,提供了流畅的滚动体验。它支持自动缓存,当图片再次请求时,可以从本地缓存中快速获取...

    高仿微信朋友圈

    2. **图片加载优化**:朋友圈中的图片数量可能较多,因此需要考虑图片加载的性能优化。可以采用第三方库,如Android的Glide或Picasso,iOS的Kingfisher,这些库支持图片缓存,能减少网络请求,提高用户体验。 3. **...

Global site tag (gtag.js) - Google Analytics