整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Flutter控件之圖片Image封裝

          Flutter控件之圖片Image封裝

          什么要進行繁瑣的封裝?直接用也挺好啊,這個回答一點毛病沒有,大部分視圖都可以原生繪制,可在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這些文件,好了鐵子們,本篇文章就先到這里,希望可以幫助大家。

          天小海前端(頭條號)為大家講解一個CSS3新增的邊框圖像屬性。這個屬性是為容器的邊框來增加圖像的。該屬性的兼容性暫時還不是特別好,建議大家使用火狐瀏覽器來嘗試該屬性的各個效果。

          承接文章:Web頁面實現圓角效果,CSS3幫你輕松實現,一個人人皆知的屬性

          技術等級:中級 | 適合有一定的CSS基礎的人士閱讀。

          希望收藏了這篇文章的你同時也可以關注一下“小海前端”的頭條號,因為這些文章都是連載的,并且是經過系統的歸納和總結的。塌下心來認真閱讀,你一定會學到對你有用的知識。

          本節涉及到的CSS3屬性為:

          • border-image

          • border-image-source

          • border-image-slice

          • border-image-width

          • border-image-repeat

          • border-image-outset

          一、圖像邊框的屬性:

          要想實現圖像的邊框,需要用到上面提到的六個屬性。這六個屬性只有border-image屬性和border-image-outset可以直接在代碼中使用,剩下的四個屬性是border-image屬性的派生屬性,用在border-image屬性的格式中。

          border-image屬性的格式如下所示:

          border-image:border-image-source

          border-image-slice/

          border-image-width

          border-image-repeat

          接下來我們對其中的每一個派生屬性來進行介紹。

          二、加載圖像源屬性:

          border-image-source屬性用于指定邊框圖像加載的圖像路徑和文件名,取值格式為:

          border-image-source:url(image_URL);

          三、圖像切片屬性:

          border-image-slice屬性用于指定一張圖片是如何分割為多個部分,并放置在塊級元素邊框的各個組成部分的。該屬性的取值為四個方向的像素值,并且規定不允許帶有單位。

          首先,我們選擇下面這張圖片作為邊框圖片的內容。這張圖片存放在一個名為images的文件夾中,文件名為ball.jpg,圖片的寬度和高度均為90像素。圖片中的每一個圓形的直徑均為30像素。

          素材圖片

          border-image-slice屬性就是用來設置上下左右四個方向向內切分圖像的寬度。我們大家一塊看下張圖片。

          切分圖片示意圖

          可以看出,如果四個方向均向內切分30像素的大小,由于這些圓的直徑為30像素,那么這些切分線就將這張圖片劃分為了9個組成部分。這9個組成部分正好是圖片中編號的9個組成部分。

          這樣,這張圖片的九個部分就會分布在邊框的以下幾個位置:

          • 1號圓形分布在邊框的左上角。

          • 2號圓形分布在邊框的上方。

          • 3號圓形分布在邊框的右上角。

          • 4號圓形分布在邊框的左側。

          • 5號圓形CSS將其分布在容器的內部。

          • 6號圓形分布在邊框的右側。

          • 7號圓形分布在邊框的左下角。

          • 8號圓形分布在邊框的下方。

          • 9號圓形分布在邊框的右下角。

          最后將圖像邊框的寬度也設置為30像素,這個圖像邊框就能夠顯示出來了。

          CSS代碼如下所示:

          border-image:url(../images/ball.jpg) 30/30px;

          最終的顯示效果為:

          代碼效果示意圖

          四、圖片邊框的平鋪效果:

          我們可以從效果圖中看出,在四個邊上的圖片都是拉伸的,這是由于border-image-repeat屬性的取值默認是stretch,意思是“拉伸”,該屬性還可以取值為repeat(平鋪)、round(精確平鋪)。我們將這個效果取值為round,再看一看邊框效果。

          CSS代碼如下所示:

          border-image:url(../images/ball.jpg) 30/30px round;

          最終的顯示效果為:

          代碼效果示意圖

          小海聲明

          在頭條上發表的這些文章都是從前端開發的基礎開始一步一步講起的。我非常希望能有更多的前端開發初學者通過我寫的文章,逐步學到一定的知識,甚至慢慢有了入門的感覺。這些文章都是我這幾年教學過程中的經驗,每寫一篇時我都盡量把握好措辭,用簡單易懂的語言描述,同時精心設計版面,讓版面更加豐富,激發閱讀興趣。所以,每一篇文章可能篇幅不長,但是都要耗費小海老師很久的時間。

          希望收藏了這篇文章的你同時也可以關注一下“小海前端”的頭條號,因為這些文章都是連載的,并且是經過系統的歸納和總結的。塌下心來認真閱讀,你一定會學到對你有用的知識。

          關注“小海前端”,我會繼續為大家奉上更加深入的前端開發文章,也希望更多的初學者跟著學下去,我們共同將前端開發的路努力堅持的走下去。

          文章預告

          下一篇文章中,小海前端(頭條號)會為小伙伴們繼續介紹border-image屬性的詳細用法。希望正在學習CSS3技術的小伙伴們繼續關注。

          片處理其實一鍵滲透到我們的基礎工作中,學會對圖片的基本處理也是工作基本功。在遇到好看的圖片卻被拉伸要如何處理?今天給大家介紹一個神奇的網站,在線一鍵修復拉伸變形圖片,處理圖像快人一步!

          在線工具:圖像AI處理:zaixianai-cn/imageHandle

          素材準備:變形哪吒圖片/拉伸女生圖片

          1.打開網站,進入“圖像AI處理”欄目

          打開這個神奇的網站,在線AI轉換,然后再打開“圖像AI處理”欄目,里面有其他選項,找到“拉伸圖片修復”即可。如下圖所示:


          2.上傳圖片,開始修復

          將準備好的素材,點擊“本地上傳”,然后網站就會自動開始修復啦。

          3.修復完成,點擊查看

          圖片修復過程很快,十幾秒的時間,然后就可以自己進行比對。值得注意的是,他的優化前和優化后的圖片尺寸在網站上都會被固定尺寸給框柱,所以如果原圖片跟網站尺寸不匹配,那么效果可能看不出來,得要下載下來才看清。


          4.下載修復好的圖片

          點擊“立即下載”,掃描,網站就會自動下載啦!下面看看修復效果和案例吧!

          網站還有語音處理功能,可以參考案例:文字如何在線轉成語音?


          主站蜘蛛池模板: 国产综合精品一区二区| 日本一区午夜爱爱| 精品一区二区三区色花堂| 精品成人乱色一区二区| 一区二区三区午夜视频| 亚洲一区二区三区香蕉| 岛国无码av不卡一区二区| 久久国产午夜一区二区福利 | 久久精品免费一区二区喷潮| 国产美女一区二区三区| 日韩一区二区免费视频| 国产一区在线视频| 亚洲.国产.欧美一区二区三区| 精品国产一区在线观看| 国产成人一区二区在线不卡| 精品国产日产一区二区三区 | 韩国资源视频一区二区三区| 国产婷婷一区二区三区| 国产一区二区三区乱码网站| 国产一区二区三区亚洲综合| 久久久久一区二区三区 | 另类ts人妖一区二区三区| 久久国产精品免费一区二区三区| 麻豆高清免费国产一区| 一区二区三区在线看| 无码人妻一区二区三区一| 国产不卡视频一区二区三区| 日韩中文字幕精品免费一区| 精品乱子伦一区二区三区| 欧美亚洲精品一区二区| 亚洲爆乳无码一区二区三区| 国产在线视频一区二区三区| 亚洲视频一区二区三区| 亚洲美女高清一区二区三区| 伊人久久大香线蕉AV一区二区| 国产av熟女一区二区三区| 高清在线一区二区| 亚洲AV网一区二区三区| ...91久久精品一区二区三区| 久久久99精品一区二区| 国产精品一区不卡|