在上一篇Android Activity Result API (二) :拍照与选择照片中提到了使用默认合约GetContent和GetMultipleContents来实现选择照片。
但是通过这两个默认合约打开的选择器其实是文件选择器,并不是直接进入相册的,不是很方便,因此想到了使用自定义合约来实现直接进入相册选择照片。
选择单张照片
通过自定义合约实现单张照片选择代码如下:
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)
}
}
}
效果图:
选择多张照片
虽然可以实现选择多张照片,但是同默认合约一样无法控制选择数量的上限。
通过自定义合约实现多张照片选择代码如下:
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)
}
}
}
效果图: