美文网首页
Flutter仿Boss-6.底部tab切换

Flutter仿Boss-6.底部tab切换

作者: 一笑轮回吧 | 来源:发表于2024-04-08 22:21 被阅读0次

效果

boss_tab.gif

实现

  • 图片资源采用boss包中的动画webp资源。
  • Flutter采用Image加载webp动画。

遇到的问题

问题:Flutter加载webp再次加载无法再次播放动画问题

看如下代码:

Image.asset(
     'assets/images/xxx.webp',
     width: 40.w,
     height: 30.w,
)

运行的效果:

屏幕录制2024-04-09 22.14.41.gif

直接采用上面代码加载webp动画图片的时候,发现首次加载是没有问题的,当切换其他tab再次切换回来的时候,虽然我重新setState了,但是图片不会重新动画加载出来。开始觉得很奇怪,Image都重新创建了,为啥动画不重新执行呢?心想难道有缓存,想当然就给Image定义了key,每次点击按钮给Image设置不同的key,运行发现还是不行,到这一步只好谷歌大法了,看到了很多人遇到这个问题,但是没有给出解决的答案,看来只能源码大法了。

源码走起~~这里省略...

然后发现Image中有内存缓存ImageCache,翻看了源码后发现了解决方案,因为这里我不需要内存缓存,而且这个缓存与Image中的bundle有关系,只要每次创建Image设置不同的bundle就OK了,所以我就把代码尝试修改了下。

Image.asset(
      'assets/images/xxx.webp',
      bundle: PlatformAssetBundle(),
      width: 40.w,
      height: 30.w,
)

再运行下效果:


boss_tab.gif

完整源码

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_project/res/colors/color_res.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

/// BottomBarItem
class BottomBarItem extends StatefulWidget {
  // Tab 名字
  final String tabName;

  // Tab 图标
  final String tabIcon;

  // Tab 选中图标
  final String tabSelectedIcon;

  // 默认颜色
  final Color tabTextColor;

  // 选中颜色
  final Color tabTextSelectedColor;

  // Tab对应索引
  final int tabIndex;

  // 点击回调
  final Function(int) onTap;

  // 是否选中
  final bool isChecked;

  // 角标
  final int badger;

  const BottomBarItem({
    Key? key,
    required this.tabName,
    required this.tabIcon,
    required this.tabSelectedIcon,
    required this.onTap,
    required this.tabIndex,
    this.tabTextColor = Colors.grey,
    this.tabTextSelectedColor = RC.themeColor,
    this.isChecked = false,
    this.badger = 0,
  }) : super(key: key);

  @override
  State<BottomBarItem> createState() => _BottomBarItemState();
}

class _BottomBarItemState extends State<BottomBarItem> {
  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: Stack(
        children: [
          Positioned(
            child: Container(
              alignment: Alignment.center,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  widget.isChecked
                      ? Image.asset(
                          widget.tabSelectedIcon,
                          bundle: PlatformAssetBundle(),
                          width: 40.w,
                          height: 30.w,
                        )
                      : Image.asset(
                          widget.tabIcon,
                          width: 40.w,
                          height: 30.w,
                        ),
                  Text(
                    widget.tabName,
                    style: TextStyle(
                      color: widget.isChecked
                          ? widget.tabTextSelectedColor
                          : widget.tabTextColor,
                      fontSize: 10.sp,
                    ),
                  ),
                ],
              ),
            ),
          ),
          Visibility(
            visible: widget.badger > 0,
            child: Positioned(
              right: 30.w,
              top: 10.w,
              child: ClipOval(
                child: Container(
                  alignment: Alignment.center,
                  color: Colors.red,
                  width: 8,
                  height: 8,
                ),
              ),
            ),
          )
        ],
      ),
      onTap: () {
        widget.onTap(widget.tabIndex);
        setState(() {});
      },
    );
  }
}

具体详情:github.com/yixiaolunhui/flutter_project

相关文章

网友评论

      本文标题:Flutter仿Boss-6.底部tab切换

      本文链接:https://www.haomeiwen.com/subject/pgxatjtx.html