Skip to content

Instantly share code, notes, and snippets.

@webserveis
Last active January 6, 2020 12:06
Show Gist options
  • Save webserveis/0dbe8ae24513192fa22aaba1da71d8bb to your computer and use it in GitHub Desktop.
Save webserveis/0dbe8ae24513192fa22aaba1da71d8bb to your computer and use it in GitHub Desktop.
Custom List with section

Custom List con secciones

Lista con elemento

  • avatar
  • text1
  • text2

y división con secciones

seccion1 elemento 1 elemento 2

seccion2 elemento 3 elemento 4

<?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:id="@+id/drawItem"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/sym_def_app_icon" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/avatar"
app:layout_constraintTop_toTopOf="parent"
tools:text="Two-Line item" />
<TextView
android:id="@+id/summary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:textColorSecondary"
app:layout_constraintEnd_toEndOf="@+id/title"
app:layout_constraintStart_toStartOf="@+id/title"
app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="Secondary text" />
</androidx.constraintlayout.widget.ConstraintLayout>
package app.webserveis.testlist
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import app.webserveis.testlist.models.CustomModel
import app.webserveis.testlist.models.MessageModel
import app.webserveis.testlist.models.SectionModel
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.content_main.*
/*
http://worldpopulationreview.com/world-cities/
https://www.suntos.com.np/kotlin-android-sample-projects-with-source-code-in-android-studio/simple-recyclerview-android-example-in-kotlin-source-code.html#update-main-activity
https://developer.android.com/guide/topics/ui/layout/recyclerview
https://medium.com/@hinchman_amanda/working-with-recyclerview-in-android-kotlin-84a62aef94ec
*/
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
initRecyclerView()
}
private fun initRecyclerView() {
val mAdapter = MyCustomSectionAdapter(dummyData())
recycler_view.setHasFixedSize(true)
recycler_view.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recycler_view.adapter = mAdapter
mAdapter.setOnItemClickListener(object : MyCustomSectionAdapter.ClickListener {
override fun onItemClick(v: View, position: Int) {
Log.v(TAG, "onItemClick $position")
Toast.makeText(
this@MainActivity,
"Clicked($position): ${mAdapter.getItem(position)}",
Toast.LENGTH_SHORT
).show()
}
})
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
private fun dummyData(): List<Any> {
val myList = mutableListOf<Any>()
myList.add(SectionModel("Section 1"))
myList.add(CustomModel("Application 1 lorem impsum alore noire", "com.application1.app com.application1.app",null))
myList.add(CustomModel("Application 2", "com.application2.app",null))
myList.add(CustomModel("Application 3", "com.application3.app",null))
myList.add(CustomModel("Application 4", "com.application4.app",null))
myList.add(CustomModel("Application 5", "com.application5.app",null))
myList.add(CustomModel("Application 6", "com.application6.app",null))
myList.add(CustomModel("Application 7", "com.application7.app",null))
myList.add(CustomModel("Application 8", "com.application8.app",null))
myList.add(SectionModel("Section 2"))
myList.add(CustomModel("Application 9", "com.application9.app",null))
myList.add(CustomModel("Application 10", "com.application10.app",null))
myList.add(CustomModel("Application 11", "com.application11.app",null))
myList.add(CustomModel("Application 12", "com.application12.app",null))
myList.add(CustomModel("Application 13", "com.application13.app",null))
myList.add(CustomModel("Application 14", "com.application14.app",null))
myList.add(CustomModel("Application 15", "com.application15.app",null))
return myList
}
companion object {
val TAG: String =
MainActivity::class.java.simpleName
}
}
package app.webserveis.testlist
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import app.webserveis.testlist.models.CustomModel
import app.webserveis.testlist.models.SectionModel
/*
https://github.com/JakeSteam/StickyHeaders/blob/master/app/src/main/java/uk/co/jakelee/stickyheadersdemo/ContentAdapter.kt
https://medium.com/@ivancse.58/android-and-kotlin-recyclerview-with-multiple-view-types-65285a254393
https://www.android4dev.com/how-to-create-recyclerview-with-multiple-view-types/
*/
class MyCustomSectionAdapter(private val mDataSet: List<Any>?) :
RecyclerView.Adapter<BaseViewHolder<*>>() {
private var clickListener: ClickListener? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) {
TYPE_SECTION -> SectionViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.simple_section_item_1, parent, false)
)
TYPE_CUSTOM -> MessageViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.custom_list_item_2, parent, false)
)
else -> throw IllegalArgumentException("Invalid view type")
}
override fun onBindViewHolder(holder: BaseViewHolder<*>, position: Int) {
val item = mDataSet?.get(position)
when (holder) {
is SectionViewHolder -> holder.bind(item as SectionModel)
is MessageViewHolder -> holder.bind(item as CustomModel)
else -> throw IllegalArgumentException()
}
}
override fun getItemCount(): Int {
return mDataSet?.size ?: 0
}
fun getItem(position: Int): Any? {
//return if (mDataSet != null) mDataSet[position] else null
return mDataSet?.get(position)
}
override fun getItemViewType(position: Int): Int =
when (mDataSet?.get(position)) {
is SectionModel -> TYPE_SECTION
is CustomModel -> TYPE_CUSTOM
else -> throw IllegalArgumentException("Invalid type of data $position")
}
fun setOnItemClickListener(clickListener: ClickListener) {
this.clickListener = clickListener
}
inner class SectionViewHolder(itemView: View) : BaseViewHolder<SectionModel>(itemView) {
private var title: TextView = itemView.findViewById(android.R.id.text1) as TextView
override fun bind(item: SectionModel) {
title.text = item.title
}
}
inner class MessageViewHolder(itemView: View) : BaseViewHolder<CustomModel>(itemView),
View.OnClickListener {
private val text1 = itemView.findViewById(R.id.title) as TextView
private val text2 = itemView.findViewById(R.id.summary) as TextView
init {
if (clickListener != null) {
itemView.setOnClickListener(this)
}
}
override fun bind(item: CustomModel) {
text1.text = item.title
text2.text = item.summary
}
override fun onClick(v: View?) {
if (v != null) {
clickListener?.onItemClick(v, adapterPosition)
}
}
}
companion object {
private const val TYPE_SECTION = 0
private const val TYPE_CUSTOM = 1
}
interface ClickListener {
fun onItemClick(v: View, position: Int)
}
}
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Sub header"
android:textColor="?android:colorAccent"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment