【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


<<:  完赛

>>:  JavaScript Day29 - other

[Day 13] Reactive Programming - Reactor(Processors & Sinks)

前言 这个主题花了我好多的时间查资料,之前提到动态的产生publisher其实就有sink的概念,但...

[Day-15] for回圈

今天也是要练习回圈 但不是while而是for回圈 while以及for两者都是回圈 其实功能基本上...

EP 9: Navigation by Shell in TopStore App

Hello, 各位 iT邦帮忙 的粉丝们大家好~~~ 本篇是 Re: 从零开始用 Xamarin 技...

原来产品也有自己的生命历程 Product Life Cycle

有些人可能以为在完成开发後,把产品交付给用户,只要有持续的做迭代与优化,产品的使用用户就会越来越多,...

Day15 javascript 对象介绍

今天咱们要来谈的是JavaScript 对象,JavaScript 中的所有事物都是物件:不论是字串...