fix(이미지 선택): 이미지 선택 및 크롭 로직 수정

This commit is contained in:
2025-09-18 00:17:20 +09:00
parent 02155065f7
commit d22907c7d5
16 changed files with 397 additions and 571 deletions

View File

@@ -1,21 +1,23 @@
package kr.co.vividnext.sodalive.mypage.profile
import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import android.view.View
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import coil.load
import coil.transform.CircleCropTransformation
import com.github.dhaval2404.imagepicker.ImagePicker
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.bumptech.glide.request.RequestOptions
import com.jakewharton.rxbinding4.widget.textChanges
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.base.BaseActivity
import kr.co.vividnext.sodalive.common.ImagePickerCropper
import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.RealPathUtil
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.databinding.ActivityProfileUpdateBinding
import kr.co.vividnext.sodalive.databinding.ItemLiveTagSelectedBinding
@@ -33,27 +35,6 @@ class ProfileUpdateActivity : BaseActivity<ActivityProfileUpdateBinding>(
private val viewModel: ProfileUpdateViewModel by inject()
private val imageResult =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val resultCode = result.resultCode
val data = result.data
if (resultCode == RESULT_OK) {
// Image Uri will not be null for RESULT_OK
val fileUri = data?.data!!
binding.ivProfile.background = null
viewModel.updateProfileImage(fileUri) {
SharedPreferenceManager.profileImage = it
binding.ivProfile.load(it) {
crossfade(true)
transformations(CircleCropTransformation())
}
}
} else if (resultCode == ImagePicker.RESULT_ERROR) {
Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
}
}
private val tagFragment: MemberTagFragment by lazy {
MemberTagFragment(viewModel.tags) { tag, isChecked ->
when {
@@ -76,22 +57,23 @@ class ProfileUpdateActivity : BaseActivity<ActivityProfileUpdateBinding>(
private lateinit var loadingDialog: LoadingDialog
private lateinit var cropper: ImagePickerCropper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.getRealPathFromURI = {
RealPathUtil.getRealPath(applicationContext, it)
}
bindData()
}
override fun onStart() {
super.onStart()
viewModel.getUserInfo()
}
override fun onDestroy() {
cropper.cleanup()
super.onDestroy()
}
private fun bindData() {
compositeDisposable.add(
binding.etBlog.textChanges().skip(1)
@@ -220,6 +202,34 @@ class ProfileUpdateActivity : BaseActivity<ActivityProfileUpdateBinding>(
loadingDialog = LoadingDialog(this, layoutInflater)
cropper = ImagePickerCropper(
caller = this,
context = this,
isEnabledFreeStyleCrop = false,
config = ImagePickerCropper.Config(
aspectX = 1f, aspectY = 1f,
compressFormat = Bitmap.CompressFormat.JPEG,
compressQuality = 90
),
onSuccess = { file, _ ->
binding.ivProfile.background = null
viewModel.updateProfileImage(file) {
SharedPreferenceManager.profileImage = it
Glide.with(this)
.load(it)
.placeholder(R.drawable.ic_place_holder)
.apply(
RequestOptions()
.transform(CircleCrop())
)
.into(binding.ivProfile)
}
},
onError = { e ->
Toast.makeText(this, "${e.message}", Toast.LENGTH_SHORT).show()
}
)
compositeDisposable.add(
binding.etIntroduce.textChanges()
.debounce(500, TimeUnit.MILLISECONDS)
@@ -241,19 +251,7 @@ class ProfileUpdateActivity : BaseActivity<ActivityProfileUpdateBinding>(
viewModel.changeGender(Gender.NONE)
}
binding.ivPhotoPicker.setOnClickListener {
ImagePicker.with(this)
.crop()
.galleryOnly()
.galleryMimeTypes( // Exclude gif images
mimeTypes = arrayOf(
"image/png",
"image/jpg",
"image/jpeg"
)
)
.createIntent { imageResult.launch(it) }
}
binding.ivPhotoPicker.setOnClickListener { cropper.launch() }
binding.tvSelectTag.setOnClickListener {
if (tagFragment.isAdded) return@setOnClickListener

View File

@@ -1,6 +1,5 @@
package kr.co.vividnext.sodalive.mypage.profile
import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.orhanobut.logger.Logger
@@ -53,8 +52,6 @@ class ProfileUpdateViewModel(private val repository: UserRepository) : BaseViewM
val isLoading: LiveData<Boolean>
get() = _isLoading
lateinit var getRealPathFromURI: (Uri) -> String?
fun getUserInfo() {
compositeDisposable.add(
repository.getProfile("Bearer ${SharedPreferenceManager.token}")
@@ -90,8 +87,7 @@ class ProfileUpdateViewModel(private val repository: UserRepository) : BaseViewM
_genderLiveData.postValue(gender)
}
fun updateProfileImage(uri: Uri, onSuccess: (String) -> Unit) {
val file = File(getRealPathFromURI(uri))
fun updateProfileImage(file: File, onSuccess: (String) -> Unit) {
val image = MultipartBody.Part.createFormData(
"image",
file.name,