安卓图片保存到本地和裁剪
Posted 落月江树
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓图片保存到本地和裁剪相关的知识,希望对你有一定的参考价值。
安卓图片保存到本地和裁剪
这里的两个小功能做了我四天,实在是坑爹啊,对安卓的文件,uri还是懵懵懂懂,先把能实现的方法记录一下
安卓10,11之后的存储空间管理是一个大坑,有时间要系统的整理一下
保存图片
要保存图片到本地,我们有样学样,先看看其他应用保存到了哪里
打开相册,发现大多数app保存的图片都在内部存储/Pictures/xxx
下,xxx为应用自己命名的目录名,通常和应用名的英文或者拼音一致(我使用的是MIUI系统)
在安卓10适配时,要访问到这个内部存储,需要通过uri,因为我们保存的是图片,可以借助媒体库把图片插入进来,下面的代码和注释很好的说明了
val values = ContentValues()
// 指定相册, 这里是内部存储空间的Pictures相册下面再生成相册
values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/simple")
// 生成保存位置的uri
val saveUri: Uri?= requireContext().contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
if (saveUri != null) {
// 利用输出流,把文件写出,并压缩
requireContext().contentResolver.openOutputStream(saveUri).use{
if(bitmap.compress(Bitmap.CompressFormat.JPEG,100,it)){
Toast.makeText(requireContext(),"存储成功",Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(requireContext(),"存储失败",Toast.LENGTH_SHORT).show()
}
}
}else{
Toast.makeText(requireContext(),"存储失败",Toast.LENGTH_SHORT).show()
}
}
这里根据文档的指导,要先生成我们插入位置的uri,然后才通过输出流的方式把文件写入存储中。在这里要注意,只有指定格式为JPG,才会在照片中直接看到我们保存的图片,若写入为PNG,则只能先寻找相册再找到图片。这里用了use拓展,把输出流指定为bitmap压缩的路径,压缩率为100
裁剪图片
打开相册
要从相册中选择图片,首先我们要能选出来。系统把打开相册封装为了一个具有返回值的Activity,我们选择的照片就是返回值
imageView!!.setOnClickListener {
val intent = Intent()
intent.type = "image/*"
intent.action = "android.intent.action.GET_CONTENT"
intent.addCategory("android.intent.category.OPENABLE")
startActivityForResult(intent, REQUEST_CODE_ALBUM)
}
在这里,点击头像框的imageview后,会打开相册,然后等待返回值。当在相册中点击选到一张图片,就返回了
成功返回后,进行处理:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_CODE_ALBUM ->{ // 在这里处理逻辑
Log.d("返回值", "${REQUEST_CODE_ALBUM}")
// 下面的uCrop是裁剪函数,后面会介绍
uCrop(data?.data!!)
}
}
裁剪
如果要给用户做更换头像的功能,必须用到裁剪图片,这里我们使用第三方库UCrop进行裁剪
首先导入依赖:
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
...
}
// :app中
implementation \'com.github.yalantis:ucrop:2.2.6-native\'
implementation \'com.github.yalantis:ucrop:2.2.6\'
上面打开相册用了uCrop函数,我们考察这个函数的内容
@RequiresApi(Build.VERSION_CODES.Q)
fun uCrop(sUri:Uri){
var mPhotoUri = getCacheuri()
Log.d("返回的Uri","${mPhotoUri}")
UCrop.of(sUri, mPhotoUri!!) //定义路径
.withAspectRatio(1f, 1f) //定义裁剪比例
.withMaxResultSize(150, 150) //定义裁剪图片宽高最大值, 一般要适配你的imageview
.start(this)
}
在UCrop的调用中,我们要指定一个图片来源的Uri (这里采用的是打开相册返回的Uri) ,和一个裁剪后保存的Uri,把图片存到某个地方
我们可以把目标Uri定位在app缓存中,getCacheuri函数实现了这个功能
fun getCacheuri():Uri{
var cacheFile:File? = null
val outpurDir = this.cacheDir
if(outpurDir.exists()){
cacheFile = File(outpurDir.path+File.separator+"${System.currentTimeMillis()}_"+"cache.png")
}
var mPhotoUri = Uri.fromFile(cacheFile)
return mPhotoUri
}
在这里,我们获取到应用缓存目录,然后在缓存目录下创建一个新文件(格式可以修改,这里用了时间戳来保证唯一文件名),然后把这个文件对应的Uri返回回去,此时文件创建出来,但没有具体内容
裁剪成功后,显示我们裁剪的图片
// 在override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) 作为一个选择项
UCrop.REQUEST_CROP->{
Log.d("裁剪返回", "${UCrop.REQUEST_CROP}")
var uri = UCrop.getOutput(data!!)
Log.d("返回Uri", "${uri}")
imageView!!.setImageURI(uri) // 这里也可以运用Glide加载
}
这样,一般就能实现截图功能
简易的图片界面, 用了ShapeAbleImageView, 宽高都是150dp:
截图使用:
裁剪后图像,大致实现了个换头像的效果:
以上是关于安卓图片保存到本地和裁剪的主要内容,如果未能解决你的问题,请参考以下文章
安卓开发截取当前屏幕图片及截取整个ListView图片并保存到本地