Flutter控件之图片Image封装

news2024/9/21 18:41:46

Flutter控件之基类Widget封装

Flutter控件之文本Text封装

为什么要进行繁琐的封装?直接用也挺好啊,这个回答一点毛病没有,大部分视图都可以原生绘制,可在Flutter中偏偏原生的控件,少了很多需要又常用的属性,比如宽高,比如内外边距,又比如点击事件,如果不采取封装,视图的结构会一层嵌套一层,徒增很多的冗余代码,所以,为了简洁代码,还有为了拓展原生组件没有的属性,就不得不进行一次简单的封装,使其在调用的时候,可以很方便的实现某些功能。

本来只打算封一个Widget的基类就算了,但是想到很多的基础组件其实也需要进行拓展一些属性,那么索性就一一封一下吧,既是学习,也是积累,本篇文章就简单的针对图片Image做一个封装,此Image也是基于第一篇的BaseWidget,不熟悉的可以看下第一篇的文章。

还是按照惯例,简单的罗列下基本的大纲:

1、实际的效果一览

2、Image相关属性分析

3、源码和具体使用

4、相关总结

一、实际的效果一览

效果呢,很是简单,就是一些平时的功能,比如圆角,圆形,设置占位图等等。

二、Image相关属性分析

自定义Image继承了父类的一些属性,比如宽高,内外边距,点击事件等,当然了,也增加了自己独有的一些属性,比如圆角,圆形,占位图等,具体的父类属性就不过多介绍了,看第一篇文章即可,简单的列举下Image的相关属性。

属性

类型

概述

placeholderImage

String

占位图(仅支持assets)

errorImage

String

错误图(仅支持assets)

imagePath

String

图片地址(支持网络/assets/File)

imageBoxFit

BoxFit

图片拉伸方式

fill:Box被完全填充,相当于ScaleType的FIT_XY。

contain:保持Box的纵横比至至少有一边填充满父控件,相当于ScaleType的FIT_CENTER。

cover:保持Box的纵横比进行缩放至Box完全填充满父控件,超出部分进行裁剪,相当于ScaleType的CENTER_CROP。

fitWidth:缩放Box宽直至填充满父控件。

fitHeight:缩放Box高直至填充满父控件。

none:不进行任何缩放操作。

scaleDown:Box大于父控件,则采用与contain一致的缩放模式,否则采用none缩放模式。

imageLoadType

int

图片加载类型

isClipOval

bool

是否是圆形

imageRadius

double

设置图片圆角

三、源码和具体使用

源码就比较过分的简单了,一是继承原有的BaseWidget属性,二是拓展自己的相关属性,占位图,错误图,是否圆形,设置圆角等,具体的源码如下:

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

import '../../base/base_widget.dart';

///AUTHOR:AbnerMing
///DATE:2023/5/20
///INTRODUCE:图片控件

class VipImage extends BaseWidget {
  final String? placeholderImage; //占位图
  final String? errorImage; //错误图
  final String? imagePath; //图片地址
  final BoxFit? imageBoxFit; //图片拉伸方式
  final int? imageLoadType; //图片加载类型
  final bool? isClipOval; //是否是圆形
  final double? imageRadius; //设置图片圆角
  const VipImage(this.imagePath,
      {super.key,
      this.placeholderImage,
      this.errorImage,
      this.imageBoxFit,
      this.imageLoadType,
      this.isClipOval,
      this.imageRadius,
      super.width,
      super.height,
      super.margin,
      super.marginLeft,
      super.marginTop,
      super.marginRight,
      super.marginBottom,
      super.padding,
      super.paddingLeft,
      super.paddingTop,
      super.paddingRight,
      super.paddingBottom,
      super.backgroundColor,
      super.strokeWidth,
      super.strokeColor,
      super.solidColor,
      super.radius,
      super.isCircle,
      super.leftTopRadius,
      super.rightTopRadius,
      super.leftBottomRadius,
      super.rightBottomRadius,
      super.childWidget,
      super.alignment,
      super.gradient,
      super.gradientBegin,
      super.gradientEnd,
      super.gradientColorList,
      super.gradientColorStops,
      super.onClick,
      super.onDoubleClick,
      super.onLongPress});

  @override
  Widget getWidget(BuildContext context) {
    //不需要占位图
    if (placeholderImage == null) {
      return getEndWidget(getImage());
    } else {
      return getEndWidget(getFadeInImage());
    }
  }

  /*
  * 返回最终的Widget
  * */
  Widget getEndWidget(widget) {
    //设置图片为圆形
    if (isClipOval == true) {
      return ClipOval(child: widget);
    }
    //设置图片圆角
    if (imageRadius != null) {
      return ClipRRect(
          borderRadius: BorderRadius.circular(imageRadius!), child: widget);
    }
    return widget;
  }

  /*
  * 有无占位图组件
  * */
  Widget getFadeInImage() {
    return FadeInImage(
        fit: imageBoxFit ?? BoxFit.contain,
        placeholderFit: imageBoxFit ?? BoxFit.contain,
        placeholder: getPlaceholder(),
        image: getImageProvider(),
        placeholderErrorBuilder: (ctx, err, stackTrace) => _imagePlaceholder(),
        imageErrorBuilder: (ctx, err, stackTrace) => _imageError());
  }

  /*
  * 无占位图组件
  * */
  Widget getImage() {
    return Image(
        image: getImageProvider(),
        fit: imageBoxFit ?? BoxFit.contain,
        errorBuilder: (ctx, err, stackTrace) => _imageError());
  }

  /*
  * 占位图错误组件
  * */
  Widget _imagePlaceholder() {
    return Image.asset("", fit: imageBoxFit ?? BoxFit.contain);
  }

  /*
  * 错误组件
  * */
  Widget _imageError() {
    var imagePath = "";
    if (errorImage != null) {
      imagePath = errorImage!;
    }
    return Image.asset(imagePath, fit: imageBoxFit ?? BoxFit.contain);
  }

  /*
  * 判断图片是网络还是本地还是应用内
  * */
  ImageProvider getImageProvider() {
    if (imageLoadType == null) {
      return NetworkImage(imagePath!);
    } else if (imageLoadType == 0) {
      return FileImage(File(imagePath!));
    } else {
      return AssetImage(imagePath!);
    }
  }

  /*
  * 占位图
  * */
  ImageProvider getPlaceholder() {
    return AssetImage(placeholderImage!);
  }
}

简单使用

 VipImage("https://www.vipandroid.cn/ming/image/gan.png")

具体案例(对应第一条的效果图)

这个案例中结合了之前封装的VipText控件,大家可以直接看那篇文章即可,当然你可以删除,本身它就是一个文本Text控件,用来做个描述信息。

import 'package:flutter/material.dart';

import '../../constants/dimen_constant.dart';
import '../../constants/image_constant.dart';
import '../widget/vip_image.dart';
import '../widget/vip_text.dart';

///AUTHOR:AbnerMing
///DATE:2023/5/20
///INTRODUCE:Image组件效果页面

class ImagePage extends StatefulWidget {
  const ImagePage({super.key});

  @override
  State<ImagePage> createState() => _ImagePageState();
}

class _ImagePageState extends State<ImagePage> {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      padding: const EdgeInsets.only(
          left: DimenConstant.dimen_10, right: DimenConstant.dimen_10),
      child: SingleChildScrollView(
          child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: const [
            VipImage(
              "https://www.vipandroid.cn/ming/image/gan.png",
              marginTop: DimenConstant.dimen_10,
            ),
            VipText("(普通加载)", marginTop: DimenConstant.dimen_5),
            VipImage(
              "https://www.vipandroid.cn/ming/image/gan.png",
              marginTop: DimenConstant.dimen_10,
              width: 80,
              height: 80,
            ),
            VipText("(设置宽高)", marginTop: DimenConstant.dimen_5),
            VipImage(
              "https://www.vipandroid.cn/ming/image/gan.png",
              marginTop: DimenConstant.dimen_10,
              imageBoxFit: BoxFit.fill,
              width: 80,
              height: 80,
            ),
            VipText("(设置宽高拉伸充满)", marginTop: DimenConstant.dimen_5),
            VipImage(
              "https://www.vipandroid.cn/ming/image/gan.png",
              marginTop: DimenConstant.dimen_10,
              imageBoxFit: BoxFit.cover,
              width: 80,
              height: 80,
            ),
            VipText("(设置宽高居中裁切)", marginTop: DimenConstant.dimen_5),
            VipImage(
              "https://www.vipandroid.cn/ming/image/gan.png",
              marginTop: DimenConstant.dimen_10,
              imageBoxFit: BoxFit.cover,
              placeholderImage: ImageConstant.imageDefault,
              width: 80,
              height: 80,
            ),
            VipText("(设置占位图)", marginTop: DimenConstant.dimen_5),
            VipImage(
              "https://www.vipandroid.cn/ming/image/gan.png",
              marginTop: DimenConstant.dimen_10,
              imageBoxFit: BoxFit.cover,
              isClipOval: true,
              width: 80,
              height: 80,
            ),
            VipText("(设置圆形)", marginTop: DimenConstant.dimen_5),
            VipImage(
              "https://www.vipandroid.cn/ming/image/gan.png",
              marginTop: DimenConstant.dimen_10,
              imageBoxFit: BoxFit.cover,
              imageRadius: DimenConstant.dimen_10,
              placeholderImage: ImageConstant.imageDefault,
              width: 80,
              height: 80,
            ),
            VipText("(设置圆角)", marginTop: DimenConstant.dimen_5),
          ])),
    );
  }
}

DimenConstant

把相关尺寸抽成了一个常量类了,目的便于管理,大家不想用直接代码写值也行。

///AUTHOR:AbnerMing
///DATE:2023/5/15
///INTRODUCE:尺寸常量

class DimenConstant {
  static const double dimen_5 = 5;
  static const double dimen_10 = 10;
  static const double dimen_15 = 15;
  static const double dimen_22 = 22;
  static const double dimen_44 = 44;
}

ImageConstant

图片常量类,用来存储一些assets下的图片地址,便于管理。

///AUTHOR:AbnerMing
///DATE:2023/5/15
///INTRODUCE:图片地址常量

class ImageConstant {
  static const String imageDefault = "images/vip_ic_image_default.png";
}

四、相关总结

在项目开发的时候,关于一些常量信息,比如尺寸的大小,本地的图片地址,请求的接口地址等等,我们一般不要直接在页面中写死,一是不方便管理,二是后期一旦改动,就需要查找每个文件,非常的浪费时间,所以,尽量抽取到一个地方,类似Android中的,strings.xml,dimens.xml,colors.xml这些文件,好了铁子们,本篇文章就先到这里,希望可以帮助大家。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/547670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最小生成树—Kruskal算法和Prim算法

1.最小生成树 连通图&#xff1a;在无向图中&#xff0c;若从顶点v1到顶点v2有路径&#xff0c;则称顶点v1与顶点v2是连通的。如果图中任 意一对顶点都是连通的&#xff0c;则称此图为连通图。 生成树&#xff1a;一个连通图的最小连通子图称作该图的生成树。有n个顶点的连通…

Java基础-面向对象总结(3)

本篇文章主要讲解Java面向对象的知识点 面向对象的三大特性类的扩展(抽象类,接口,内部类,枚举) 目录 面向对象和面向过程的区别? 面向对象的五大基本原则 面向对象三大特性 继承 怎么理解继承 ? 继承和聚合的区别&#xff1f; 封装 多态 什么是多态 什么是运行时多…

面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生

测试员可以先在大厂镀金&#xff0c;以后去中小厂毫无压力&#xff0c;基本不会被卡&#xff0c;事实果真如此吗&#xff1f;但是在我身上却是给了我很大一巴掌... 所谓大厂镀金只是不卡简历而已&#xff0c;如果面试答得稀烂&#xff0c;人家根本不会要你。况且要不是大厂出来…

MySQL数据库基础4-内置函数

文章目录 日期函数字符串函数数学函数其他函数 日期函数 函数名称描述current date()当前日期current time()当前时间current timestamp()当前时间戳date(datetime)返回datetime参数的日期部分date add(date, interval d_value type)在date中添加日期或时间&#xff0c;interv…

GitHub Actions Error “Waiting for a runner to pick up this job”

GitHub Actions Error “Waiting for a runner to pick up this job” 什么是GitHub Actions GitHub Actions 是一个 CI/CD&#xff08;持续集成和持续部署&#xff09;平台&#xff0c;可以让您自动化工作流程并与 GitHub 存储库中的代码集成。使用 GitHub Actions&#xff…

智能排班系统 【数据库设计】

文章目录 数据库设计规范ER图物理模型数据表登录日志表操作日志表菜单表角色表企业表门店表省市区表门店节日表消息表职位表排班规则表排班任务表排班结果存储scheduling_date排班日表scheduling_shift排班班次表shift_user班次员工中间表 定时通知表用户表中间表role_menu角色…

适合小白的网络安全书籍推荐

学习的方法有很多种&#xff0c;看书就是一种不错的方法&#xff0c;但为什么总有人说&#xff1a;“看书是学不会技术的”。 其实就是书籍没选对&#xff0c;看的书不好&#xff0c;你学不下去是很正常的。 一本好书其实不亚于一套好的视频教程&#xff0c;尤其是经典的好书…

MATLAB系列(2)——plot画图函数

一、plot plot画的是折线图。plot可以画出多种线类型的图&#xff0c;比如实线、虚线、星线、圆圈线等,一个图里可以画多条折线&#xff0c;方便对比。 1.1 设置坐标轴标签 和 图名 使用xlabel 和ylabel&#xff0c;title设置图名&#xff0c;fontsize设置名字字体大小 1.2 …

Netty核心技术三--NIO编程

1. JAVA NIO基本介绍 Java NIO 全称 java non-blocking IO&#xff0c;是指 JDK 提供的新API。从 JDK1.4 开始&#xff0c;Java 提供了一系列改进的输入/输出的新特性&#xff0c;被统称为 NIO(即 New IO)&#xff0c;是同步非阻塞的 NIO 相关类都被放在 java.nio 包及子包下&…

【软件测试基础】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 1、什么是软件测试(CASE) 1.1 软件测试就是验…

亲测解决:项目无法编译/打包,提示找不到符号的问题

我在对服务进行打包的过程中遇到了“Error…找不到符号”的问题&#xff0c;但是我的项目是能够正常启动的&#xff0c;为什么会出现这个问题呢&#xff1f; 有的博主说是因为我没有正常打包&#xff0c;然后我又学习了一遍如何对项目进行打包…但是然并卵&#xff08;然而并没…

【Java数据结构】——第十节(下).选择排序与堆排序

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;Java初阶数据结构 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目…

一文3000字从0到1手把手教你基于PostMan的接口自动化测试

临近下半年&#xff0c;公司任务也不是很多&#xff0c;趁这个机会老大让我研究了一下PostMan的脚本自动化测试。作为一个前端开发&#xff0c;说实话&#xff0c;对于PostMan的操作&#xff0c;仅仅限于新建请求->填写url地址和参数->send发送&#xff0c;然后看看返回值…

智能排班系统 【开源说明】

文章目录 引言说明讲讲开源开源要做什么了解开源协议项目的信息脱敏写好项目说明文档修改.gitignore 项目不完善点说明管理系统前端页面自适应做得不好部分页面体验不好 管理系统后端接口缺乏数据校验数据管理接口查询不够完善接口可以更加完善 开源仓库地址其他文章引用说明前…

【我的创作纪念日】—— 纪念四年的坚持

这是一篇和技术无关的博客&#xff0c;但对我而言&#xff0c;它承载了不菲的价值 普通且宁静的一天&#xff0c;被一条消息戳中&#xff0c;于是&#xff0c;写一篇分享帖&#xff0c;纪念我这 1460 天的坚持初衷&#xff1a; 前言&#xff1a;对过去的回顾 4 年前的我&#…

南京邮电大学算法与设计实验二:贪心算法(最全最新,与题目要求一致)

三、实验原理及内容 实验原理&#xff1a; 1、用贪心法实现求两序列的一般背包问题。要求掌握贪心法思想在实际中的应用&#xff0c;分析一般背包的问题特征&#xff0c;选择算法策略并设计具体算法&#xff0c;编程实现贪心选择策略的比较&#xff0c;并输出最优解和最优解值。…

图的遍历,最小生成树,最短路径算法的手算。

1.图的遍历 按照某种规则沿着图中的边对图中的所有顶点访问一次且仅访问一次。 注&#xff1a;图是一种特殊的树。 1.广度优先遍历BFS 不难看出&#xff0c;图的广度优先就是参照的树的层次遍历算法。 2.深度优先遍历 从某个顶点开始V&#xff0c;访问这个顶点V相邻的任意…

【音视频开发】视频编码格式:YUV

文章目录 分类标准分类 简介 参考&#xff1a;YCbCr与YUV 分类标准 首先&#xff0c;我们可以将 YUV 格式按照数据大小分为三个格式&#xff0c;YUV 420&#xff0c;YUV 422&#xff0c;YUV 444。由于人眼对 Y 的敏感度远超于对 U 和 V 的敏感&#xff0c;所以有时候可以多个 …

位运算符及其相关操作详解

位运算符详解 前言&#xff1a;由于位运算符是直接对二进制数操作&#xff0c;因此对二进制、八进制、十六进制不甚了解的小伙伴建议先看这篇二进制、八进制、十六进制与十进制的相互关系&#xff0c;这样阅读本篇时将事半功倍 总览 位运算是对计算机存储的二进制序列的相应位进…

【笔试强训选择题】Day17.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 前言 目…