You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Activity Result Contracts结合UCrop时无法获取裁剪结果到应用中

Fixing UCrop Result Preview Issue in Your Android Activity

Hey there! Let's figure out why your cropped image isn't showing up in the ImageView—I've spotted a few key issues in your code that are causing this problem, and fixing them should get things working smoothly.

1. You're Using the Wrong Intent to Get the Cropped Result

The biggest mistake is in your cropImage activity result callback:

private val cropImage = registerForActivityResult(uCropContract){
    val uri = intent.data // ❌ This is the NewPostActivity's intent, not UCrop's result!
    imageUri = uri
    newPostImageSelector.setImageURI(imageUri)
}

UCrop already returns the cropped image's Uri directly through the callback parameter (it). You don't need to access intent.data here—that's pointing to the intent that launched your activity, not the result from UCrop.

2. Unsafe Parsing of UCrop Result

Your custom uCropContract doesn't handle error cases properly, which could lead to crashes or null results. If the user cancels the crop, intent might be null, and using !! will throw an exception.

3. Invalid Output File Name

You added a space in your output file name (" .jpg"), which can cause file path issues. Always avoid spaces in file names for Android storage operations.


Corrected Code

Here's the fixed version of your code with explanations:

Step 1: Fix the UCrop Contract

Update the contract to safely handle result codes and null intents:

private val uCropContract = object : ActivityResultContract<Pair<Uri, Uri>, Uri?>() {
    override fun createIntent(context: Context, input: Pair<Uri, Uri>): Intent {
        val (inputUri, outputUri) = input
        return UCrop.of(inputUri, outputUri)
            .withAspectRatio(2F, 1F)
            .withMaxResultSize(1720, 860)
            .getIntent(context)
    }

    override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
        // Only return the result if the crop was successful
        return if (resultCode == RESULT_OK && intent != null) {
            UCrop.getOutput(intent)
        } else {
            null
        }
    }
}

I changed the input type to a Pair<Uri, Uri> instead of a List—it's cleaner for passing exactly two URIs.

Step 2: Fix the Crop Result Callback

Now use the callback parameter to get the cropped Uri:

private val cropImage = registerForActivityResult(uCropContract) { croppedUri ->
    croppedUri?.let {
        imageUri = it
        newPostImageSelector.setImageURI(imageUri) // ✅ This will load the cropped image!
    }
}

We use let to safely handle the case where the user cancels the crop (croppedUri is null).

Step 3: Fix the Output Uri and Launch Logic

Update the getContent callback to pass a Pair instead of a list, and fix the file name:

private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
    uri?.let { inputUri ->
        // Remove the space in the file name
        val outputFile = File(filesDir, "${System.currentTimeMillis()}_post.jpg")
        val outputUri = outputFile.toUri()
        // Pass input and output URIs as a Pair
        cropImage.launch(Pair(inputUri, outputUri))
    }
}

Full Corrected Activity Code

class NewPostActivity : AppCompatActivity() {
    private var myUrl: String? = null
    private var imageUri: Uri? = null
    private var storagePostPicRef: StorageReference? = null
    private lateinit var publishPostButton: ImageView
    private lateinit var closePostPageButton: ImageView
    private lateinit var newPostImageSelector: ImageView

    private val uCropContract = object : ActivityResultContract<Pair<Uri, Uri>, Uri?>() {
        override fun createIntent(context: Context, input: Pair<Uri, Uri>): Intent {
            val (inputUri, outputUri) = input
            return UCrop.of(inputUri, outputUri)
                .withAspectRatio(2F, 1F)
                .withMaxResultSize(1720, 860)
                .getIntent(context)
        }

        override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
            return if (resultCode == RESULT_OK && intent != null) {
                UCrop.getOutput(intent)
            } else {
                null
            }
        }
    }

    private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
        uri?.let { inputUri ->
            val outputFile = File(filesDir, "${System.currentTimeMillis()}_post.jpg")
            val outputUri = outputFile.toUri()
            cropImage.launch(Pair(inputUri, outputUri))
        }
    }

    private val cropImage = registerForActivityResult(uCropContract) { croppedUri ->
        croppedUri?.let {
            imageUri = it
            newPostImageSelector.setImageURI(imageUri)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_new_post)
        storagePostPicRef = FirebaseStorage.getInstance().reference.child("Post Pictures")
        publishPostButton = findViewById(R.id.publishNewPost)
        closePostPageButton = findViewById(R.id.closeAddPost)
        newPostImageSelector = findViewById(R.id.newPostImage)

        publishPostButton.setOnClickListener { uploadImage() }
        closePostPageButton.setOnClickListener {
            val closeIntent = Intent(this, MainActivity::class.java)
            startActivity(closeIntent)
            finish()
        }
        newPostImageSelector.setOnClickListener {
            getContent.launch("image/*")
        }
    }

    // Don't forget to implement your uploadImage() method!
    private fun uploadImage() {
        // Add your Firebase upload logic here using imageUri
    }
}

Key Takeaways

  • Always use the callback parameter provided by registerForActivityResult to get the result from child activities.
  • Handle null cases and result codes safely to avoid crashes.
  • Avoid spaces or special characters in file names when creating local files for image processing.

After making these changes, your cropped image should load correctly into the ImageView for preview. Good luck with your app development!

内容的提问来源于stack exchange,提问作者Adrian Njagi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:59:07