반응형

1편 : 기본적인 recycle view 구현

2편 : viewModel을 이용한 recycle view 구현

3편 : diffUtil callback을 이용한 recycle view 구현

 

차례대로 개시할 생각입니다.

 

뷰구성

기본적인 recycle view를 만들어줍니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/demo_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:paddingTop="@dimen/spacing_small"
    android:paddingBottom="@dimen/spacing_small"
    android:scrollbarStyle="outsideOverlay"
    android:scrollbars="vertical"
    android:layoutAnimation="@anim/grid_layout"/>

-여기서 layoutAnimation는 recycleview 각자 아이템들의 에니메이션을 담당합니다.

 

 

recycle view를 inflater를 이용해 불러와줍니다.

class DefaultListFragment :Fragment(){


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        return inflater.inflate(R.layout.default_list_fragment, container, false)
    }
    
}

 

adapter 생성

기본적인 adapter 생성

class DefaultListAdapter(private val context: Context,
private val model:ArrayList<DefaultListModel>,
private val onListClick:(model:DefaultListModel) -> Unit )
	:RecyclerView.Adapter<DefaultListAdapter.DefaultListHolder>() {
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DefaultListHolder {
       
    }

    override fun getItemCount(): Int {
       
    }

    override fun onBindViewHolder(holder: DefaultListHolder, position: Int) {
       
    }


    inner class DefaultListHolder(parent: ViewGroup) : RecyclerView.ViewHolder(

    ) {
    
    }
}

- 어댑터에서 사용할 기본적인 변수들을 받습니다.

- context : Glide를 이용해 이미지를 받아오기오려면 context객체가 필요하기때문에 받아왔습니다.

- model : 데이터를 저정하고있는 list를 받아왔습니다.

- onListClick : 클릭했을때 메인에서 변수를 넘겨받을수 있도록 클릭 리스너를 받아옵니다.

 

 

 

각 아이템에 쓰일 layout xml 생성

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
    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:id="@+id/demo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="@dimen/spacing_small"
    android:layout_marginTop="@dimen/spacing_tiny"
    android:layout_marginRight="@dimen/spacing_small"
    android:layout_marginBottom="@dimen/spacing_tiny">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:src="@drawable/no_image"
        android:scaleType="fitXY"
        app:layout_constraintBottom_toTopOf="@id/title_label"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

        <TextView
            android:id="@+id/title_label"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/spacing_medium"
            android:layout_marginTop="@dimen/spacing_medium"
            android:layout_marginRight="@dimen/spacing_medium"
            android:gravity="start|center_vertical"
            android:textAppearance="?attr/textAppearanceHeadline5"
            app:layout_constraintBottom_toTopOf="@+id/body_label"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/imageview"
            tools:text="Hello, world!" />

        <TextView
            android:id="@+id/body_label"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/spacing_medium"
            android:gravity="start|center_vertical"
            android:textAppearance="?attr/textAppearanceListItemSecondary"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/title_label"
            tools:text="Hello, world!" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

 

holder에 연결

    inner class DefaultListHolder(parent: ViewGroup) : RecyclerView.ViewHolder(
		LayoutInflater.from(parent.context).inflate(R.layout.default_list_item, parent, false)
    ) {
        private val iv:ImageView = itemView.findViewById(R.id.imageview)
        private val titleView:TextView = itemView.findViewById(R.id.title_label)
        private val bodyView:TextView = itemView.findViewById(R.id.body_label)

        fun bindView(model:DefaultListModel){
            titleView.text = model.defaultTitle
            bodyView.text = model.defaultBody
            Glide
                .with(context)
                .load( model.defaultImage)
                .centerCrop()
                .placeholder(R.drawable.no_image)
                .into(iv)
        }
    }

- bindView는 onBindViewHolder메소드에서 holder를 가저와 사용할 생각입니다.

 

 

만들어놓은 것들 연결

class DefaultListAdapter(
  private val context: Context,
  private val model:ArrayList<DefaultListModel>,
  private val onListClick:(model:DefaultListModel) -> Unit
  )
  : RecyclerView.Adapter<DefaultListAdapter.DefaultListHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DefaultListHolder {
        return DefaultListHolder(parent).apply {
            itemView.setOnClickListener {
                onListClick(model.get(adapterPosition))
            }
        }
    }

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

    override fun onBindViewHolder(holder: DefaultListHolder, position: Int) {
        holder.bindView(model.get(position))
    }


    inner class DefaultListHolder(parent: ViewGroup) : RecyclerView.ViewHolder(
        LayoutInflater.from(parent.context).inflate(R.layout.default_list_item, parent, false)
    ) {
        private val iv:ImageView = itemView.findViewById(R.id.imageview)
        private val titleView:TextView = itemView.findViewById(R.id.title_label)
        private val bodyView:TextView = itemView.findViewById(R.id.body_label)

        fun bindView(model:DefaultListModel){
            titleView.text = model.defaultTitle
            bodyView.text = model.defaultBody
            Glide
                .with(context)
                .load( model.defaultImage)
                .centerCrop()
                .placeholder(R.drawable.no_image)
                .into(iv)
        }
    }
}

Main에 연결

   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val data = context?.let {
            Parser.getAlbumList(it,"DefaultList")
        }
        val rcv: RecyclerView = view.findViewById(R.id.demo_list)
        val mAdapter = context?.let {
            data?.let { it1 ->
                DefaultListAdapter(it, it1){ list ->
                    Log.d("asdf","Title : ${list.defaultTitle}, Body : ${list.defaultBody}, image : ${list.defaultImage}")
                }
            }
        }

        rcv.apply {
            layoutManager = GridLayoutManager(context,2)
            adapter = mAdapter
        }
    }

- 특별한것은 없고  list 생성후 연결시켜주면된다.

반응형

+ Recent posts