基于Flutter的图片浏览器的实现

一 效果展示:

1. 图片展示:

2.混色,平铺,拉伸,原图展示

二 实验准备:

1.在包结构中创建images包来存放我们用到的图片,在pubspec.yaml中声明路径:

  1. 检查虚拟机是否正常运行:

三 详细设计:

大体流程:

特别注意:

我们创建继承自State 的**_MyHomePageState**类的用处是

  1. 状态管理: State 对象是与 StatefulWidget 相关联的状态的持有者。通过继承自State,可以在这个对象中存储和管理与用户界面相关的数据。

  2. 生命周期方法: State 类提供了一系列生命周期方法,例如 initStatedidUpdateWidgetbuilddispose 等。这些方法允许在不同阶段执行特定的操作,例如在初始化状态、更新部件时、构建部件树、销毁状态等。

  3. 动态更新: 通过调用 setState 方法,可以通知Flutter框架重新构建UI。这使得在用户与应用交互时,能够根据状态的变化动态更新UI,提供交互性和实时性。

  4. 保存和恢复状态: State 对象可以保存和恢复其状态。这对于在应用生命周期内保留数据状态,以及在设备方向切换或应用关闭后恢复状态非常有用。

  5. 构建UI: build 方法是构建用户界面的地方。通过覆盖 build 方法,可以定义在状态更改时如何构建和渲染UI。

  6. 数据封装: 将相关的状态和逻辑封装在State类中有助于提高代码的组织性和可读性。这样,每个部件的状态都可以独立管理,降低了代码的复杂度。

  7. 优化性能: State 对象的状态是惰性创建的,当部件首次插入到树中时,State 对象才会被创建。这有助于优化应用性能。

cpp 复制代码
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

功能实现:

功能一:图片展示:

组件:

Container: 用于创建包含图片的容器。

Scaffold: 提供应用程序的基本结构,包括主体区域。

Column: 用于在垂直方向上排列不同的小部件。

属性和方法:

Container的width和height属性: 设置容器的宽度和高度。

Container的color属性: 设置容器的背景颜色。

Container的child属性: 设置容器中包含的子部件。

DecorationImage的image属性: 设置Image.asset的图片来源。

DecorationImage的repeat属性: 设置图片在容器中的重复方式。

cpp 复制代码
Container imgContainer = Container(
  width: MediaQuery.of(context).size.width,
  height: MediaQuery.of(context).size.height / 3,
  color: Colors.amberAccent,
  child: Container(
    decoration: BoxDecoration(
      image: DecorationImage(
        image: AssetImage(lists[index]),
        repeat: ImageRepeat.repeat,
      ),
    ),
  ),
);

功能二:效果选择 :

组件:

RadioListTile: 用于显示单选列表项。

属性和方法:

value属性: 表示当前选项的值。

groupValue属性: 表示所在组的当前选中值。

title属性: 列表项的主要文本。

subtitle属性: 列表项的副标题文本。

onChanged回调: 在用户选择该项时触发的函数。

Dart 复制代码
RadioListTile(
  value: 0,
  groupValue: selected,
  title: Text('混色'),
  subtitle: Slider(
    value: colorsValue,
    min: 0,
    max: 255,
    onChanged: (value) {
      setState(() {
        colorsValue = value;
      });
    },
  ),
  onChanged: (value) {
    setState(() {
      selected = value ?? 0;
    });
  },
);

功能三:混色效果 :

组件:

Container: 用于包裹混色效果的图片。

ColorFiltered: 用于应用颜色混合效果。

属性和方法:

colorFilter属性: 设置ColorFiltered的颜色混合滤镜。

Color.fromARGB方法: 创建一个颜色对象。

round()方法: 将浮点数四舍五入为最接近的整数。

Dart 复制代码
ColorFiltered(
  colorFilter: ColorFilter.mode(
    Color.fromARGB(255, colorsValue.round(), colorsValue.round(), colorsValue.round()),
    BlendMode.colorDodge,
  ),
  child: Image.asset(lists[index]),
);

功能四:平铺效果:

组件:

Container: 用于包裹平铺效果的图片。

属性和方法:

DecorationImage的repeat属性: 设置图片在容器中的重复方式。

round()方法: 将浮点数四舍五入为最接近的整数。

cpp 复制代码
Container(
  width: MediaQuery.of(context).size.width,
  height: MediaQuery.of(context).size.height / 3,
  color: Colors.amberAccent,
  child: Container(
    decoration: BoxDecoration(
      image: DecorationImage(
        image: AssetImage(lists[index]),
        repeat: ImageRepeat.repeat,
      ),
    ),
  ),
);

功能五:颜色调整:

组件:

Slider: 用于提供滑动条以调整颜色值。

属性和方法:

value属性: 表示当前滑块的值。

min和max属性: 设置滑块的最小和最大值。

onChanged回调: 在滑动条值变化时触发的函数。

cpp 复制代码
Slider(
  value: colorsValue,
  min: 0,
  max: 255,
  onChanged: (value) {
    setState(() {
      colorsValue = value;
    });
  },
);

功能六:图片切换 :

组件:

ElevatedButton: 用于显示提升的按钮。

属性和方法:

onPressed回调: 在按钮被点击时触发的函数。

cpp 复制代码
ElevatedButton(
  child: Text('向前'),
  onPressed: () {
    setState(() {
      if (index > 0) index--;
    });
  },
);
ElevatedButton(
   child: Text('向后'),
      onPressed: () {
         setState(() {
         if (index < lists.length - 1) index++;
      });
   },
),

功能七:拉伸图片

组件:

Container 组件:

用途: 用于创建一个矩形的可视容器,可以包含子组件,并设置容器的样式和尺寸。

相关属性:

width:容器的宽度,设置为屏幕的宽度。

height:容器的高度,设置为屏幕高度的三分之一。

color:容器的颜色,设置为 Colors.amberAccent

Image.asset 组件:

用途: 用于显示应用内的图片资源。

相关属性:

lists[index]:图片的路径,从预定义的列表中选择。

fit:用于指定图片的填充方式,这里设置为 BoxFit.fill,表示填充整个容器。

cpp 复制代码
mgContainer = Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height / 3,
        color: Colors.amberAccent,
        child: Image.asset(
          lists[index],
          fit: BoxFit.fill,
        ),
      );

四 完整代码

cpp 复制代码
import 'package:flutter/material.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  int? selected = 0; // 默认选中混色
  List<String> lists = ['images/p1.jpg', 'images/p2.jpg', 'images/p3.jpg', 'images/p4.jpg'];
  int index = 0;
  double colorsValue = 0.0;
  BoxFit fitType = BoxFit.fill; // 用于控制图片的填充方式
  @override
  Widget build(BuildContext context) {
    Container imgContainer;

    if (selected == 1) {
      // 如果是平铺效果,将 Image.asset 放在 Container 中
      imgContainer = Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height / 3,
        color: Colors.amberAccent,
        child: Container(
          decoration: BoxDecoration(
            image: DecorationImage(
              image: AssetImage(lists[index]),
              repeat: ImageRepeat.repeat,
            ),
          ),
        ),
      );
    } else if (selected == 2) {
      // 如果是拉伸原图,将图片的填充方式设置为拉伸
      imgContainer = Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height / 3,
        color: Colors.amberAccent,
        child: Image.asset(
          lists[index],
          fit: BoxFit.fill,
        ),
      );
    } else {
      // 否则应用混色效果
      imgContainer = Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height / 3,
        color: Colors.amberAccent,
        child: ColorFiltered(
          colorFilter: ColorFilter.mode(
            Color.fromARGB(255, colorsValue.round(), colorsValue.round(), colorsValue.round()),
            BlendMode.colorDodge,
          ),
          child: Image.asset(
            lists[index],
            fit: fitType, // 使用BoxFit属性来控制图片的填充方式
          ),
        ),
      );
    }

    return Scaffold(
      body: Column(
        children: <Widget>[
          imgContainer,
          RadioListTile(
            value: 0,
            groupValue: selected,
            title: Text('混色'),
            subtitle: Slider(
              value: colorsValue,
              min: 0,
              max: 255,
              onChanged: (value) {
                setState(() {
                  colorsValue = value;
                });
              },
            ),
            onChanged: (value) {
              setState(() {
                selected = value ?? 0;
                fitType = BoxFit.fill; // 选择混色时,将图片的填充方式设置为拉伸
              });
            },
          ),
          RadioListTile(
            value: 1,
            groupValue: selected,
            title: Text('平铺'),
            subtitle: Text('按XY方向平铺在显示区域'),
            onChanged: (value) {
              setState(() {
                selected = value ?? 0;
                fitType = BoxFit.fill; // 选择平铺时,将图片的填充方式设置为拉伸
              });
            },
          ),
          RadioListTile(
            value: 2,
            groupValue: selected,
            title: Text('拉伸原图'), // 选择拉伸原图时,将图片的填充方式设置为拉伸
            onChanged: (value) {
              setState(() {
                selected = value ?? 0;
                fitType = BoxFit.fill;
              });
            },
          ),
          RadioListTile(
            value: 3,
            groupValue: selected,
            title: Text('显示原图'), // 新增:显示原图
            onChanged: (value) {
              setState(() {
                selected = value ?? 0;
                fitType = BoxFit.contain; // 选择显示原图时,将图片的填充方式设置为保持宽高比适应容器
              });
            },
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              ElevatedButton(
                child: Text('向前'),
                onPressed: () {
                  setState(() {
                    if (index > 0) index--;
                  });
                },
              ),
              ElevatedButton(
                child: Text('向后'),
                onPressed: () {
                  setState(() {
                    if (index < lists.length - 1) index++;
                  });
                },
              ),
            ],
          ),
        ],
      ),
    );
  }
}
相关推荐
如若12326 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~1 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语1 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport1 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg1 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww1 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_748254881 小时前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
星就前端叭2 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234522 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js
Web阿成2 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript