好的,我們會發現,有時候我們傳送的照片檔案太大,以及有可能我們拍完美美的照片時,卻發現我們竟然不在中心點!! 太難過了,那這時候我們可能就會需要裁切,哭了 裁切感覺有點困難,沒關係! 我們這邊有第三方套件!!!
ImagePicker 提供我們很多方便的東西,如
ImagePicker.with(this)
.crop() //Crop image and let user choose aspect ratio.
.start()
ImagePicker.with(this)
.compress(1024) //Final image size will be less than 1 MB
.start()
ImagePicker.with(this)
.maxResultSize(620, 620) //Final image resolution will be less than 620 x 620
.start()
ImagePicker.with(this)
.galleryOnly() //User can only select image from Gallery
.cameraOnly() //User can only capture image using Camera
.start() //Default Request Code is ImagePicker.REQUEST_CODE
ImagePicker.with(this)
.galleryMimeTypes( //Exclude gif images
mimeTypes = arrayOf(
"image/png",
"image/jpg",
"image/jpeg"
)
)
.start()
這些都有寫在https://github.com/Dhaval2404/ImagePicker
有興趣的小夥伴們可以看看喔!
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
implementation 'com.github.dhaval2404:imagepicker:2.1'
一樣,我們先顯示後,等到user按下修改的時候我們才上傳我們的照片+修改profile的資料
//讓我們存uri
var selectedUri: Uri? = null
private val startForProfileImageResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
result: ActivityResult ->
val resultCode = result.resultCode
val data = result.data
if (resultCode == Activity.RESULT_OK){
val fileUri = data?.data
if (fileUri != null) {
Constant.loadUserImage(fileUri,binding.ivEditProfileImage)
selectedUri = fileUri
}
}
}
我們只需要裁減+壓縮就好啦!
if(ContextCompat.checkSelfPermission(requireActivity(),android.Manifest.permission.READ_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED){
ImagePicker.with(this)
//裁減
.crop()
//壓縮 KB為單位
.compress(1024)
//畫素
.maxResultSize(1080,1080)
.createIntent{intent->
startForProfileImageResult.launch(intent)
}
}
跟前面提到的一樣,我們把這邊修改成只呼叫saveImageToFireStorage(),而當今天save成功的時候,我們再update整筆資料,我們把原本的
//把這邊刪掉,因為我們現在拿到的還只是fileUri,我們要把它傳到storage
mHashMap[Constant.IMAGE] = selectedUri
再新增以下這個!
selectedUri?.let { accountViewModel.saveImageToFireStorage(mHashMap, it) }
好的,這邊我們也一樣,我們不再把fragment傳進去啦! 我們只傳數據+透過livedata來跟UI溝通,一樣,我們只用失敗,因為成功它就會進到updateUserDetailToFireStore這個funtion啦! 且我們要記得要把Uri轉成String (否則沒辦法上傳到Firestore)
private val _updateUserDetailFail = MutableLiveData<String>()
val updateUserDetailFail: LiveData<String>
get() = _updateUserDetailFail
fun saveImageToFireStorage(mHashMap: HashMap<String,Any>,uri: Uri){
val sdf: StorageReference = FirebaseStorage.getInstance().reference.child(Constant.USER_IMAGE + "_" + System.currentTimeMillis())
sdf.putFile(uri)
.addOnSuccessListener {
it.metadata?.reference?.downloadUrl
?.addOnSuccessListener {
//要再這邊把uri改成String
mHashMap[Constant.IMAGE] = it.toString()
updateUserDetailToFireStore(mHashMap)
}
?.addOnFailureListener {
_updateUserDetailFail.postValue(it.toString())
}
}
.addOnFailureListener {
_updateUserDetailFail.postValue(it.toString())
}
}
//當然還需要reset我們的資料啦!
fun resetUpdateFail(){
_updateUserDetailFail.postValue(null)
}
★我們這邊偷懶,原本應該要兩個功能各都有自己的livedata,但是這邊懶了,就先沒加
基本上就是修改成透過livedata
//成功之後的livedata
private val _updateUserDetailSuccessful = MutableLiveData<Boolean>()
val updateUserDetailSuccessful: LiveData<Boolean>
get() = _updateUserDetailSuccessful
fun updateUserDetailToFireStore(mHashMap: HashMap<String,Any>){
getCurrentUID()?.let{
FirebaseFirestore.getInstance().collection(Constant.USER)
.document(it)
.update(mHashMap)
.addOnSuccessListener{
_updateUserDetailSuccessful.postValue(true)
}
.addOnFailureListener{
_updateUserDetailFail.postValue(it.toString())
}
}
}
//這邊一樣要新增我們的reset啦!
fun resetUpdateSuccessful(){
_updateUserDetailSuccessful.postValue(null)
}
在fragment新增以下
accountViewModel.updateUserDetailSuccessful.observe(viewLifecycleOwner, Observer {
if (it == true){
showSnackBar(resources.getString(R.string.update_user_profile_successful),false)
hideDialog()
accountViewModel.getUserDetail()
accountViewModel.resetUpdateSuccessful()
}
})
accountViewModel.updateUserDetailFail.observe(viewLifecycleOwner, Observer {
hideDialog()
showSnackBar(it,true)
accountViewModel.resetUpdateFail()
})
大功告成啦!!