在 flutter 中播放 gif 错误

问题描述 投票:0回答:1

在我的 flutter 应用程序中,我有一个屏幕显示带有 gif 的练习名称,列表太长,当我将 gif 添加到列表中时,gif 没有按预期播放,gif 只有 2 秒,当第一个 gif 时播放第一秒,它停止并等待,直到列表中的所有其他 gif 播放第一秒,当所有 gif 播放第一秒时,然后返回到第一个 gif 并播放第二个(第二个),并以这种方式重播 gif ,我该如何解决这个问题?

我使用了cached_network_images和Image.memory和Image.file,它们都有保存问题

列表视图代码:

ListView.builder(
                              physics: const NeverScrollableScrollPhysics(),
                              shrinkWrap: true,
                              itemCount: exercises.length,
                              itemBuilder:
                                  (BuildContext context, int index) =>
                                      Padding(
                                padding: const EdgeInsets.only(bottom: 10),
                                child: Column(
                                  children: [
                                    Container(
                                      width: double.infinity,
                                      padding: const EdgeInsets.symmetric(
                                        horizontal: 20,
                                        vertical: 20,
                                      ),
                                      decoration: BoxDecoration(
                                        color: theme.colorScheme.background,
                                        border: Border.all(
                                          width: 3,
                                          color: theme.colorScheme
                                              .tertiaryContainer,
                                        ),
                                        borderRadius:
                                            BorderRadius.circular(35),
                                      ),
                                      child: ListTile(
                                        minVerticalPadding: 0,
                                        visualDensity: const VisualDensity(
                                          vertical: 4,
                                        ),
                                        title: Row(
                                          children: [
                                            SizedBox(
                                              width: width * .1,
                                              height: width * .1,


//......................................Display gifs here.................................


                                              child: ImageLoader(
                                                imageUrl: '$baseUrl${exercises[index]['gif']}'
                                              ),
                                            ),
                                            SizedBox(width: width * .015),
                                            Column(
                                              crossAxisAlignment:
                                                  CrossAxisAlignment.start,
                                              children: [
                                                SizedBox(
                                                  width: width * .5,
                                                  child: BigText(
                                                    text: Functions()
                                                        .getAvailableData(
                                                      lang: lang,
                                                      data:
                                                          exercises[index],
                                                      type: TranslationTypes
                                                          .name,
                                                    ),
                                                    color: theme.cardColor,
                                                    fontSize: width * .026,
                                                    maxLines: 2,
                                                    height: 1.75,
                                                    textOverflow:
                                                        TextOverflow
                                                            .visible,
                                                  ),
                                                ),
                                                SizedBox(
                                                  height: width * .015,
                                                ),
                                                exercises[index]
                                                            ['muscle'] ==
                                                        null
                                                    ? const SizedBox()
                                                    : Container(
                                                        height:
                                                            height * .03,
                                                        alignment: Alignment
                                                            .center,
                                                        padding:
                                                            const EdgeInsets
                                                                .symmetric(
                                                          horizontal: 20,
                                                          vertical: 5,
                                                        ),
                                                        decoration:
                                                            BoxDecoration(
                                                          borderRadius:
                                                              BorderRadius
                                                                  .circular(
                                                                      1000),
                                                          color: const Color(
                                                                  0xFF86EE75)
                                                              .withOpacity(
                                                                  .15),
                                                        ),
                                                        child: BigText(
                                                          text: Functions()
                                                              .getAvailableData(
                                                            lang: lang,
                                                            data: exercises[
                                                                    index]
                                                                ['muscle'],
                                                            type:
                                                                TranslationTypes
                                                                    .name,
                                                          ),
                                                          color: theme
                                                              .colorScheme
                                                              .outline,
                                                          fontSize:
                                                              width * .018,
                                                        ),
                                                      ),
                                              ],
                                            ),
                                          ],
                                        ),
                                        trailing: Material(
                                          borderRadius:
                                              BorderRadius.circular(10000),
                                          color:
                                              theme.colorScheme.background,
                                          child: InkWell(
                                            onTap: () {
                                              addAndRemoveFromExercises(
                                                  index);
                                            },
                                            borderRadius:
                                                BorderRadius.circular(1000),
                                            child: Container(
                                              width: width * .065,
                                              height: width * .065,
                                              padding: EdgeInsets.all(
                                                width * .020,
                                              ),
                                              decoration: BoxDecoration(
                                                borderRadius:
                                                    BorderRadius.circular(
                                                        10000),
                                                border: Border.all(
                                                  width: 3,
                                                  color: theme.colorScheme
                                                      .tertiaryContainer,
                                                ),
                                              ),
                                              child: selectedIds.contains(
                                                          exercises[index]
                                                              ['id']) ==
                                                      true
                                                  ? SvgPicture.asset(
                                                      'assets/icons/check.svg',
                                                      color:
                                                          theme.cardColor,
                                                      width: 25,
                                                      height: 25,
                                                    )
                                                  : const SizedBox(),
                                            ),
                                          ),
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ),

ImageLoader代码:

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'spinkit.dart';

class ImageLoader extends StatelessWidget {
  const ImageLoader({
    Key? key,
    required this.imageUrl,
    this.borderRadius,
    this.errorHeight,
    this.errorWidth,
    this.fit,
    this.color,
    this.id,
    this.width,
    this.height,
  }) : super(key: key);

  final String imageUrl;
  final BorderRadius? borderRadius;
  final double? errorHeight, errorWidth, width, height;
  final BoxFit? fit;
  final String? id;
  final Color? color;

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: borderRadius ?? BorderRadius.circular(10),
      child: CachedNetworkImage(
        fit: fit ?? BoxFit.fill,
        height: height,
        width: width,
        color: color,
        cacheKey: id,
        imageUrl: imageUrl,
        errorWidget: (context, url, exc) {
          return Center(
            child: Icon(
              Icons.error,
              color: Colors.red.withOpacity(0.7),
              size: 30,
            ),
          );
        },
        placeholder: (context, url) {
          return const Spinkit();
        },
      ),
    );
  }
}

当所有GIF都相同时没有问题,只有当GIF不同时才会出现问题

flutter image gif
1个回答
0
投票

这里有几种解决这个问题的方法:

预加载图像:您可以考虑预加载它们,而不是仅在 GIF 进入视图时加载它们。这可能会占用大量资源,并且不建议将其用于包含许多 GIF 的长列表,但如果您的列表易于管理,则这可以确保所有 GIF 均已完全加载并准备好播放。您可以为此使用 precacheImage 函数。

使用专用的 GIF 库:不要使用标准的图像显示小部件,而是考虑使用专用于更好地处理 GIF 的包,例如 flutter_gifimage。这些库通常可以更好地控制 GIF 动画,并可能以避免当前问题的方式处理渲染。

自定义滚动物理:为 ListView.builder 实现自定义滚动物理,减少或消除 GIF 的离屏优化。这是一种更高级的解决方案,可能会导致性能问题,但它允许您保持 GIF 运行,即使它们不在直接视口中也是如此。

优化和缩小尺寸:确保您的 GIF 已优化且不会太大。 GIF 越大、越复杂,Flutter 就越难在列表中管理它们。降低帧速率或尺寸可能会有所帮助。

替代动画格式:考虑动画是否需要是 GIF。在某些情况下,将 GIF 转换为 MP4 等视频格式并使用视频播放器(如 flutter_video_player)可能会更有效。这是因为视频格式通常可以更好地优化播放,并且可以比 GIF 更有效地暂停和恢复。

一次显示一个 GIF:修改设计以一次仅显示一个动画 GIF,而其他 GIF 则暂停或替换为静态图像,直到用户与它们交互。这大大减少了渲染引擎的负载。

自定义 GIF 播放器:实现自定义 GIF 播放器,可以更好地处理列表中 GIF 的生命周期和播放。这可能涉及根据 GIF 在视口中的可见性对 GIF 何时开始和停止进行更详细的控制。

状态管理:确保应用程序的状态管理不会导致小部件不必要的重建,这可能会重置 GIF 动画。使用 Provider 或 Bloc 等工具有效管理状态,而不会导致不需要的重建。

© www.soinside.com 2019 - 2024. All rights reserved.