Android

[Android] 5주차 스터디 (Kotlin, CustomListView)

poppy 2020. 10. 28. 23:33
반응형

ListView - Kotlin

View부분은 리스트뷰 하나를 넣어주는 것으로 간단하게 구성하였습니다!

코틀린으로 리스트뷰를 만들어보겠습니다

먼저 코틀린 문법을 간단히 보고 코드를 보겠습니다!

코틀린 문법
1. 변수 - val, var
val : 초기에 값을 할당하면 변경할 수 없음, 초기화가 한 번만 되는 것이 맞다면 여러 값을 초기화 할 수 있음
var: 초기화 후 값을 변경할 수 있음, 단 정해진 타입의 값만 넣을 수 있음
2. :(콜론)은 상속관계를 나타내거나 해당 변수가 무슨 타입인지 선언할 때 쓰임
ex) MainActivity : AppCompatActivity() => 상속, val name : String => 변수타입 선언
3. $ = %
$와 %은 같은 역할을 수행함 ex) println("%d",a) = println("$a")
4. 함수를 쓸 때는 "fun 함수명()" 
5. 배열 : arrayOf
특정 타입을 지정하지 않은 경우 어떤 값이 들어가도 상관 없음 ex) var arr = arrayOf("abc",100,"1이3",true)
특정 타입을 지정하는 경우 해당 타입의 값만 들어갈 수 있음 ex) var arr = arrayOf<Int>(100,200,300)

 

class MainActivity : AppCompatActivity() { //MainActivity가 AppCompatActivity()을 상속
    override fun onCreate(savedInstanceState: Bundle?) { //savedInstanceState가 Bundle 타입, ? = null값 허용
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val LIST_MENU = arrayOf("MEMU1","MENU2","MENU3")

        var listView : ListView = findViewById(R.id.listview) as ListView

        val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, LIST_MENU)
        listView.adapter = adapter 
    }
}

val LIST_MENU = arrayOf("MEMU1","MENU2","MENU3") - 문자열을 바탕으로 데이터를 정의합니다

var listView : ListView = findViewById(R.id.listview) as ListView - listView 객체 생성을 합니다

val adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1,LIST_MENU) - adapter 객체 생성하고 데이터와 연동

listView.adapter = adapter - 코틀린은 getAdapter 와 setAdapter 함수 통일하므로 listView와 연결해주기만 하면 됩니다

listView.setOnItemClickListener { parent, view, position, id ->
            if (position == 0) {
                AlertDialog.Builder(this)
                    .setTitle("앱을 종료하겠습니까?")
                    .setPositiveButton("종료") { dialogInterface: DialogInterface?, i: Int -> finish() }
                    .setNegativeButton("취소") { dialogInterface: DialogInterface?, i: Int -> null }
                    .show()
            }

            if (position == 1) {
                var cal = Calendar.getInstance()
                DatePickerDialog(
                    this,
                    DatePickerDialog.OnDateSetListener { datePicker, year, month, day ->
                        Toast.makeText(this, "${year}년 ${month + 1}월 ${day}일", Toast.LENGTH_SHORT)
                            .show()
                    },
                    cal.get(Calendar.YEAR),
                    cal.get(Calendar.MONTH),
                    cal.get(Calendar.DATE)
                ).show()

                TimePickerDialog(
                    this,
                    TimePickerDialog.OnTimeSetListener { timePicker, hour, minute ->
                        Toast.makeText(this, "${hour}시 ${minute}분", Toast.LENGTH_SHORT).show()
                    },
                    cal.get(Calendar.MONTH),
                    cal.get(Calendar.MINUTE),
                    true
                ).show()
            }

            if (position == 2) {
                    startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://www.naver.com")))
            }
        }

다음은 리스트뷰 아이템을 선택했을 때 어떤 동작을 실행할 것인지에 관한 코드입니다. 아이템의 위치값(position)을 가져와서 각각 다른 동작을 하도록 해주었습니다!

positon이 0일 경우 AlertDialog를 띄워 앱을 종료할 수 있게 했습니다

posiiotn이 1일 경우 DatePicker 와 TimePicker를 띄워 현재 시간과 날짜를 토스트 메시지로 나타나게 했습니다

이때 month는 0부터 시작하므로 month+1을 해줘야 정상적으로 날짜가 나옵니다

position이 1일 경우 네이버 웹사이트로 이동하게 했습니다

CustomListView - Kotlin

View부분은 먼저 main부분은 리스트뷰로 간단히 구성했고, main의 리스트뷰 아이템에 들어갈 뷰를 listview_item.xml로 만들었습니다! 리스트뷰 아이템은 한 개의 이미지뷰와 두 개의 텍스트뷰로 구성하였습니다

activity_main.xml / listview_item.xml

ListViewItem.kt

@Getter
@Setter
class ListViewItem_Kotlin {
    var icon: Drawable? = null
    var title: String? = null
    var desc: String? = null
}

리스트뷰 아이템에 들어갈 정보를 변수 선언해주고 lombok을 사용하여 생성자를 만들지 않고 생성자를 만든 것과 같은 기능을 주었습니다

ListViewAdapter.kt

//Adapter에 추가된 데이터를 저장하기 위한 ArrayList
private val listViewItemList = ArrayList<ListViewItem>()
    
override fun getCount(): Int {
    return listViewItemList.size
}

override fun getItem(position: Int): Any {
    return listViewItemList[position]
}

override fun getItemId(position: Int): Long {
    return position.toLong()
}

어댑터에 추가된 데이터를 저장하기 위한 listViewItemList를 생성해줍니다. 

getCount()listViewItemList의 데이터 항목 개수를 가져와 리턴해줍니다

getItem()listViewItemList의 위치의 값을 가져와 리턴해줍니다

getItemId()는 위치만 리턴해줍니다

 

override fun getView(position: Int, convertView: View, parent: ViewGroup): View {
        var convertView = convertView
        val pos = position //리스트뷰의 아이템 위치
        val context = parent.context //부모객체의 Context를 가져옴
        
        // "listview_item" Layout을 inflate하여 convertView 참조
        if (convertView == null) {
            val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = inflater.inflate(R.layout.listview_item, parent, false)
        }
        
        val iconImageView = convertView.findViewById<View>(R.id.imageView1) as ImageView
        val titleTextView = convertView.findViewById<View>(R.id.textView1) as TextView
        val descTextView = convertView.findViewById<View>(R.id.textView2) as TextView
        
        val listViewItem = listViewItemList[position]
        
        iconImageView.setImageDrawable(listViewItem.icon)
        titleTextView.text = listViewItem.title
        descTextView.text = listViewItem.desc
        
        return convertView
    }

getView()지정된 position에 위치한 데이터를 화면에 출력하는 View를 리턴해줍니다!

val iconImageView = convertView.findViewById<View>(R.id.imageView1) as ImageView - 화면에 표시될 View와 위젯을 연결해줌, 매번 findViewById를 하는 것이 성능적으로 비효율적이라서 ViewHolder패턴을 사용하면 좋습니다

val listViewItem = listViewItemList[position] - listViewItemList에서 position에 위치한 데이터를 할당해줍니다

iconImageView.setImageDrawable(listViewItem.icon) - 리스트뷰 아이템 내의 위젯에 데이터를 반영해줍니다

 

fun addItem(icon: Drawable?, title: String?, desc: String?) {
        val item = ListViewItem() // 하나의 리스트 항목을 하나의 객체로 봄
        
        item.icon = icon
        item.title = title
        item.desc = desc
        
        listViewItemList.add(item)
}

addItem()은 아이템에 데이터 추가를 해줍니다!

 

MainActivity.kt

class MainActivity_Kotlin : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val listview: ListView
        val adapter: ListViewAdapter
        adapter = ListViewAdapter()
        
        listview = findViewById<View>(R.id.listView_Shape) as ListView //리스트뷰 참조
        listview.adapter = adapter //listview와 adapter 연결
        
        //아이템 추가
        adapter.addItem(ContextCompat.getDrawable(this, R.drawable.instagram), "instagram", "this is instagram")
        adapter.addItem(ContextCompat.getDrawable(this, R.drawable.youtube), "youtube", "this is youtube")
        adapter.addItem(ContextCompat.getDrawable(this, R.drawable.facebook), "facebook", "this is facebook")
        
        //클릭이벤트 정의
        listview.onItemClickListener = OnItemClickListener { parent, v, position, id ->
            val item = parent.getItemAtPosition(position) as ListViewItem //CustomList의 경우
            Toast.makeText(applicationContext, item.title, Toast.LENGTH_LONG).show()
        }
    }
}

listview와 adapter 변수를 생성해주고 리스트뷰와 adapter를 연결해줍니다!

val item = parent.getItemAtPosition(position) as ListViewItem- CustomListView의 경우 이 코드를 써주어야 하고, 아이템의 위치를 가져와 할당합니다

 

 

반응형