Advanced UI

ewillwin·2023년 3월 22일
0
  • split an Activity into multiple Layouts (HorizontalScrollView, Inflater)
  • Create and manage ListView (Adapter)

Multiple Layouts

  • Sometimes, we need more than one Layout
    • Sometimes, we need partial arrangement
    • Some place needs linear arrangement, or some place needs scrollView
  • A layout is allowed to contain other Layouts
    • All Layouts are also have constrains and attributes for arrangement
    • It actually similar with inserting Views into a Layout

Inflation & LayoutInflater

  • Kotlin source는 "objectified"된 resource만 사용할 수 있음
  • xml resource를 kotlin object로 convert 해줘야함
  • ex) setContentView
    • To use XML contents in the kotlin source codes, we need objectified Views
    • setContentView function convert contents defined in XML to Kotlin object
  • XML contents를 objectify하는 프로세스를 Inflation이라고 함
  • LayoutInflater는 Inflation과 거의 같은 operation을 함
  • layout을 runtime 동안에 바꿔주기 위해 Inflator가 필요함

Adapter

  • ListView: A ViewGroup which groups several items and display them in vertical scrollable list
  • The list items are automatically inserted to the ListView using Adapter
    • Adapter pull contents from a source
  • To make ListView,
    • 1) Custom Adapter -> .kt file
    • 2) Custom List Layout -> .xml file
    • 3) Set custom adapter to listview





Practice

  • file structure는 아래와 같음
    MainActivity.kt
    Restaurant.kt
    CustomAdapter.kt
    activity_main.xml
    item.xml
    sub_layout.xml

"item.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">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_weight="1"
        tools:srcCompat="@tools:sample/avatars" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="TextView" />
</LinearLayout>
  • listview의 item

"sub_layout.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">

    <ImageView
        android:id="@+id/leftImageView"
        android:layout_width="200dp"
        android:layout_height="100dp"
        tools:srcCompat="@tools:sample/avatars" />

    <ImageView
        android:id="@+id/rightImageView"
        android:layout_width="200dp"
        android:layout_height="100dp"
        tools:srcCompat="@tools:sample/avatars" />
</LinearLayout>
  • SHOW SUB LAYOUT 버튼을 누르면 출력됨

"activity_main.xml"

<?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/source"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <HorizontalScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_marginTop="300dp"
        app:layout_constraintTop_toTopOf="parent">

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

            <Button
                android:id="@+id/pizza"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Button" />

            <Button
                android:id="@+id/hamburger"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Button" />

            <Button
                android:id="@+id/chicken"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Button" />
        </LinearLayout>
    </HorizontalScrollView>

    <Button
        android:id="@+id/showButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="SHOW SUB LAYOUT"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:orientation="horizontal"
        app:layout_constraintBottom_toTopOf="@+id/scrollview"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/showButton">
    </LinearLayout>

    <ListView
        android:id="@+id/reslistview"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/scrollview"
        tools:layout_editor_absoluteY="290dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
  • constraint 잘 맞춰야함
  • layout의 구조는 아래와 같음

"Restaurant.kt"

package com.example.week4

class Restaurant (val id: Int, val name: String)
  • Restaurant Class 생성

"CustomAdapter.kt"

package com.example.week4

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ImageView
import android.widget.TextView


class CustomAdapter (val context: Context, val items: ArrayList<Restaurant>): BaseAdapter(){
    override fun getCount(): Int{
        return items.size
    }

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

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

    override fun getView(i: Int, cvtView: View?, parent: ViewGroup?): View{
        val inflater: LayoutInflater =
            LayoutInflater.from(context)
        val view: View = inflater.inflate(R.layout.item,null)

        var imgView = view.findViewById<ImageView>(R.id.imageView)
        var textView = view.findViewById<TextView>(R.id.textView)

        textView.text = items[i].name
        imgView.setImageResource(items[i].id)

        return view
    }
}
  • BaseAdapter를 Extend함
  • Context parameter 정의 및 item들을 저장하기 위한 Arraylist를 parameter로 정의
  • getCount(), getItem(), getItemId를 override 해줌
  • getView()를 override 해줌
    • LayoutInflater를 생성
    • view를 생성
    • imgView와 textView를 정의
    • imgView는 setImageResource()를 이용하여 item[i].id로 참조한 이미지로 할당
    • textView는 item list에서 해당하는 index의 name으로 할당
    • 마지막에 변환한 view를 반환해줌

"MainActivity.kt"

package com.example.week4

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.ListView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var container = findViewById<LinearLayout>(R.id.container)
        var showButton = findViewById<Button>(R.id.showButton)

        showButton.setOnClickListener {

            val layoutInflater: LayoutInflater =
                applicationContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater


            layoutInflater.inflate(R.layout.sub_layout, container, true)

            var leftImageView = findViewById<ImageView>(R.id.leftImageView)
            var rightImageView = findViewById<ImageView>(R.id.rightImageView)

            leftImageView.setImageResource(R.drawable.bbq)
            rightImageView.setImageResource(R.drawable.bhc)
        }

        val pizzaButton = findViewById<Button>(R.id.pizza)
        pizzaButton.setOnClickListener{
            val pizzaData = ArrayList<Restaurant>()
            pizzaData.add(Restaurant(R.drawable.domino, "domino pizza"))
            pizzaData.add(Restaurant(R.drawable.pizzanarachickengongju, "pizza nara chicken gong"))
            pizzaData.add(Restaurant(R.drawable.pizzahut, "pizza hut"))

            val myAdapter = CustomAdapter(applicationContext, pizzaData)
            val listView = findViewById<ListView>(R.id.reslistview)
            listView.adapter = myAdapter
        }

        val hamburgerButton = findViewById<Button>(R.id.hamburger)
        hamburgerButton.setOnClickListener{
            val hamburgerData = ArrayList<Restaurant>()
            hamburgerData.add(Restaurant(R.drawable.burgerking, "burger king"))
            hamburgerData.add(Restaurant(R.drawable.lotteria, "lotte ria"))
            hamburgerData.add(Restaurant(R.drawable.momstouch, "moms touch"))
            hamburgerData.add(Restaurant(R.drawable.mcdonalds, "mc donald"))

            val myAdapter = CustomAdapter(applicationContext, hamburgerData)
            val listView = findViewById<ListView>(R.id.reslistview)
            listView.adapter = myAdapter
        }

        val chickenButton = findViewById<Button>(R.id.chicken)
        chickenButton.setOnClickListener{
            val chickenData = ArrayList<Restaurant>()
            chickenData.add(Restaurant(R.drawable.bbq, "bb q"))
            chickenData.add(Restaurant(R.drawable.bhc, "bh c"))
            chickenData.add(Restaurant(R.drawable.goobne, "goob ne"))

            val myAdapter = CustomAdapter(applicationContext, chickenData)
            val listView = findViewById<ListView>(R.id.reslistview)
            listView.adapter = myAdapter
        }

    }
}
  • container layout과 showButton을 정의하고, setOnClickListener를 이용해 버튼이 클릭 될 경우 leftImageView와 rightImageView가 container layout에 출력되도록 설정
  • pizzaButton, hamburgerButton, chickenButton을 각각 생성해줌
    • setOnClickListener 안에 버튼이 클릭 될 경우 실행할 프로세스를 정의함
    • pizzaData를 생성하고 pizza item들을 add 해줌
    • myAdapter를 정의하여 CustomAdapter를 할당해주고, CustomAdapter에 Context와 pizzaData를 인수로 넣어줌
    • listView를 생성해주고, listView에 myAdapter를 할당해주어 item들 (pizza들)을 삽입해줌
    • hamburgerButton과 chickenButton도 마찬가지로 setOnClickListener에서 adapter를 이용해 listView 구현
profile
Software Engineer @ LG Electronics

0개의 댓글