땀이 삐질삐질 나는 개발 일기

리사이클러뷰 아이템 액티비티로 전달하기 본문

개발 Tip

리사이클러뷰 아이템 액티비티로 전달하기

삐질 2019. 7. 6. 01:25
안녕하세요. 삐질삐질 개발하는 개발자 삐질입니다.

오늘은 게시판 형식의 Recyclerview 에서 Item을 선택하여  다음 액티비티로 전달 후 

선택되어 진 Item에 대해 자세히 볼수있는 과정을 간단하게 배워보겠습니다.


 . 



( 주의 ) 귀찮은 FindByViewId를 사용하지 않기 위해 Databinding을 사용했습니다. 이에 관련된 세팅은 아래와 같습니다.

  • App Level의 gradle setting file 
android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.ppizil.renderactivityitem_from_recyclerview"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled = true
    }
}
여기서 dataBinding{ enabled = true} 부분을 추가해주시면 됩니다.







본격적으로  Layout file -> kt파일 순으로 살펴보도록 하겠습니다.

  1. Activity_main.xml
    리사이클러뷰 하나를 선언 해 줍니다.
<?xml version="1.0" encoding="utf-8"?>
<layout>
    <androidx.recyclerview.widget.RecyclerView
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/reyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    </androidx.recyclerview.widget.RecyclerView>
</layout>


2.  Item_entity.xml 
    타이틀, 서브타이틀, 날짜  TextView를 선언 해 줍니다.
<?xml version="1.0" encoding="utf-8"?>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/viewGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#EEB8B8"
        android:padding="15dp">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="타이틀 영역"
            android:textSize="18sp"
            android:textStyle="bold"
            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"
            app:layout_constraintVertical_bias="0.5" />

        <TextView
            android:id="@+id/subTitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="4dp"
            android:layout_marginEnd="4dp"
            android:text="서브타이틀"
            android:textSize="12sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/date"
            app:layout_constraintHorizontal_bias="0.162"
            app:layout_constraintStart_toEndOf="@+id/title"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.5" />

        <TextView
            android:id="@+id/date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="날짜영역"
            android:textSize="12sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.5" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

  1. activity_item_detail.xml
    리사이클러뷰에서 선택 된 아이템의 내용을 표시할 TextView들을 선언 해 줍니다.
<?xml version="1.0" encoding="utf-8"?>
<layout>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="15dp"
        android:orientation="vertical">

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

            <TextView
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:text="타이틀"
                android:textColor="#000000"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:text="데이트"
                android:textColor="#000000"
                android:textSize="18sp" />
        </LinearLayout>


        <TextView
            android:id="@+id/contents"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="본 메세지"
            android:textColor="#000000"
            android:textSize="18sp" />

    </LinearLayout>
</layout>

  1. MainActivity.kt
    - 복잡한 로직은 없습니다. init() 메서드에서  각 한줄 한줄의 Item으로 쓸 Item객체를 만들고, 글의 내용을 입력 해줍니다.
    - 그후 만들어 진 객체를 List에 추가 합니다.
    - 만들어진 List를 Recyclerview의 Adapter에 대입 해 줍니다.

class MainActivity : AppCompatActivity() {


    var binding: ActivityMainBinding? = null
    lateinit var items: MutableList<ItemEntity>
    lateinit var adapter: BoardAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        init();
    }

    fun init() {
        items = ArrayList()
        for (i in 0..19) { //데이터 생성 영역
            val item = ItemEntity()
            item.title = "$i 번째 글 입니다."
            item.contents = "안녕하세요. 개발자 삐질입니다.\n 오늘은 리사이클러뷰 아이템을 액티비티에 전달하는 방법에 대해 알아보도록 하겠습니다."
            item.subTitle = item.contents?.indexOf("\n")?.let { item.contents?.substring(0, it) }
            item.date = System.currentTimeMillis().toString()
            items.add(item)
        }

        adapter = BoardAdapter(this) //리사이클러뷰 사용영역
        adapter.items = items
        var linearLayoutManager = LinearLayoutManager(this)
        linearLayoutManager.orientation= RecyclerView.VERTICAL
        binding?.reyclerView?.layoutManager = linearLayoutManager
        binding?.reyclerView?.adapter = adapter
    }
}


  1. BoardAdapter.kt 
    - 기본적으로 Click Area는 각각의 title, date , subContents Textview가 아닌, 부모 Viewgroup을 클릭하면 해당 아이템을 선택한 효과를 내기위해
    onClick부분 처럼 선언 했습니다.
    - Intent를 통해  해당 ItemEntity를 직렬화( Serialize )된 객체로써 전달을 합니다. 
    - 여기서 직렬화(Serialize)는 추가적인 가벼운 별도의 개념이해를 필요로 합니다.
    - Serialize 대신 Pacelable객체를 쓸순 있지만 (이것은 정말 기본 예제이기 때문에..)
class BoardAdapter(private val context: Context) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    var items: List<ItemEntity>

    init {
        items = ArrayList()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val binding = ItemEntityBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ItemViewHolder(binding)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is ItemViewHolder) {
            holder.bind(context, position, items[position])
        }
    }

    override fun getItemCount(): Int {
        return items.size
    }

    class ItemViewHolder(private val binding: ItemEntityBinding)
        : RecyclerView.ViewHolder(binding.root), View.OnClickListener {
        private var context: Context? = null
        private var pos: Int = 0
        private var itemEntity: ItemEntity? = null

        init {
            init()
        }

        fun bind(context: Context, pos: Int, itemEntity: ItemEntity) {
            this.context = context
            this.pos = pos
            this.itemEntity = itemEntity
            binding.title.setText(itemEntity.title)
            binding.subTitle.setText(itemEntity.subTitle)
            binding.date.setText(itemEntity.date)
            binding.executePendingBindings()
        }

        fun init() {
            binding.viewGroup.setOnClickListener(this)
            binding.title.setClickable(false)
            binding.subTitle.setClickable(false)
            binding.date.setClickable(false)
        }

        override fun onClick(v: View) {
            val id = v.id
            when (id) {
                R.id.viewGroup -> {
                    val intent = Intent(context, ItemDetailActivity::class.java)
                    intent.putExtra("item", itemEntity)
                    context?.startActivity(intent)
                }
            }
        }
    }
}

  1. ItemEntity.kt
    - Reyclerview에서 ItemEntity(그릇)로 쓸 Custom DataClass(그냥 내가 임의로 만든 클래스) 입니다.
    - BoardAdapter에서 Intent에 직렬화 된 객체를 담기 위해서는  데이터 클래스로 쓸 클래스에 Serialize를 상속하는 클래스로 구성해야 합니다.(알아서 직렬화 해주는 고마움)
class ItemEntity: Serializable{
    var title: String? = null
    var subTitle: String? = null
    var contents: String? = null
    var date: String? = null
}

  1. ItemDetailActivity.kt
    - Intent를 통해 받은 item을 ItemEntity로 저장하고, 해당  TextView들에게  setText해줄 수 있도록 합니다.
class ItemDetailActivity : AppCompatActivity() {

    lateinit var binding: ActivityItemDetailBinding
    lateinit var item: ItemEntity
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_item_detail)
        init();
    }

    fun init() {
        item = intent.extras.get("item") as ItemEntity
        binding.title.setText(item.title)
        binding.contents.setText(item.contents)
        binding.date.setText(item.date)
    }
}




안드로이드 초보 개발자를 위해 아래와 같은 카카오 오픈톡을 운영 중입니다


Comments