👉 앱 개발 숙련 개념 정리를 마무리해보자.
- 뷰바인딩에 대해 이해하고 findViewById와의 차이점을 설명
- 어댑터 뷰의 기본 개념 및 종류, 리스트 뷰와 그리드 뷰의 설정 방법 이해
- 커스텀 항목 뷰를 정의하는 방법, RecyclerView를 사용하는 방법 이해
- 프래그먼트의 기본개념 및 프래그먼트 생명주기 이해
- 다이얼로그가 무엇인지 알고 구조에 대해 이해
- 알림의 중요도 순서를 이해
viewBinding은 View와 상호작용하는 코드를 쉽게 작성할 수 있고, 인스턴스에 상응하는 레이아웃에 ID가 있는 모든 View의 직접 참조가 포함된다.
뷰 바인딩은 View를 직접 참조를 생성하기 때문에 유효하지 않은 ID로 인해 Null 예외가 발생할 위험이 없다.
각 바인딩 클래스에 있는 필드의 유형이 xml 파일에서 참조하는 뷰와 일치해 클래스 변환 예외가 발생할 위험이 없다.
어댑터 뷰는 여러 항목을 나열하고 선택이 가능하도록 기능을 제공하는 뷰로, ListView와 GridView가 있다. 표시할 항목 데이터를 직접 나열하지 않고 어댑터라는 객체로부터 공급받는다.
ListView는 항목들을 수직(vertical)로 나열하는 방식이고, GridView는 항목들을 격자 형태로 나열하는 방식을 말한다.
복수 개의 항목을 수직으로 나타내는 방식인 ListView의 설정방법을 정리해보자.
항목들을 격자 형태로 나열해 이미지를 나열할 때 주로 사용하는 방식으로 GridView의 설정방법을 정리해보자.
하나의 문자열이나 이미지뿐만 아니라, 다수의 문자열이나 이미지를 포함하는 임의의 이미지 뷰를 나열할 때 주로 사용하는 방식으로 CustomView의 설정방법을 정리해보자.
<?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="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/iconItem"
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
android:scaleType="centerCrop"
android:padding="@dimen/icon_padding"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:src="@drawable/sample_0" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2">
<TextView
android:id="@+id/textItem1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="@dimen/list_item_text_size1"
android:padding="@dimen/list_item_padding"
android:hint="Name"
/>
<TextView
android:id="@+id/textItem2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="@dimen/list_item_text_size2"
android:padding="@dimen/list_item_padding"
android:hint="Age"
/>
</LinearLayout>
</LinearLayout>
TextView의 TextSize 및 padding이 dimen에서 가져오고 있기 때문에 이를 위한 dimen 파일을 생성하고 코드를 추가해준다.
항목과 관련된 데이터 클래스를 생성하고 정의해준다.
class MyAdapter(val Context : Context, val mItems: MutableList<MyItem>) : BaseAdapter() {
// 항목 총 개수 반환
override fun getCount(): Int {
return mItems.size
}
// 항목 중 position 위치의 항목 반환
override fun getItem(position: Int): Any {
return mItems[position]
}
// 항목 id를 항목의 위치로 간주함
override fun getItemId(position: Int): Long {
return position.toLong()
}
// position 위치의 항목에 해당되는 항목뷰를 반환하는 것이 목적
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
// convertView : ListView에 항목을 띄울 view
var convertView = convertView
if(convertView == null)
convertView = LayoutInflater.from(parent?.context).inflate(R.layout.item_recyclerview, parent, false)
val item:MyItem = mItems[position]
// convertView 변수로 참조되는 항목 뷰 객체 내에 포함된 객체를 id를 통해 얻어오기
val iconImageView = convertView?.findViewById<View>(R.id.iconItem) as ImageView
val tv_name = convertView.findViewById<View>(R.id.textItem1) as TextView
val tv_age = convertView.findViewById<View>(R.id.textItem2) as TextView
// 어댑터가 관리하는 항목 데이터 중에서 position 위치의 항목의 객체를 해당 항목에 설정
iconImageView.setImageResource(item.aIcon)
tv_name.text = item.aName
tv_age.text = item.aAge
return convertView
}
}
한정적인 화면에 많은 데이터를 넣을 수 있는 view로, ListView를 삭제 및 생성을 반복하는 것을 보완한 방식으로, 사용자가 스크롤을 할 때, 위에 있던 항목이 다시 아래로 돌아오면서 재사용하는 방식이다.
RecyclerView 사용방법을 정리해보자.
class MyAdapter(val mItems: MutableList<MyItem>) : RecyclerView.Adapter<MyAdapter.Holder>() {
interface ItemClick {
fun onClick(view: View, position: Int)
}
var itemClick : ItemClick? = null
// ViewHolder 생성
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter.Holder {
// View binding을 이용해 아이템 레이아웃을 inflate하고 View Holder 생성
val binding = ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
// ViewHolder에 Data binding
override fun onBindViewHolder(holder: Holder, position: Int) {
// 아이템 뷰 클릭 이벤트 설정
holder.itemView.setOnClickListener {
itemClick?.onClick(it, position)
}
// 아이템 데이터 binding
holder.iconImageView.setImageResource(mItems[position].aIcon)
holder.name.text = mItems[position].aName
holder.age.text = mItems[position].aAge
}
// id를 항목의 위치로 간주함 -> 아이템의 id 반환
override fun getItemId(position: Int): Long {
return position.toLong()
}
// 항목 총 개수 반환
override fun getItemCount(): Int {
return mItems.size
}
// Hoder 클래스 정의
inner class Holder(val binding: ItemRecyclerviewBinding) : RecyclerView.ViewHolder(binding.root){
val iconImageView = binding.iconItem
val name = binding.textItem1
val age = binding.textItem2
}
}
Holder 코드를 먼저 만들어주어야 하고, onCreateViewHolder에서 Holder을 리턴해주어야 한다는 것
activity 위에서 동작하는 모듈화된 사용자 인터페이스로 하나의 activity에 여러 개의 fragment를 조합해 창이 여러 개인 UI를 구축할 수 있고, 하나의 fragemnt를 여러 activity에서 재사용이 가능하며, activity에서 activity로 넘어가는 것보다 빠르기 때문에 자주 사용된다.
fragment의 생명주기는 activity의 생명주기와 연관되어 있다.
👉 자세한 설명은 evergreen_tree님의 블로그 참고
사용자에게 결정을 내리거나 추가 정보를 입력하라는 메세지를 표시하는 작은 창을 말한다.
구조는 제목, 콘텐츠 영역, 작업 버튼으로 이루어져 있다.
알림 기능은 사용자에게 앱과 관련된 정보를 보여주는 기능이다. 알림을 터치하면 앱으로 이동할 수 있으며, 상단 부분에 표시된다.
- 긴급 : IMPORTANCE_HIGH - 🔔, 헤드업 알림 표시
- 높음 : IMPORTANCE_DEFAULT - 🔔
- 보통 : IMPORTANCE_LOW - 🔔
- 낮음 : IMPORTANCE_MIN - 🔕, 상태줄에 표시 ❌