연습장/실습

4주차_ SNS 앱 4. TextView 더보기 기능

아이른 2024. 4. 8. 12:22

문제 5. 마이 페이지( MyageActivity )

  • 사용자가 메인 페이지에서 선택한 아이템의 상세 정보를 제공하는 페이지입니다.
  • 상세 정보를 구조화된 형태로 표시하기 위해 **ConstraintLayout**을 활용하세요.
  • 메인 페이지에서 상세 페이지를 생성할 때 필요한 data를 Intent로 전달해 보세요.
  • 사용자와 상호작용을 위한 버튼이나 링크를 포함하여 다양한 기능을 제공해보세요.

문제 5-1. 구현

  • MainAvtivity 포스트를 클릭하였을 때, 관련 세부 내용을 받음
  • 메모 부분에 더보기 기능 추가

1. xml

 

Android studio_ 0-2. CardView & CircleImageView

CardView 플랫폼 전체에 일관성 있는 모양을 카드의 내부에 정보 및 스타일을 쉽게 표시 FrameLayout 형태를 띄기 때문에 배열 방식이 달라 레이아웃을 하나 더 넣어서 작성 app:cardElevation="15dp" : 카드

hyelan-note.tistory.com

 

더보기

acticity_detail.xml

<?xml version="1.0" encoding="utf-8"?>


<androidx.constraintlayout.widget.ConstraintLayout 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">

    <View
        android:id="@+id/viewTop"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:background="@color/white"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/setMainButton"
        android:layout_width="40dp"
        android:layout_height="50dp"
        android:layout_marginStart="10dp"
        android:layout_marginTop="5dp"
        android:src="@drawable/btn_back"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/setUserimage"
        android:layout_width="83dp"
        android:layout_height="97dp"
        android:layout_marginStart="10dp"
        android:layout_marginTop="15dp"
        app:layout_constraintStart_toStartOf="@id/viewTop"
        app:layout_constraintTop_toBottomOf="@id/toolbar"
        tools:src="@drawable/iupp"
        app:civ_border_width="4dp"
        app:civ_border_color="@color/purple_100"/>

    <TextView
        android:id="@+id/setUserId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="20dp"
        app:layout_constraintStart_toEndOf="@id/setUserimage"
        app:layout_constraintTop_toBottomOf="@id/toolbar"
        tools:text="아이디"/>

    <TextView
        android:id="@+id/setUserName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        app:layout_constraintStart_toStartOf="@id/setUserId"
        app:layout_constraintTop_toBottomOf="@id/setUserId"
        tools:text="이름"/>

    <TextView
        android:id="@+id/memo"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        app:layout_constraintStart_toStartOf="@id/setUserName"
        app:layout_constraintTop_toBottomOf="@id/setUserName"
        tools:text="메모"
        />

    <androidx.cardview.widget.CardView
        android:id="@+id/viewon"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="10dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="20dp"
        android:background="@color/white"
        app:cardCornerRadius="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/memo"
        app:cardElevation="15dp" >

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

            <TextView
                android:id="@+id/title"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:layout_marginHorizontal="25dp"
                android:textSize="28sp"
                app:layout_constraintBottom_toTopOf="@id/setStory"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:text="타이틀"/>

            <ImageView
                android:id="@+id/setStory"
                android:layout_width="365dp"
                android:layout_height="223dp"
                android:layout_marginTop="20dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/title"
                tools:src="@drawable/iust" />

            <TextView
                android:id="@+id/userStory"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="5dp"
                android:layout_marginTop="40dp"
                android:textSize="18sp"
                app:layout_constraintStart_toStartOf="@id/setStory"
                app:layout_constraintEnd_toEndOf="@id/setStory"
                app:layout_constraintTop_toBottomOf="@id/setStory"
                tools:text="뭐가들어올지 몰라도 뭐가 들어오긴 할것임"/>

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
    
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

2. DetailActivity

① data class 값 받기

//MainActivity.kt : 값 전달
startActivity(Intent(this, DetailActivity::class.java).apply {
   putExtra(USER_DATA, writer)
   putExtra(POST_DATA, post)
  }
)


//DetailActivity.kt : 값 받기
val user = intent.getSerializableExtra(MainActivity.USER_DATA) as User
val post = intent.getSerializableExtra(MainActivity.POST_DATA) as Post

 

② View에 송출하기

val userimage = findViewById<ImageView>(R.id.setUserimage)
val userid = findViewById<TextView>(R.id.setUserId)
val username = findViewById<TextView>(R.id.setUserName)
val storyImage = findViewById<ImageView>(R.id.setStory)
val userstory = findViewById<TextView>(R.id.userStory)
val storytitle = findViewById<TextView>(R.id.title)
val usermemo = findViewById<TextView>(R.id.memo)

storyImage.setImageResource(post.imageId)
userimage.setImageResource(user.profileImageId)
username.setText(user.name)
userid.setText(user.userId)
userstory.setText(post.content)
storytitle.setText(post.title)
usermemo.setText(user.memo)

 

③ 뒤로가기 버튼 처리

val backButton = findViewById<ImageView>(R.id.setMainButton)

    backButton.setOnClickListener {
    finish()
}

 

④ 더보기 기능

  • View.post() : 안드로이드에서 UI 작업을 뷰가 다음에 그려질 때까지 지연시키기 위해 사용
    • 전달된 Runnable 객체가 UI 스레드(메인 스레드)의 메시지 큐에 포함되어, 현재 진행 중인 모든 레이아웃 계산, 측정, 그리기 작업이 완료된 후에 실행
    • 뷰와 관련된 변경 사항이 안전하게 처리되고, 뷰가 완전히 그려진 상태에서 코드를 실행할 수 있음
    • [Kotlin] TextView의 더보기 기능 구현 (tistory.com)

var isExpanded = false

    usermemo.post {//더보기 텍스트 표시
    if (usermemo.layout.lineCount >= 3) {
        moreMemo.visibility = View.VISIBLE
    }//visibility : 뷰의 속성 값 = View.VISIBLE : 뷰를 보여줄지 결정
}

    moreMemo.setOnClickListener {//더보기 클릭 이벤트
    
    if (isExpanded) {//접기
        isExpanded = false
        usermemo.maxLines = 2 //maxLines을 2로 지정하면 접는 효과과 같음
    } else {//펴저서 텍스트 전부 노출
        isExpanded = true
        usermemo.maxLines = Int.MAX_VALUE //maxLines을 무한대로 설정하면 텍스트가 모두 보여짐
    }
}

 

⑤ DetailActivity.kt

class DetailActivity : AppCompatActivity() {

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

        val backButton = findViewById<ImageView>(R.id.setMainButton)
        val userimage = findViewById<ImageView>(R.id.setUserimage)
        val userid = findViewById<TextView>(R.id.setUserId)
        val username = findViewById<TextView>(R.id.setUserName)
        val storyImage = findViewById<ImageView>(R.id.setStory)
        val userstory = findViewById<TextView>(R.id.userStory)
        val storytitle = findViewById<TextView>(R.id.title)
        val usermemo = findViewById<TextView>(R.id.memo)
        val moreMemo = findViewById<TextView>(R.id.showMore)
        var isExpanded = false

        val user = intent.getSerializableExtra(MainActivity.USER_DATA) as User
        val post = intent.getSerializableExtra(MainActivity.POST_DATA) as Post

        usermemo.post {
            if (usermemo.layout.lineCount >= 3) {
                moreMemo.visibility = View.VISIBLE
            }
        }

        storyImage.setImageResource(post.imageId)
        userimage.setImageResource(user.profileImageId)
        username.setText(user.name)
        userid.setText(user.userId)
        userstory.setText(post.content)
        storytitle.setText(post.title)
        usermemo.setText(user.memo)

        backButton.setOnClickListener {
            finish())
        }
        
        moreMemo.setOnClickListener {

            if (isExpanded) {
                isExpanded = false
                usermemo.maxLines = 2
            } else {
                isExpanded = true
                usermemo.maxLines = Int.MAX_VALUE
            }
        }
    }
}

동작 화면

더보기 더보기 펼치기