activity_main.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=".MainActivity">
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
<ListView
android:id="@+id/lv1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
var data = arrayOf("데이터1", "데이터2", "데이터3", "데이터4", "데이터5",
"데이터1", "데이터2", "데이터3", "데이터4", "데이터5",
"데이터1", "데이터2", "데이터3", "데이터4", "데이터5",
"데이터1", "데이터2", "데이터3", "데이터4", "데이터5")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// var adapter = ArrayAdapter<String>(this, R.layout.row, R.id.tv1, data)
var adapter = ListAdapter()
lv1.adapter = adapter
}
inner class ListAdapter : BaseAdapter() {
var listener = BtnListener()
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View? {
var convertView: View? = p1 // p1은 재사용 가능 한 View
if (p1 == null) { // 없을땐 새롭게 만들어주고
convertView = layoutInflater.inflate(R.layout.row, null)
}
var text: TextView? = convertView?.findViewById<TextView>(R.id.textview)
var button1: Button? = convertView?.findViewById<Button>(R.id.btn1)
var button2: Button? = convertView?.findViewById<Button>(R.id.btn2)
button1?.setOnClickListener(listener)
button2?.setOnClickListener(listener)
// 버튼 리스너에서 어떤 항목을 선택했는지 알고 싶지만 BtnListener에서는 알 수 없다. 그래서 tag를 달아서 쓴다.
button1?.tag = p0
button2?.tag = p0
text?.text = data[p0]
return convertView
}
// 객체 반환 시에
override fun getItem(p0: Int): Any? {
return null
}
override fun getItemId(p0: Int): Long {
return 0
}
override fun getCount(): Int {
return data.size
}
}
inner class BtnListener : View.OnClickListener {
override fun onClick(p0: View?) {
// 받은 tag를 int로 형변환 하여 사용한다.
var position = p0?.tag as Int
when (p0?.id) {
R.id.btn1 ->
tv1.text = "${position}첫 번째 버튼"
R.id.btn2 ->
tv1.text = "${position}두 번째 버튼"
}
}
}
}
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/textview"
android:text="asd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/btn1"
android:text="버튼1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn2"
android:text="버튼2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
이번에는 Adapter를 내가 만든 레이아웃으로 리스트를 만들고 싶을 때 커스텀하는 방법이다. 클래스에 BaseAdapter을 임플리먼트 시키고 필수 오버라이딩 메서드를 구현해 주면 되는데, 각각 4개가 존재한다. 중요한 것은 getView와 getCount인데, getCount는 리스트뷰가 정확히 개수가 어떤지 모르기 때문에, 그것을 반환해주는 메서드이고 getView는 항목이 굉장히 많다고 하면 스크롤이 되게 되는데 안보이던게 보이게 된다. 이 메서드는 항목하나를 구성하기 위해서 호출이 된다. 100만개에서 화면에 호출해야하는 것은 7개면 7개만 호출된다. 스크롤을하게 되면 보이던게 안보이게 되는 애들은 버리지 않고 두번째 매개변수로 넘어오게 되어 재사용하여 사용하게 된다. 단 몇개의 객체만 가지고 무한개를 사용한다. 만약 재사용가능한 객체가 없다면 그냥 null이 들어가게 하여 새로 뷰 객체를 만들게 된다. 그리고 해당하는 버튼에 리스너를 달아주는데 문제는 인덱스 값을 버튼 리스너에서 알 수가 없다. 그래서 tag에 인덱스를 넣어서 전달해준다. 그리고 리스너의 when 절에서 꺼내서 쓰면 된다.
궁금하신 점은 덧글로 남겨주세요.
'안드로이드' 카테고리의 다른 글
[Android Kotlin] 안드로이드 코틀린 ViewPager (0) | 2020.03.24 |
---|---|
[Android Kotlin] 안드로이드 코틀린 Spinner (0) | 2020.03.24 |
[Android Kotlin] 안드로이드 코틀린 ListView (0) | 2020.03.21 |
[Android Kotlin] 안드로이드 코틀린 ImageView (0) | 2020.03.21 |
[Android Kotlin] 안드로이드 코틀린 EditText (0) | 2020.03.21 |