Android UI 위젯 완벽 가이드
Android UI 위젯 완벽 가이드
Android에서 자주 사용되는 UI 위젯들의 사용법과 팁을 알아봅니다.
RecyclerView
RecyclerView는 대용량 데이터셋을 효율적으로 표시하는 위젯입니다.
기본 설정
recyclerView.apply {
layoutManager = LinearLayoutManager(context)
adapter = myAdapter
setHasFixedSize(true)
}
Grid Layout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:listitem="@layout/item_grid" />
Item Decoration
recyclerView.addItemDecoration(
DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
)
Item Animation
recyclerView.itemAnimator = DefaultItemAnimator()
Layout Animation
<!-- res/anim/layout_animation_fall_down.xml -->
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_fall_down"
android:delay="15%"
android:animationOrder="normal" />
recyclerView.layoutAnimation = AnimationUtils.loadLayoutAnimation(
context, R.anim.layout_animation_fall_down
)
스크롤 비활성화
android:nestedScrollingEnabled="false"
DiffUtil 사용
class UserDiffCallback : DiffUtil.ItemCallback<User>() {
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem
}
}
class UserAdapter : ListAdapter<User, UserViewHolder>(UserDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
// ViewHolder 생성
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bind(getItem(position))
}
}
ConstraintLayout
ConstraintLayout은 복잡한 레이아웃을 플랫하게 만들 수 있는 강력한 레이아웃입니다.
Chain 사용
<!-- 수평 체인 -->
<Button
android:id="@+id/button1"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/button2" />
<Button
android:id="@+id/button2"
app:layout_constraintStart_toEndOf="@id/button1"
app:layout_constraintEnd_toEndOf="parent" />
Chain Style 종류:
spread: 균등 분배spread_inside: 양쪽 끝은 붙이고 내부만 균등 분배packed: 중앙에 모음
Guideline
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
Barrier
여러 뷰의 끝에 동적으로 배리어를 설정합니다.
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierDirection="end"
app:constraint_referenced_ids="text1,text2,text3" />
Group
여러 뷰의 visibility를 한번에 제어합니다.
<androidx.constraintlayout.widget.Group
android:id="@+id/group"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
app:constraint_referenced_ids="button1,button2,text1" />
Percent 크기
<View
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintHeight_percent="0.3" />
CoordinatorLayout
CoordinatorLayout은 자식 뷰들 간의 상호작용을 조정합니다.
기본 구조
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!-- 컨텐츠 -->
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Scroll Flags
scroll: 스크롤 시 사라짐enterAlways: 아래로 스크롤하면 바로 나타남enterAlwaysCollapsed: 상단에서만 전체 표시exitUntilCollapsed: 최소 높이까지만 줄어듦snap: 중간 상태 없이 표시/숨김
FAB with Snackbar
FAB이 Snackbar가 나타날 때 자동으로 위로 이동합니다.
Snackbar.make(view, "Message", Snackbar.LENGTH_LONG)
.setAction("Action", null)
.show()
AppBar
Toolbar 설정
setSupportActionBar(binding.toolbar)
supportActionBar?.apply {
setDisplayHomeAsUpEnabled(true)
setHomeAsUpIndicator(R.drawable.ic_menu)
}
Up 버튼 처리
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
}
NavigationDrawer
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header"
app:menu="@menu/drawer_menu" />
navigationView.setNavigationItemSelectedListener { menuItem ->
when (menuItem.itemId) {
R.id.nav_home -> { /* 처리 */ }
}
drawerLayout.closeDrawers()
true
}
TabLayout with ViewPager
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="@color/primary"
app:tabSelectedTextColor="@color/primary" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = "Tab ${position + 1}"
}.attach()
ViewStub
필요할 때만 inflate되는 경량 뷰입니다.
<ViewStub
android:id="@+id/stub"
android:inflatedId="@+id/inflated_layout"
android:layout="@layout/expensive_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
binding.stub.setOnInflateListener { _, inflated ->
// inflated 뷰 사용
}
binding.stub.inflate()
View 관련 팁
descendantFocusability
하위 뷰들의 포커스를 차단합니다.
android:descendantFocusability="blocksDescendants"
clipChildren
자식 뷰가 부모 영역 밖에도 그릴 수 있게 허용합니다.
android:clipChildren="false"
setAddStatesFromChildren
자식 뷰의 상태가 부모 뷰에 영향을 미치게 합니다.
viewGroup.setAddStatesFromChildren(true)
결론
Android의 다양한 UI 위젯들을 적절히 활용하면 복잡한 UI도 효율적으로 구현할 수 있습니다. ConstraintLayout으로 플랫한 뷰 계층을 유지하고, RecyclerView로 대용량 리스트를 처리하며, CoordinatorLayout으로 스크롤 연동 애니메이션을 구현하세요.
Comments