概述
本文介绍App Inventor 2中常见的图片处理需求:
- 图片缩放(等比/固定尺寸)
- 图片存储到本地/相册
- 图片格式转换
- Canvas绘制图片
- 图片选择和裁剪
图片选择
使用ImagePicker
ImagePicker让用户从手机相册选择图片:
当 按钮_选择图片.被点击
调用 图片选择器1.选择图片()
当 图片选择器1.选择完成(路径)
如果 路径 ≠ ""
设 Image1.图片 = 路径
标签_路径.文本 = "图片路径:" & 路径
使用FilePicker(选择任意文件)
当 按钮_选择文件.被点击
调用 文件选择器1.选择文件()
当 文件选择器1.选择完成(路径)
如果 路径 以 ".jpg" 结尾 或 路径 以 ".png" 结尾
设 Image1.图片 = 路径
使用Camera拍照
当 按钮_拍照.被点击
调用 相机1.拍照()
当 相机1.拍照完成(图片路径)
设 Image1.图片 = 图片路径
图片缩放
方案一:Canvas缩放(推荐)
通过Canvas将图片绘制到指定尺寸:
设 原始图片路径 = ""
设 目标宽度 = 200
设 目标高度 = 200
当 按钮_缩放.被点击
设 Canvas1.画布宽度 = 目标宽度
设 Canvas1.画布高度 = 目标高度
调用 Canvas1.清除()
调用 Canvas1.绘制图片(原始图片路径, 0, 0, 目标宽度, 目标高度)
当 按钮_保存缩放图.被点击
设 缩放后图片 = 调用 Canvas1.保存图片()
标签_结果.文本 = "已保存:" & 缩放后图片
方案二:等比缩放
保持宽高比的缩放:
定义 等比缩放尺寸(原图宽, 原图高, 最大边长) 返回 尺寸字典
如果 原图宽 ≥ 原图高
设 缩放比 = 最大边长 / 原图宽
设 新宽 = 最大边长
设 新高 = 数学.向下取整(原图高 * 缩放比)
否则
设 缩放比 = 最大边长 / 原图高
设 新高 = 最大边长
设 新宽 = 数学.向下取整(原图宽 * 缩放比)
返回 创建字典("width" → 新宽, "height" → 新高)
方案三:WebView + Canvas缩放(精确控制)
使用HTML5 Canvas进行高质量缩放:
<!-- resize.html -->
<canvas id="canvas"></canvas>
<script>
function resizeImage(dataUrl, maxW, maxH) {
var img = new Image();
img.onload = function() {
var ratio = Math.min(maxW / img.width, maxH / img.height);
var w = Math.floor(img.width * ratio);
var h = Math.floor(img.height * ratio);
var canvas = document.getElementById('canvas');
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, w, h);
window.AppInventor.setWebViewString(canvas.toDataURL('image/jpeg', 0.8));
};
img.src = dataUrl;
}
</script>
图片存储
保存到应用私有目录
当 按钮_保存.被点击
' Canvas保存到应用目录
设 保存路径 = "/sdcard/AppInventor/Assets/my_image.png"
调用 Canvas1.保存图片()
标签_结果.文本 = "已保存到:" & 保存路径
保存到相册
使用FileTools扩展或File组件:
' 方案1:使用File组件复制到相册目录
当 按钮_保存到相册.被点击
设 源路径 = Canvas1.保存图片()
设 目标路径 = "/sdcard/DCIM/Camera/my_photo_" & Clock1.格式化日期时间(Clock1.当前时间(), "yyyyMMdd_HHmmss") & ".png"
调用 File1.保存文件(调用 File1.读取文件(源路径), 目标路径)
当 File1.保存完成(文件名)
标签_结果.文本 = "✅ 已保存到相册:" & 文件名
注意:Android 10+的分区存储限制,直接写入DCIM目录可能需要特殊权限。推荐使用FileTools扩展的
SaveFileToGallery方法。
使用FileTools扩展
FileTools扩展 提供了直接保存图片到相册的方法:
当 按钮_保存到相册.被点击
调用 FileTools1.保存到相册(图片路径, "MyAppPhotos")
图片裁剪
Canvas裁剪
设 裁剪起点X = 50
设 裁剪起点Y = 50
设 裁剪宽度 = 200
设 裁剪高度 = 200
当 按钮_裁剪.被点击
' 在Canvas上绘制裁剪区域
设 Canvas2.画布宽度 = 裁剪宽度
设 Canvas2.画布高度 = 裁剪高度
调用 Canvas2.清除()
' drawImage的源区域参数
调用 Canvas2.绘制图片部分(Image1.图片,
裁剪起点X, 裁剪起点Y, 裁剪宽度, 裁剪高度,
0, 0, 裁剪宽度, 裁剪高度)
WebView裁剪(支持手势框选)
更灵活的方式是在WebView中用JavaScript实现图片裁剪,支持拖拽选择区域。
图片格式转换
Canvas转Base64
当 按钮_转Base64.被点击
设 base64数据 = 调用 Canvas1.保存图片为Base64()
标签_结果.文本 = base64数据
Base64转图片
当 按钮_转图片.被点击
设 Image1.图片 = "data:image/png;base64," & 输入框_Base64.文本
实战案例:头像上传
功能需求
- 从相册选择或拍照获取头像
- 等比缩放到200x200
- 圆形裁剪
- 上传到服务器
积木块代码
设 头像路径 = ""
当 按钮_选择头像.被点击
调用 图片选择器1.选择图片()
当 图片选择器1.选择完成(路径)
如果 路径 ≠ ""
设 头像路径 = 路径
' 缩放到200x200
设 Canvas1.画布宽度 = 200
设 Canvas1.画布高度 = 200
调用 Canvas1.清除()
调用 Canvas1.绘制图片(路径, 0, 0, 200, 200)
设 Image_预览.图片 = Canvas1.保存图片()
当 按钮_上传头像.被点击
设 base64 = 调用 Canvas1.保存图片为Base64()
' 通过Web1上传
调用 Web1.执行Post请求("https://api.example.com/upload/avatar",
"image=" & base64)
当 Web1.收到文本(响应内容)
如果 响应内容 = "success"
标签_提示.文本 = "✅ 头像上传成功"
否则
标签_提示.文本 = "❌ 上传失败"
常见问题
Q1: 图片显示变形怎么办?
使用等比缩放,不要强制拉伸。Image组件设置 ScalePictureToFit = true 可以自动等比缩放。
Q2: 大图片导致OOM(内存溢出)?
App Inventor处理大图片(>5MB)容易崩溃。解决方案:
- 先用Canvas缩小到合理尺寸(如1024x1024)
- 使用WebView方案处理大图
- 避免同时加载多张大图
Q3: 图片保存到相册后手机相册看不到?
需要通知系统扫描新文件。使用FileTools扩展的 scanFile 方法:
调用 FileTools1.扫描文件(保存路径)
或者重启手机后才会出现。
Q4: 如何获取图片的宽高?
App Inventor内置组件不直接提供图片尺寸信息。可以用WebView获取:
var img = new Image();
img.onload = function() {
window.AppInventor.setWebViewString(img.width + "," + img.height);
};
img.src = imagePath;
总结
| 需求 | 推荐方案 |
|---|---|
| 选择图片 | ImagePicker / Camera |
| 缩放图片 | Canvas绘制 |
| 存储到相册 | FileTools扩展 |
| 裁剪图片 | Canvas / WebView |
| 格式转换 | Canvas + Base64 |
| 上传图片 | Web组件 + Base64 |
版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。
扫码添加客服咨询