Android Activity Result API (三) :自定义合约打开相册选择照片

761 阅读1分钟

在上一篇Android Activity Result API (二) :拍照与选择照片中提到了使用默认合约GetContentGetMultipleContents来实现选择照片。

但是通过这两个默认合约打开的选择器其实是文件选择器,并不是直接进入相册的,不是很方便,因此想到了使用自定义合约来实现直接进入相册选择照片。

选择单张照片

通过自定义合约实现单张照片选择代码如下:

class PickSinglePhotoContract : ActivityResultContract<String, Uri>() {

    override fun createIntent(context: Context, input: String?): Intent {
        return Intent(Intent.ACTION_PICK)
            .setType("image/*")
    }

    override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
        return if (intent == null || resultCode != Activity.RESULT_OK) null else intent.data
    }
}

class PhotoActivity : AppCompatActivity() {

    private lateinit var binding: LayoutPhotoActivityBinding
    
    private val pickSinglePhoto = registerForActivityResult(PickSinglePhotoContract()) { uri ->
        binding.ivPhoto.setImageURI(uri)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.layout_photo_activity)

        binding.btnSelectPhoto.setOnClickListener {
            pickPhoto.launch(null)
        }
    }
}

效果图:

1649489005613031_.gif

选择多张照片

虽然可以实现选择多张照片,但是同默认合约一样无法控制选择数量的上限。

通过自定义合约实现多张照片选择代码如下:

class PickMultiplePhotoContract : ActivityResultContract<String, List<Uri>>() {

    override fun createIntent(context: Context, input: String?): Intent {
        return Intent(Intent.ACTION_PICK)
            .setType("image/*")
            .putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    }

    override fun parseResult(resultCode: Int, intent: Intent?): List<Uri> {
        return if (intent == null || resultCode != Activity.RESULT_OK) {
            emptyList()
        } else {
            getClipDataUris(intent)
        }
    }

    private fun getClipDataUris(intent: Intent): List<Uri> {
        val resultSet = LinkedHashSet<Uri>()
        if (intent.data != null) {
            resultSet.add(intent.data!!)
        }
        val clipData = intent.clipData
        if (clipData == null && resultSet.isEmpty()) {
            return emptyList()
        } else if (clipData != null) {
            for (i in 0 until clipData.itemCount) {
                val uri = clipData.getItemAt(i).uri
                if (uri != null) {
                    resultSet.add(uri)
                }
            }
        }
        return ArrayList(resultSet)
    }
}

class PhotoActivity : AppCompatActivity() {

    private lateinit var binding: LayoutPhotoActivityBinding
    
    private val pickMultiplePhoto = registerForActivityResult(PickMultiplePhotoContract()) { uriList ->
        if (uriList.size > 1) {
            binding.ivPhoto.setImageURI(uriList[0])
            binding.ivPhoto1.setImageURI(uriList[1])
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.layout_photo_activity)

        binding.btnSelectMultiplePhoto.setOnClickListener {
            pickMultiplePhoto.launch(null)
        }
    }
}

效果图:

1649488789551636_.gif