관리 메뉴

hyeals study

인스타그램 클론 (사용자 페이지3) 본문

안드로이드

인스타그램 클론 (사용자 페이지3)

hyeals 2020. 4. 10. 18:26

- 유저 페이지에서 프로필 사진 변경 기능 추가, 팔로우&팔로윙 카운트 기능

 

<유저 페이지 프로필 사진 변경 기능>

 

[1] UserFragment.kt에 버튼 이벤트 추가

fragmentView?.account_iv_profile?.setOnClickListener {

                //앨범 오픈
                var photoPickerIntent = Intent(Intent.ACTION_PICK)
                photoPickerIntent.type = "image/*"
                activity?.startActivityForResult(photoPickerIntent, PICK_PROFILE_FROM_ALBUM)
        }

* 여기서 PICK_PROFILE_FROM_ALBUM을 아래와 같이 선언 (static으로 선언하는 것이라고 생각하면 됨)

companion object{
        var PICK_PROFILE_FROM_ALBUM = 10
    }

[2] MainActivity.kt로 이동해서 onActivityResult메소드를 아래와 같이 만듦

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

        super.onActivityResult(requestCode, resultCode, data)

        // 앨범에서 Profile Image 사진 선택시 호출 되는 부분
        if (requestCode == UserFragment.PICK_PROFILE_FROM_ALBUM && resultCode == Activity.RESULT_OK) {

            var imageUri = data?.data
            var uid = FirebaseAuth.getInstance().currentUser!!.uid //파일 업로드
            var storageRef = FirebaseStorage.getInstance().reference.child("userProfileImages").child(uid!!)

            //사진을 업로드 하는 부분  userProfileImages 폴더에 uid에 파일을 업로드함
            storageRef.putFile(imageUri!!).continueWithTask { task: com.google.android.gms.tasks.Task<UploadTask.TaskSnapshot> ->
                return@continueWithTask storageRef.downloadUrl
            }.addOnSuccessListener { uri ->
                var map = HashMap<String,Any>()
                map["image"] = uri.toString()
                FirebaseFirestore.getInstance().collection("profileImages").document(uid).set(map)
            }

        }

    }

 

[ 코드 설명 ]

 

 

- requestCode[1]에서 만든 UserFragment.kt안에 있는 PICK_PROFILE_FROM_ALBUM이고, resultCodeOK일 경우 처리해주는 부분 (= 사진을 선택했을 경우 처리하는 부분)


 

- userProfileImages: 이미지를 저장할 폴더 명

- uid: 파일 명


 

- 이미지 다운로드 주소를 받아오기 위해서 continueWithTask를 사용

- continueWithTask의 리턴 값 addOnSuccessListener로 넘어옴

 

- 이 값HashMap에 담아줌

- map["image"]부분: 이미지 주소값을 담음


[3] UserFragment.kt로 이동해서 프로필 이미지를 다운로드하는 기능을 추가함

 

- getProfileImage라는 메소드를 만듦

 

fun getProfileImage() {
        firestore?.collection("profileImages")?.document(uid!!)?.addSnapshotListener { documentSnapshot, firebaseFirestoreException ->
                if (documentSnapshot == null) return@addSnapshotListener
                if (documentSnapshot?.data != null) {
                    val url = documentSnapshot?.data!!["image"]
                    Glide.with(activity!!).load(url).apply(RequestOptions().circleCrop()).into(fragmentView!!.account_iv_profile)
                }
            }
    }

 

- firestore에서 profileImages라는 컬렉션으로부터 내 uiddocument를 읽어옴

- 프로필 사진이 실시간으로 변하는 것을 받아오기 위해서 Snapshot이용

 

- Glide이미지를 다운로드 받아옴

- circleCrop: 이미지를 원형(circle)으로 받아오기 위함


[4] 프로젝트를 실행해서 유저 페이지 선택 → 프로필 이미지를 눌러 프로필 사진을 변경하면 아래와 같이 firebase에 값이 저장됨

 

프로필 이미지 변경

 

profileImags 컬렉션


< 팔로우, 팔로윙 카운트 기능>

 

[5] model 패키지에 FollowDTO라는 데이터 모델을 만듦 (코틀린 파일)

 

data class FollowDTO(

    var followerCount: Int = 0,
    var followers: MutableMap<String, Boolean> = HashMap(),

    var followingCount: Int = 0,
    var followings: MutableMap<String, Boolean> = HashMap()
)

 

- followerCount: 팔로워의 수

- followers: 팔로워 하는 유저들 (중복 팔로워를 방지하기 위함)

 

- followingCount: 팔로윙의 수

- followings: 팔로윙 하는 유저들 (중복 팔로윙을 방지하기 위함)


[6] UserFragment.kt로 이동해서 requestFollow라는 메소드를 만듦

 

◎ 이 메소드에는 두 가지 기능이 있음

  1. 내 계정이 누구를 팔로우하는지
  2. 상대방 계정에는 누가 팔로우를 하는지

 

fun requestFollow() {

        // Save data to my account

        var tsDocFollowing = firestore!!.collection("users").document(currentUserUid!!)
        firestore?.runTransaction { transaction ->

            var followDTO = transaction.get(tsDocFollowing!!).toObject(FollowDTO::class.java)
            if (followDTO == null) {

                followDTO = FollowDTO()
                followDTO.followingCount = 1
                followDTO.followings[uid!!] = true

                transaction.set(tsDocFollowing, followDTO)
                return@runTransaction

            }


            if (followDTO?.followings?.containsKey(uid)!!) {
                // It remove following third person when a third person follow me
                followDTO?.followingCount = followDTO?.followingCount - 1
                followDTO?.followings.remove(uid)
            } else {
                // It remove following third person when a third person not follow me
                followDTO?.followingCount = followDTO?.followingCount + 1
                followDTO?.followings[uid!!] = true
            }
            transaction.set(tsDocFollowing, followDTO)
            return@runTransaction
        }

        // Save data to third person
        var tsDocFollower = firestore!!.collection("users").document(uid!!)
        firestore?.runTransaction { transaction ->

            var followDTO = transaction.get(tsDocFollower!!).toObject(FollowDTO::class.java)
            if (followDTO == null) {

                followDTO = FollowDTO()
                followDTO!!.followerCount = 1
                followDTO!!.followers[currentUserUid!!] = true

                transaction.set(tsDocFollower, followDTO!!)
                return@runTransaction
            }

            if (followDTO!!.followers.containsKey(currentUserUid!!)) {
                // It cancel my follower when I follow a third person
                followDTO!!.followerCount = followDTO!!.followerCount - 1
                followDTO!!.followers.remove(currentUserUid!!)
            } else {
                // It cancel my follower when I don't follow a third person
                followDTO!!.followerCount = followDTO!!.followerCount + 1
                followDTO!!.followers[currentUserUid!!] = true

            }
            transaction.set(tsDocFollower, followDTO!!)
            return@runTransaction
        }

    }

 

[ 코드 설명 ]

 

- 내 계정이 누군가를 팔로우하는 과정이 담긴 트랜젝션을 만듦

 

 

- followDTO에 아무 값이 없을 때 처리하는 부분

 

- 여기서 uid상대방의 uid. (중복 팔로윙을 방지하기 위함)

 

- transaction.set(tsDocFollowing, followDTO): 데이터가 데이터 베이스에 담기게 됨.


 

- if식: 내가 이미 상대방을 팔로윙하고 있는 경우 (여기서 uid값은 상대방 uid)

 

- else: 내가 상대방을 팔로윙하고 있지 않는 경우

 


[7] UserFragment.kt의 OncreatView에 아래와 같은 버튼 클릭 이벤트를 만들어줌

 


[8] UserFragment.kt에 getFollowerAndFollowing 메소드를 만듦

fun getFolloerAndFollowing(){
        firestore?.collection("users")?.document(uid!!)?.addSnapshotListener { documentSnapshot, firebaseFirestoreException ->
            if (documentSnapshot==null) return@addSnapshotListener

            var followDTO = documentSnapshot.toObject(FollowDTO::class.java)

            if(followDTO?.followingCount != null){
                fragmentView?.account_tv_following_count?.text = followDTO?.followingCount?.toString()
            }
            if(followDTO?.followerCount != null){
                fragmentView?.account_tv_follower_count?.text = followDTO?.followerCount?.toString()

                if(followDTO?.followers?.containsKey(currentUserUid!!)) {
                    fragmentView?.account_btn_follow_signout?.text = getString(R.string.follow_cancel)
                    fragmentView?.account_btn_follow_signout?.background?.setColorFilter(ContextCompat.getColor(activity!!,R.color.colorLightGray),PorterDuff.Mode.MULTIPLY)
                }else{
                    if (uid != currentUserUid) {
                        fragmentView?.account_btn_follow_signout?.text = getString(R.string.follow)
                        fragmentView?.account_btn_follow_signout?.background?.colorFilter = null
                    }
                }
            }
        }
    }

 

[ 코드 설명 ] 

 

- 여기서 uid는 내 페이지를 클릭했을 때는 내 uid값이고, 상대방 페이지를 클릭했을 때는 상대방 uid값임.

 

- 스냅샷을 이용해서 값을 실시간으로 불러옴


 

[9] UserFragment.kt의 OncreateView메소드에 아래와 같이 getFollowerAndFollowing메소드를 넣어줌

 


[10] 프로젝트를 실행해보면 아래와 같이 팔로우 하기 전과 후의 차이를 볼 수 있음 

 

팔로우 하기 전 상대방 계정

 

팔로우 한 후 상대방 계정

 

팔로우 한 후 내 계정

 

 

 

Comments