Android 图片选择器改系统

前言

因为以前的系统图片选择器在多选的体验上太差,或者想做一些自定义的操作,所以以前一般都是使用自定义的图片选择器或者一些功能性比较强大的第三方图片选择器。但从现在起需要改成使用系统的图片选择器,为什么这么突然?因为google早已下达了最后的期限。

能看到25年的5月28就是这个的最后期限。为什么google要这么做,近年来的更新我们都知道,google一直在规范和完善权限这块领域的内容,这一操作也只是google进一步缩紧权限的操作。

那么也可以去思考一下,未来会不会进一步收缩,比如跳H5,它会不会最终弄成只允许跳自家的浏览器,或者跳其它应用会加上严苛的限制。

startActivityForResult过期

讲系统的图片选择器之前可以先预热了解一下startActivityForResult过期的问题。这个会和获取返回的图片有一定的相关。我们平时跳出应用外的页面并且需要返回数据,比如跳到相册,返回选择的相片。以前的做法一般都是通过startActivityForResult和onActivityResult去进行配合。

其中的一个核心是requestCode和resultCode,我怎么判断onActivityResult的调用是对应哪个startActivityForResult,就是用这两个code来做区分的嘛,这个注意一下,后面会考。

回归正题,现在这个方法已经过期了,如果你在项目中使用的话,你会明显发现

那么官方把这个方法过期了,自然有提供新的方法,可以参考官网 developer.android.com/training/ba...

写个Dmeo就是

scss 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 初始化 ActivityResultLauncher
    activityResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                // 处理返回结果
                if (result.getResultCode() == RESULT_OK) {
                    Intent data = result.getData();
                    // 处理数据
                }
            });
}
arduino 复制代码
Intent intent = new Intent(this, SecondActivity.class); 
activityResultLauncher.launch(intent); // 启动第二个活动

这里有个需要注意的点,registerForActivityResult需要写在onCreate里面

我这里就不做演示了,那么此时你应该会发现一个问题,假如我该Activity有intent到不同页面的场景并且都有返回内容,我怎么区分此时返回的是哪个intent的,因为这个新的方式是没有requestCode去做区分的。

其实也很简单,这里的整个activityResultLauncher就可以当成一个行为的对象,如果你要跳转多个页面,那就创建多个activityResultLauncher,它内部的callback就是对应的意图

跳转系统相册进行图片选择

上面说了startActivityForResult过期了,我这里肯定直接用registerForActivityResult来实现。

kotlin 复制代码
private var imagePickerLauncher: ActivityResultLauncher<Intent>? = null

fun bindActivity(activity: AppCompatActivity, callback: (Intent?) -> Unit?) {
    this.activity = activity

    imagePickerLauncher = activity.registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val data: Intent? = result.data
            callback.invoke(data)
        }
    }
}


fun select() {
    val intent = Intent(Intent.ACTION_PICK)
    intent.setType("image/*")
    imagePickerLauncher?.launch(intent)
}

我简单封装了一个方法,直接跳相册选择图片后返回,bindActivit需要在onCreate中调用,这个上面有重点说过。

这样看似乎是没问题,但是(Android13以下)你会发现,跳到相册里面没办法多选,只能实现单选图片的场景。那怎么进行多选呢?

Android 跳系统相册选择图片

回到最开始说的正常,联系上面的方法,既然Android提出了这个政策,而我们的旧的方法又做不到多选,那官方自然会提供新的方法给我们调用。

developer.android.com/training/da...

单选

typescript 复制代码
private var pickMultipleMedia1: ActivityResultLauncher<PickVisualMediaRequest>? = null

pickMultipleMedia1 = activity.registerForActivityResult(
    ActivityResultContracts.PickVisualMedia()
){uri ->
    callback.invoke(uri)
}

pickMultipleMedia1?.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))

多选

typescript 复制代码
private var pickMultipleMedia2: ActivityResultLauncher<PickVisualMediaRequest>? = null

pickMultipleMedia2 = activity.registerForActivityResult(
    ActivityResultContracts.PickMultipleVisualMedia(
        数量
    )
){uris ->
    if (uris.isNotEmpty()) {
        var realUris: List < Uri? > = uris
        if (uris.size > 数量){
            realUris = uris.take(数量)
        }
        callback.invoke(realUris)
    }
}

pickMultipleMedia2?.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))

多选这里里面有一步判断数量的操作,这个是和版本兼容相关的,下面会进行说明。

从这里看出,在旧版本的跳转系统相册我们是使用Intent的方法去跳转,这种方式无法适配多选的场景,而Android新提供的PickVisualMedia和PickMultipleVisualMedia能让我们实现跳转系统相册并进行单选和多选。

版本兼容

没错,PickVisualMedia和PickMultipleVisualMedia存在版本兼容的问题,在Android13以下是会打开到旧页面

可以看到这种情况下也没有多选的提示,但是当随便长按一张图片之后,就能正常打开多选的场景

但是这种多选还会存在一个问题,那就是没办法限制住图片的数量,想选多少就选多少,所以上面的代码中才会写

csharp 复制代码
        var realUris: List < Uri? > = uris
        if (uris.size > 数量){
            realUris = uris.take(数量)
        }

就是为了防止这种场景的发生,比如只能选3张图,这里选了10张,我在外边只拿前3张,当然这是我自己业务里面的策略,这里当然也可以做其它策略,比如超出就全丢掉。

而在Android13之后,PickMultipleVisualMedia会跳转到新相册中,此时就有比较好的体验了

相关推荐
zhishishe8 分钟前
工具指南:免费将 PDF 转换为 Word 的 10 个工具
android·windows·pdf·word
孙同学_17 分钟前
【MySQL】004.MySQL数据类型
android·数据库·mysql
前行的小黑炭3 小时前
Android 上下位机开发:串口是什么,为什么android版本都比较低?粘包半包的原因以及处理思路,缓冲区处理,以及超时清空缓冲区....
android
移动开发者1号3 小时前
你知道Android中配置resourcePrefix的作用吗?
android
tangweiguo030519874 小时前
Android Compose 系统 Scope 的优化实践
android
我命由我123454 小时前
Android Cordova 开发 - Cordova 快速入门(Cordova 环境配置、Cordova 第一个应用程序)
android·开发语言·前端框架·android studio·h5·安卓·android-studio
老板来根葱4 小时前
应用进程创建二三事
android·源码阅读
DEVIL4 小时前
Flutter中各类Controller的本质
android·flutter
Kongzue7 小时前
让DialogX的消息提示玩出花 - 自定义PopTip和 PopNotification的避让动画
android·java