iT邦幫忙

2021 iThome 鐵人賽

DAY 29
0
Mobile Development

30天建立寵物約散App-Android新手篇系列 第 29

【day29】修改ProfileFragment X (第三方套件)ImagePicker

好的,我們會發現,有時候我們傳送的照片檔案太大,以及有可能我們拍完美美的照片時,卻發現我們竟然不在中心點!! 太難過了,那這時候我們可能就會需要裁切,哭了 裁切感覺有點困難,沒關係! 我們這邊有第三方套件!!!

前言

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()
  • 預設可讓人挑選相簿/拍照 (當然你也可以讓user只選擇相簿or拍照)
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
  • 限制挑選的圖片type
ImagePicker.with(this)
    .galleryMimeTypes(  //Exclude gif images
        mimeTypes = arrayOf(
          "image/png",
          "image/jpg",
          "image/jpeg"
        )
      )
    .start()

這些都有寫在https://github.com/Dhaval2404/ImagePicker

有興趣的小夥伴們可以看看喔!

1.首先我們要新增

allprojects {
   repositories {
       	maven { url "https://jitpack.io" }
   }
}

implementation 'com.github.dhaval2404:imagepicker:2.1'

2.修改我們的resultLauncher

一樣,我們先顯示後,等到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   
         }
        }
    }

3.修改 checkPermission()

我們只需要裁減+壓縮就好啦!

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)
	}
}

4.修改onClick事件

跟前面提到的一樣,我們把這邊修改成只呼叫saveImageToFireStorage(),而當今天save成功的時候,我們再update整筆資料,我們把原本的

//把這邊刪掉,因為我們現在拿到的還只是fileUri,我們要把它傳到storage
mHashMap[Constant.IMAGE] = selectedUri

再新增以下這個!


selectedUri?.let { accountViewModel.saveImageToFireStorage(mHashMap, it) }

5.修改saveImageToStorage

好的,這邊我們也一樣,我們不再把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,但是這邊懶了,就先沒加

6.修改updateUserDetailToFireStore()

基本上就是修改成透過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)
    }

7.在UI觀察

在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()
        })

大功告成啦!!

day29.finished


上一篇
【day28】寵物邀約上傳流程修改 X ViewPager2 with indicator
下一篇
【day30】chatRoom修改畫面 X 動態修正layout
系列文
30天建立寵物約散App-Android新手篇30

尚未有邦友留言

立即登入留言