EMDI는 지금도 개발중

Android with Kotlin : 안드로이드 기초편 - ListView 기초 리스트뷰 클릭 시 상세화면 이동 본문

네이티브/Android

Android with Kotlin : 안드로이드 기초편 - ListView 기초 리스트뷰 클릭 시 상세화면 이동

EMDI 2020. 9. 21. 13:12

저번 글에서는 ListView를 생성 및 데이터를 출력하는 것까지 배워보았습니다. 이번 글에서는 리스트뷰 중 내가 원하는 리스트를 선택했을 때 상세화면으로 이동하는 방법 및 데이터 출력을 배워보도록 하겠습니다.

* 연습내용 : 직방 목록화면에서 리스트를 하나 클릭 시 해당 목록에 대한 상세화면으로 이동 및 데이터 출력을 연습할 계획입니다. - 프로젝트명 : Review_ListView

 

순서 위치 프로세스
1 java > RoomDetailActivity 생성
res > layout > activity_room_detail.xml 생성
리스트를 클릭했을 때 넘어갈 상세화면 부분
▶ 오른쪽 버튼 Activity 생성하면 자동으로 xml도 생성
※ 역할 : 상세화면(디자인)
2 res > layout > activity_room_detail.xml ▶ activity_main.xml에서 한 것과 비슷하게 상세화면에 뿌려줄 디자인 구성
※ 역할 : 상세화면(디자인)
3 java > MainActivity 리스트 클릭 이벤트를 넣는 작업
▶ setupEvents() 함수 안에 리스트뷰 클릭이벤트를 넣기
※ 역할 : 상세화면으로 이동할 이벤트를 설정(소스)
4 java > datas > Room 리스트 클릭 이벤트에서 담은 정보를 사용할 수 있게 작업
▶ putExtra에서 ArrayList<Room>를 가져갈 수 있게 Room 상속 설정
※ 역할 : Serializable 상속(소스)
5 java > RoomDetailActivity 메인화면에서 가져온 리스트 정보를 받고 처리작업
▶ 1) RoomDetailActivity은 AppCompatActivity를 상속받는게 아니고 전에 설정했던 BaseActivity로 변경
2) setupEvents(), setValues() override 하기
3) setValues()에서 받은 roomInfo를 가지고 매핑시키기
※ 역할 : 상세화면 데이터 뿌리기(소스)

1. RoomDetailActivity 생성

상세화면을 만들기 위해 새로운 Activity를 생성해줍니다. * 참고로 Actvity.kt 파일과 xml 파일은 각각 생성하는 것이 아니라 위의 사진과 같이 Activity > Empty Activity를 클릭해서 생성하면 kt, xml 둘다 자동 생성됩니다.

<!-- activity_room_detail.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".RoomDetailActivity">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:src="@drawable/ic_launcher_foreground"
        android:scaleType="centerCrop"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="15dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/priceTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="8,000(보증금) / 30(월세)"
            android:textSize="25sp"
            android:textColor="#000000"
            android:textStyle="bold"/>

        <TextView
            android:id="@+id/descTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="설명문구 쓰는 자리입니다."
            android:layout_marginTop="5dp"/>

    </LinearLayout>


    <TextView

        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#DFDFDF"/>

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

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="주소 정보"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"/>

        <TextView
            android:id="@+id/addressTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="서울시 은평구"
            android:textColor="#000000"/>

    </LinearLayout>

    <TextView

        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#DFDFDF"/>

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

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="층수 정보"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"/>

        <TextView
            android:id="@+id/floorTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1층"
            android:textColor="#000000"/>

    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#DFDFDF"/>

</LinearLayout>

2. activity_room_detail.xml 수정

kt, xml파일을 생성하셨으면 우선 디자인과 관련된 xml파일부터 수정하도록 합니다. 디자인은 위의 소스를 참고해주세요.

* 참고 : ListView기초와 활용에서 ImageView를 사용하긴 하지만 실제 데이터를 넣어주진 않을겁니다. ImageView관련된 내용은 나중에 상세하게 올릴 예정이니 참고해주세요.

 

package com.mwsniper.review_listview

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.mwsniper.review_listview.adapters.RoomAdapter
import com.mwsniper.review_listview.datas.Room
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : BaseActivity() {

    val mRoomList = ArrayList<Room>()
    lateinit var mRoomAdapter: RoomAdapter

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

        setupEvents()
        setValues()

    }

    override fun setupEvents() {

        //메인화면의 이벤트관련 코드를 모아두는 장소
        // 리스트 클릭 이벤트 - 리스트뷰의 각 줄이 눌리는 시점의 이벤트
        roomListView.setOnItemClickListener { adapterView, view, i, l ->

            // 눌린 위치에 해당하는 목록이 어떤 목록인지 가져오기
            val clickedRoom = mRoomList[i]
            // 선택된 목록정보를 가져왔으면 이제 화면 이동
            val myIntent = Intent(mContext, RoomDetailActivity::class.java)
            // 정보를 담아주기
            // 2번에서는 해당 부분 오류남. 3번하고 난 다음 여기로 다시 와야함
            myIntent.putExtra("roomInfo", clickedRoom)
            // 화면 전환
            startActivity(myIntent)
        }
    }

    override fun setValues() {
        mRoomList.add(Room(8000, 30, "서울시 마포구", 1, "마포구 1층 방입니다."))
        mRoomList.add(Room(10000, 50, "서울시 은평구", 10, "은평구 10층 방입니다."))
        mRoomList.add(Room(3000, 80, "서울시 영등포구", 5, "영등포구 5층 방입니다."))
        mRoomList.add(Room(5000, 15, "서울시 종로구", 4, "종로구 4층 방입니다."))
        mRoomList.add(Room(9000, 20, "서울시 강서구", 8, "강서구 8층 방입니다."))
        mRoomList.add(Room(12000, 40, "서울시 강북구", 17, "강북구 17층 방입니다."))
        mRoomAdapter = RoomAdapter(mContext, R.layout.room_list_item, mRoomList)
        roomListView.adapter = mRoomAdapter

    }
}

3. setOnItemClickListener 이벤트

상세화면 디자인을 하셨으면 이제 메인화면에서 상세화면으로 이동할 수 있는 코딩을 해보도록 하겠습니다. 메인화면 → 상세화면으로 이동할 것을 짜는거니 실행 이벤트는 MainActivity에서 해야합니다. 옛날 글에서 우리는 setOnClickListener를 배운 적이 있는데 이번 글에서는 그 이벤트가 아닌 새로운 이벤트를 써야합니다. ​ListView의 리스트를 클릭했을 때 태울 이벤트 setOnItemClickListener 이벤트

 

package com.mwsniper.review_listview.datas

import java.io.Serializable

class Room(
    val deposit: Int,
    val monthlyRent: Int,
    val address: String,
    val floor: Int,
    val description: String
// 상속받는 것처럼 구현
) : Serializable {
}

4. Serializable 설정

3번까지 했으면 분명 myIntent.putExtra 부분이 빨간색으로 바뀌면서 오류를 내뱉을 것입니다. 이 오류는 우리가 만든 데이터 클래스에 첨부할 때 발생하는 에러로, 해당 오류를 해결하기 위해서는 모든 데이터들을 한꺼번에 넘기도록 처리해줍니다.

 

package com.mwsniper.review_listview

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.mwsniper.review_listview.datas.Room
import kotlinx.android.synthetic.main.activity_room_detail.*

class RoomDetailActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_room_detail)

        setValues()
        setupEvents()

    }

    override fun setupEvents() {
    }

    override fun setValues() {

        // roomInfo를 serializable로 받는다
        // 그냥 받은 채로 변수에 넣으면 오류가 나는데 이 때 Casting을 해줘야 한다
        val room = intent.getSerializableExtra("roomInfo") as Room

        // activity_room_detail.xml에 설정했던 view에 따라 매핑
        priceTxt.text = "${room.deposit} / ${room.monthlyRent}"
        addressTxt.text = room.address
        descTxt.text = room.description
        floorTxt.text = room.floor.toString()

    }
}

5. 상세화면 데이터 매핑

MainActivity에서 putExtra로 roomInfo를 보내줬으니 이제 상세화면에서 해당 정보를 받고 화면에 보일 수 있도록 매핑하는 작업을 하도록 하겠습니다. Serializable로 보낸 데이터는 받을 때 intent.getSerializableExtra로 받아야하며 "roomInfo"는 앞서 정한 name을 넣은 것 입니다. 여기서 주의해야할 점은 as Room인데요 그냥 받은 상태로 변수 넣고 작업을 하면 앱이 죽거나 오류가 납니다. 그렇기에 오류가 안나도록 우리는 Room(데이터클래스)로 캐스팅을 해줘야합니다.

 

​여기까지 잘 따라오셨으면 위의 화면과 같이 정상적으로 상세화면 이동 및 데이터출력을 확인하실 수 있습니다. 원래는 리스트목록보다 더 많은 데이터들을 상세화면에 출력해야하는데 아직은 서버 DB를 통해 데이터를 가져오는 작업을 하지 않았기에 똑같은 정보를 가지고 출력하였습니다.

Comments