Team Project - Hikers

박재원·2024년 1월 4일
0

TIL

목록 보기
22/50
post-thumbnail
post-custom-banner

내일배움캠프를 시작하고 첫 팀프로젝트를 시작하게 됐다. 우리팀은 등산하는 사람들을 위한 커뮤니티 앱을 만들기로 하였다. 내가 맡은 역할은 메인페이지에서 프로필을 눌렀을 때 내 정보와 내가 올린 게시글, 좋아요를 누른 게시글을 출력하고 정보수정을 할 수 있게 구현하는 역할이다. 로그인 회원가입부터 메인페이지, 글쓰기 등 전체적인 코드를 올리고 싶지만 양이 많고 내가 구현에 참여하지 않은 내용들이 있어서 내가 맡은 액티비티만 올리겠다.

MyPage

package com.android.hikers

import android.content.ContentValues.TAG
import android.content.Intent
import android.os.Bundle
import android.text.method.ScrollingMovementMethod
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.HorizontalScrollView
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.core.view.setPadding
import com.android.hikers.data.PostManager
import com.android.hikers.data.UserManager
import com.google.android.material.chip.ChipGroup
import kotlin.math.log
import kotlin.math.min


class MyPage : AppCompatActivity() {

    private val back: ImageButton by lazy { findViewById(R.id.btn_back) }
    private val setting: Button by lazy { findViewById(R.id.btn_edit) }

    private val profilePhoto: ImageView by lazy { findViewById(R.id.img_profile) }
    private val name: TextView by lazy { findViewById(R.id.tv_name) }
    private val id: TextView by lazy { findViewById(R.id.tv_id) }
    private val info: TextView by lazy { findViewById(R.id.tv_myinfo) }
    private val more: TextView by lazy { findViewById(R.id.view_more) }

    private val myPostScrollView: HorizontalScrollView by lazy { findViewById(R.id.scrollview_my_post) }
    private val noWrittenPostTextView: TextView by lazy { findViewById(R.id.tv_no_my_post) }
    private val likedPostScrollView: HorizontalScrollView by lazy { findViewById(R.id.scrollview_my_like) }
    private val noLikedPostTextView: TextView by lazy { findViewById(R.id.tv_no_liked_post) }
    private val character1: TextView by lazy { findViewById(R.id.tv_character1) }
    private val character2: TextView by lazy { findViewById(R.id.tv_character2) }
    private val character3: TextView by lazy { findViewById(R.id.tv_character3) }


    private val userManager = UserManager.newInstance()
    private val postManager = PostManager.newInstance()

    //현재 로그인 한 유저의 아이디
    private val userID by lazy {
        intent.getStringExtra(EXTRA_ID) ?: "hong_gildong"
    }

    private val myPostItemList by lazy {
        listOf<ViewGroup>(
            findViewById(R.id.mypage_mypost1),
            findViewById(R.id.mypage_mypost2),
            findViewById(R.id.mypage_mypost3),
            findViewById(R.id.mypage_mypost4),
            findViewById(R.id.mypage_mypost5)
        )
    }
    private val likedPostItemList by lazy {
        listOf<ViewGroup>(
            findViewById(R.id.mypage_likepost1),
            findViewById(R.id.mypage_likepost2),
            findViewById(R.id.mypage_likepost3),
            findViewById(R.id.mypage_likepost4),
            findViewById(R.id.mypage_likepost5)
        )
    }

    private val myPostItemIDMap by lazy {
        mutableMapOf<Int, Int>(
            R.id.mypage_mypost1 to -1,
            R.id.mypage_mypost2 to -1,
            R.id.mypage_mypost3 to -1,
            R.id.mypage_mypost4 to -1,
            R.id.mypage_mypost5 to -1
        )
    }
    private val likedPostItemIDMap by lazy {
        mutableMapOf<Int, Int>(
            R.id.mypage_likepost1 to -1,
            R.id.mypage_likepost2 to -1,
            R.id.mypage_likepost3 to -1,
            R.id.mypage_likepost4 to -1,
            R.id.mypage_likepost5 to -1
        )
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_my_page)

        setViewMore(info, more)

        //프로필 정보 표시하기
        initProfile()

        //내가 작성한 게시물 목록 표시하기
        initMyPostScrollView()
        //내가 좋아한 게시물 목록 표시하기
        initLikedPostScrollView()

        //게시물 클릭 이벤트 처리하기
        initPostItem()

        goToMain()
        goToUserInfo()
    }

    override fun onResume() {
        super.onResume()

        //디테일 페이지에서 좋아요를 누르거나 취소한 뒤, 마이 페이지로 돌아왔을 때,
        //좋아요 여부를 반영하여 다시 UI 표시하기
        initProfile()
        initLikedPostScrollView()
    }

    private fun setViewMore(contentTextView: TextView, viewMoreTextView: TextView) {
        contentTextView.post {
            val lineCount = contentTextView.layout.lineCount
            if (lineCount > 0) {
                if (contentTextView.layout.getEllipsisCount(lineCount - 1) > 0) {
                    // 더보기 표시
                    viewMoreTextView.visibility = View.VISIBLE

                    // 더보기 클릭 이벤트
                    viewMoreTextView.setOnClickListener {
                        contentTextView.maxLines = Int.MAX_VALUE
                        viewMoreTextView.visibility = View.GONE
                        info.setMovementMethod(ScrollingMovementMethod())
                    }
                } else {
                    viewMoreTextView.visibility = View.GONE
                }
            }
        }
    }

    private fun initProfile() {
        val loginUser = userManager.findUserByID(userID)!!

        val userName = loginUser.name
        val userImage = loginUser.profileImage
        val userId = "@ " + loginUser.ID
        val userIntroduction = loginUser.introduction

        character1.isVisible = false
        character2.isVisible = false
        character3.isVisible = false

        if (loginUser.character.size != 0) {
            if (loginUser.character.size == 1) {
                character1.isVisible = true
                val userCharacter1 = loginUser.character[0]

                character1.text = userCharacter1
            } else if (loginUser.character.size == 2) {
                character1.isVisible = true
                character2.isVisible = true
                val userCharacter1 = loginUser.character[0]
                val userCharacter2 = loginUser.character[1]

                character1.text = userCharacter1
                character2.text = userCharacter2
            } else if (loginUser.character.size == 3) {
                character1.isVisible = true
                character2.isVisible = true
                character3.isVisible = true
                val userCharacter1 = loginUser.character[0]
                val userCharacter2 = loginUser.character[1]
                val userCharacter3 = loginUser.character[2]

                character1.text = userCharacter1
                character2.text = userCharacter2
                character3.text = userCharacter3
            }


        }


        name.text = userName
        id.text = userId
        //아직 소개가 없어서 주석 처리 함
        info.text = userIntroduction
        profilePhoto.run {
            if (userImage != null) setImageURI(userImage)
            else setImageResource(R.drawable.default_profile)
        }
        info.run {
            if (userIntroduction != null) text = userIntroduction
            else setText(R.string.introduction)
        }
    }


    private fun initMyPostScrollView() {
        val loginUser = userManager.findUserByID(userID)!!
        val myPostIDList = loginUser.writtenPostIDList

        if (myPostIDList.isEmpty()) {
            noWrittenPostTextView.isVisible = true
            myPostScrollView.isVisible = false
            return
        }

        noWrittenPostTextView.isVisible = false
        myPostScrollView.isVisible = true
        myPostItemList.forEach { it.isVisible = false }

        //내가 작성한 게시물 중 최근에 작성한 5개의 게시물만 표시하기
        for (index in 0 until min(5, myPostIDList.size)) {
            //표시할 게시물 ID
            val postID = myPostIDList[myPostIDList.size - 1 - index]
            //게시물이 표시될 postItem 레이아웃
            val postItem = myPostItemList[index]

            myPostItemIDMap[postItem.id] = postID
            setPostItemUI(postItem, postID)
        }
    }

    private fun initLikedPostScrollView() {
        val loginUser = userManager.findUserByID(userID)!!
        val likedPostIDList = loginUser.likedPostIDList

        Log.d(TAG, "userID: ${userID}, likedPostList: ")
        for (postID in likedPostIDList) {
            Log.d(TAG, "$postID")
        }

        if (likedPostIDList.isEmpty()) {
            noLikedPostTextView.isVisible = true
            likedPostScrollView.isVisible = false
            return
        }

        noLikedPostTextView.isVisible = false
        likedPostScrollView.isVisible = true
        likedPostItemList.forEach { it.isVisible = false }

        //내가 좋아한 게시물 중 최근에 작성한 5개의 게시물만 표시하기
        for (index in 0 until min(5, likedPostIDList.size)) {
            //표시할 게시물 ID
            val postID = likedPostIDList[likedPostIDList.size - 1 - index]
            //게시물이 표시될 postItem 레이아웃
            val postItem = likedPostItemList[index]

            likedPostItemIDMap[postItem.id] = postID
            setPostItemUI(postItem, postID)
        }
    }

    private fun setPostItemUI(postItem: ViewGroup, postID: Int) {
        postItem.isVisible = true

        val imageView = postItem.findViewById<ImageView>(R.id.pt_image)
        val titleText = postItem.findViewById<TextView>(R.id.tv_post_title)
        val nameText = postItem.findViewById<TextView>(R.id.tv_post_name)

        val post = postManager.findPostByID(postID)!!
        imageView.run {
            if (post.image != null) {
                try {
                    Log.d(TAG, "postID: ${post.postID}, post image is not null")
                    setImageURI(post.image)
                    scaleType = ImageView.ScaleType.CENTER_CROP
                    setPadding(0)
                } catch (e: Exception) {
                    Log.d(TAG, "게시물 이미지 접근 오류 발생!")
                    setImageResource(R.drawable.hikers_icon_small_grey)
                    scaleType = ImageView.ScaleType.CENTER_INSIDE
                    setPadding(20)
                }
            } else {
                Log.d(TAG, "postID: ${post.postID}, post image is null")
                setImageResource(R.drawable.hikers_icon_small_grey)
                scaleType = ImageView.ScaleType.CENTER_INSIDE
                setPadding(20)
            }
        }
        titleText.text = post.title
        nameText.text = userManager.findUserByID(post.writerId)!!.name
    }

    private fun initPostItem() {
        //내가 작성한 게시글
        for (postItem in myPostItemList) {
            //게시글 클릭 이벤트 처리하기
            postItem.setOnClickListener {
                val postID = myPostItemIDMap[postItem.id]!!
                Log.d(TAG, "post item clicked) post id: ${postID}")

                if (postID == -1) return@setOnClickListener

                goToDetail(postID)
            }
        }
        //내가 좋아요한 게시글
        for (postItem in likedPostItemList) {
            //게시글 클릭 이벤트 처리하기
            postItem.setOnClickListener {
                val postID = likedPostItemIDMap[postItem.id]!!
                Log.d(TAG, "post item clicked) post id: ${postID}")

                if (postID == -1) return@setOnClickListener

                goToDetail(postID)
            }
        }
    }

    private fun goToDetail(postID: Int) {
        //로그인한 회원 ID와 게시물 ID 전달하며, 디테일 화면으로 이동
        val detailIntent = Intent(this, DetailPageActivity::class.java).apply {
            putExtra("userID", userID)
            putExtra("postID", postID)
            //마이페이지에서 디테일 화면을 시작했음을 전달
            putExtra("activityName", "MyPage")
        }
        startActivity(detailIntent)
    }

    private fun goToMain() {
        back.setOnClickListener {
            //val intent = Intent(this, MainActivity::class.java)
            //startActivity(intent)
            finish()
        }
    }

    private fun goToUserInfo() {
        setting.setOnClickListener {
            Log.d(TAG, "edit info button clicked")
            val editIntent = Intent(this, UserInfoActivity::class.java).apply {
                putExtra(EXTRA_ID, userID)
            }
            startActivity(editIntent)
        }
    }
}

activity_my_page.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MyPage">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <ImageButton
        android:id="@+id/btn_back"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginStart="15dp"
        android:layout_marginTop="15dp"
        android:background="#00ff0000"
        android:padding="0sp"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_close"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_edit"
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:layout_marginTop="24dp"
        android:layout_marginEnd="24dp"
        android:background="#00ff0000"
        android:drawableLeft="@drawable/drawable_setting"
        android:drawablePadding="8dp"
        android:text="@string/edit_myinfo"
        android:textSize="10sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/img_profile"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginStart="32dp"
        android:layout_marginTop="10dp"
        android:src="@drawable/default_profile"
        android:transitionName="@string/trans_profile_image"
        app:civ_border_color="@color/black"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_back" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="150dp"
        android:layout_marginTop="15dp"
        android:text="@string/name"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_back" />

    <TextView
        android:id="@+id/tv_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="150dp"
        android:layout_marginTop="5dp"
        android:text="@string/id"
        android:textSize="10sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_name" />

    <TextView
        android:id="@+id/tv_myinfo"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginStart="150dp"
        android:layout_marginTop="5dp"
        android:layout_marginEnd="24dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:text="@string/introduction"
        android:textSize="15sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_id" />

    <TextView
        android:id="@+id/view_more"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="24dp"
        android:text="@string/more"
        android:visibility="visible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_myinfo" />
      
    <TextView
        android:id="@+id/tv_post"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="50dp"
        android:text="@string/record"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/img_profile"
        app:layout_constraintBottom_toTopOf="@id/scrollview_my_post"/>


    <TextView
        android:id="@+id/tv_no_my_post"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:layout_marginStart="24dp"
        android:layout_marginEnd="24dp"
        android:layout_marginTop="10dp"
        android:text="@string/no_written_posts"
        android:gravity="center"
        android:visibility="invisible"
        tools:visibility="visible"
        app:layout_constraintTop_toBottomOf="@id/tv_post"
        />

    <HorizontalScrollView
        android:id="@+id/scrollview_my_post"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="24dp"
        app:layout_constraintTop_toBottomOf="@+id/tv_post">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <LinearLayout
                android:id="@+id/mypage_mypost1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/mypage_mypost2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />

            </LinearLayout>

            <LinearLayout
                android:id="@+id/mypage_mypost3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/mypage_mypost4"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/mypage_mypost5"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>

        </LinearLayout>

    </HorizontalScrollView>

    <TextView
        android:id="@+id/tv_like"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:text="@string/like"
        android:textSize="20sp"
        android:textStyle="bold"
        android:layout_marginTop="210dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_post" />

    <TextView
        android:id="@+id/tv_no_liked_post"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="24dp"
        android:text="@string/no_liked_posts"
        android:gravity="center"
        android:visibility="invisible"
        tools:visibility="visible"
        app:layout_constraintTop_toBottomOf="@id/tv_like"
        />

    <HorizontalScrollView
        android:id="@+id/scrollview_my_like"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:layout_marginLeft="24dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="24dp"
        app:layout_constraintTop_toBottomOf="@+id/tv_like">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <LinearLayout
                android:id="@+id/mypage_likepost1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/mypage_likepost2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/mypage_likepost3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/mypage_likepost4"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/mypage_likepost5"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <include layout="@layout/mypage_post_layout" />
            </LinearLayout>


        </LinearLayout>

    </HorizontalScrollView>

    <TextView
        android:id="@+id/tv_character1"
        android:layout_width="40dp"
        android:layout_height="20dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="5dp"
        android:text="@string/keyword"
        android:textSize="12sp"
        android:textColor="#39B54A"
        android:gravity="center"
        android:background="@drawable/tag_layout"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/img_profile" />

    <TextView
        android:id="@+id/tv_character2"
        android:layout_width="40dp"
        android:layout_height="20dp"
        android:layout_marginStart="12dp"
        android:layout_marginTop="5dp"
        android:text="@string/keyword"
        android:textSize="12sp"
        android:textColor="#39B54A"
        android:gravity="center"
        android:background="@drawable/tag_layout"
        app:layout_constraintStart_toEndOf="@+id/tv_character1"
        app:layout_constraintTop_toBottomOf="@+id/img_profile" />

    <TextView
        android:id="@+id/tv_character3"
        android:layout_width="40dp"
        android:layout_height="20dp"
        android:layout_marginStart="12dp"
        android:layout_marginTop="5dp"
        android:text="@string/keyword"
        android:textSize="12sp"
        android:textColor="#39B54A"
        android:gravity="center"
        android:background="@drawable/tag_layout"
        app:layout_constraintStart_toEndOf="@+id/tv_character2"
        app:layout_constraintTop_toBottomOf="@+id/img_profile" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

mypage_post_layout.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/view_post"
        android:layout_width="120dp"
        android:layout_height="180dp"
        android:layout_marginRight="30dp"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/pt_image"
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:src="@drawable/hikers_icon_small_grey"
            android:scaleType="centerInside"
            android:padding="20dp"
            android:background="@color/light_grey"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/pt_image">

            <TextView
                android:id="@+id/tv_post_title"
                android:layout_width="100dp"
                android:layout_height="wrap_content"
                android:layout_marginBottom="5dp"
                android:ellipsize="end"
                android:maxLines="1"
                android:text="@string/post_title"
                android:textSize="15sp"
                android:textStyle="bold"
                tools:layout_editor_absoluteX="36dp"
                tools:layout_editor_absoluteY="180dp" />

            <TextView
                android:id="@+id/tv_post_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="5dp"
                android:text="@string/post_writer_name"
                android:textColor="#6E6E6E"
                android:textSize="10sp"
                tools:layout_editor_absoluteX="36dp"
                tools:layout_editor_absoluteY="180dp" />


        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

</merge>
post-custom-banner

0개의 댓글