일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 안드로이드 유닛 테스트
- rxjava hot observable
- rxjava cold observable
- 서비스 vs 쓰레드
- 클래스
- 안드로이드 라이선스
- 안드로이드 레트로핏 사용법
- 큐 자바 코드
- ar vr 차이
- Rxjava Observable
- 2022 플러터 안드로이드 스튜디오
- 플러터 설치 2022
- jvm이란
- 스택 큐 차이
- 서비스 쓰레드 차이
- rxjava disposable
- 스택 자바 코드
- ANR이란
- 안드로이드 유닛테스트란
- 안드로이드 레트로핏 crud
- android ar 개발
- 안드로이드 os 구조
- jvm 작동 원리
- 2022 플러터 설치
- android retrofit login
- 객체
- 안드로이드 유닛 테스트 예시
- 자바 다형성
- 안드로이드 라이선스 종류
- 멤버변수
- Today
- Total
나만을 위한 블로그
[Android] 코틀린으로 TabLayout, ViewPager, Fragment를 활용해서 화면 넘기기 구현하기 본문
[Android] 코틀린으로 TabLayout, ViewPager, Fragment를 활용해서 화면 넘기기 구현하기
참깨빵위에참깨빵_ 2021. 2. 10. 19:18예전에 자바로 된 같은 내용의 포스팅을 작성한 적이 있다.
onlyfor-me-blog.tistory.com/197
이번엔 코틀린으로 위 내용을 어떻게 구현하는지에 대해 포스팅하려고 한다.
역시 아래 의존성은 꼭 넣어야 한다. 뷰페이저, 탭 레이아웃, 리사이클러뷰 등의 머티리얼 디자인 요소들을 한방에 바로 사용할 수 있게 해준다.
implementation 'com.google.android.material:material:1.3.0-alpha01'
액티비티의 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AfterLoginActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/after_login_viewpager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="1"
app:layout_constraintHeight_percent=".9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/after_login_tablayout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="1"
app:layout_constraintHeight_percent=".1"
app:tabIndicatorColor="@color/colorPrimaryDark"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/after_login_viewpager">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="메인"/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="검색"/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="내 서재"/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="마이페이지"/>
</com.google.android.material.tabs.TabLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
탭 레이아웃 안에 탭 아이템이 있는 걸 볼 수 있다. 그리고 나는 탭이 바닥에 있는 걸 선호해서 뷰페이저를 위에 두고 그 밑에 탭 레이아웃을 뒀는데, 반대로 탭이 맨 위로 올라가도록 하고 싶다면 뷰페이저와 탭 레이아웃의 위치를 서로 바꾸면 된다. ConstraintLayout을 썼기 때문에 체인만 신경써서 바꿔주면 별 문제없이 작동한다.
이제 각각의 탭 아이템을 누르면 나올 프래그먼트를 만들어준다.
프래그먼트 이름은 각각 MainFragment, SearchFragment, LibraryFragment, MyPageFragment로 지었고, 각 프래그먼트의 xml 및 자바 코드는 아래로 통일했다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="메인 프래그먼트"
android:textSize="20sp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
class MainFragment : Fragment()
{
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View?
{
return inflater.inflate(R.layout.fragment_main, container, false)
}
}
xml 안의 텍스트뷰는 프래그먼트가 제대로 나오는지 확인하기 위해 넣은 텍스트뷰다. 테스트가 끝나면 지우고 다른 뷰나 위젯으로 채워넣으면 된다.
이제 이 포스팅에서 가장 중요한 요소인 어댑터를 만들어보자. 프래그먼트 다 만들어놓고 어댑터 안 만들면 말짱 도루묵이다.
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
class PagerAdapter(manager: FragmentManager): FragmentPagerAdapter(manager)
{
private val fragmentList = ArrayList<Fragment>()
private val titleList = ArrayList<String>()
override fun getItem(position: Int): Fragment = fragmentList[position]
override fun getCount(): Int = titleList.size
override fun getPageTitle(position: Int): CharSequence = titleList[position]
fun addFragment(fragment: Fragment, title: String)
{
fragmentList.add(fragment)
titleList.add(title)
}
}
코틀린은 메서드 몸통 안의 코드가 한 줄로 끝나는 경우 =을 써서 간단하게 메서드를 만들 수 있기 때문에 자바에 비해 상대적으로 코드가 많이 짧다.
위 코드 기준 9, 10번 줄의 ArrayList는 각각 프래그먼트와 제목을 담기 위한 ArrayList고, 맨 밑의 addFragment()의 인자로 프래그먼트와 문자열이 넘어오면 그것들을 각각 ArrayList에 집어넣어서 탭 레이아웃에서 보여지도록 할 때 필요하다.
getItem(), getCount()는 FragmentPagerAdapter를 구현할 경우 단축키를 통해 자동으로 만들 수 있지만, getPageTitle()만은 메서드명을 직접 타이핑해서 재정의해야 한다.
마지막으로 이것을 적용한 액티비티의 코드다.
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.kotlinproj.Library.LibraryFragment
import com.example.kotlinproj.MyPage.MyPageFragment
import com.example.kotlinproj.Search.SearchFragment
import kotlinx.android.synthetic.main.activity_after_login.*
class AfterLoginActivity : AppCompatActivity()
{
private lateinit var context: Context
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_after_login)
val adapter = PagerAdapter(supportFragmentManager)
adapter.addFragment(MainFragment(), "메인")
adapter.addFragment(SearchFragment(), "검색")
adapter.addFragment(LibraryFragment(), "내 서재")
adapter.addFragment(MyPageFragment(), "마이페이지")
after_login_viewpager.adapter = adapter
after_login_tablayout.setupWithViewPager(after_login_viewpager)
}
}
val adapter에 위에서 만든 어댑터를 매핑한 다음 addFragment()를 호출해서 사용할 프래그먼트와 탭 아이템에 붙일 이름을 넣는 걸 볼 수 있다.
그리고 뷰페이저에 어댑터를 붙인 다음, 이 뷰페이저를 탭 레이아웃에 붙이면 끝이다.
여기까지 한 후 빌드해서 확인해보면 아래와 같이 작동한다.
마지막으로 xml에서 탭 레이아웃에 적용할 수 있는 옵션들을 정리한 다음 포스팅을 마무리한다.
코드를 보면 알겠지만 아래 옵션들은 코드에서 어느 것도 적용하지 않았다. 자신의 입맛에 맞춰 사용하자.
app:tabGravity = 탭의 정렬 방식을 지정하는 옵션이다.
- fill : 각 탭의 넓이를 동일한 간격으로 맞춘다
- center : 탭을 가운데로 정렬한다
app:tabMode = 탭의 표시 방식을 지정한다.
- fixed : 모든 탭이 나오도록 설정한다
- scrollable : 탭이 화면 밖을 나갈 경우 스크롤되도록 설정한다. 위 예제에서 이 옵션을 적용할 경우 모든 탭이 왼쪽으로 쏠리는데 언제 쓰는진 모르겠다.
app:tabIconTint = 아이콘 색을 결정한다. 이 예제처럼 커스텀 뷰를 쓰는 경우엔 쓸모없는 옵션이다.
app:tabSelectedTextColor = 탭이 선택됐을 때 글자 색을 바꾸는 옵션이다.
app:tabIndicatorColor = 탭이 선택될 때마다 글자 밑의 얇은 가로선이 나오는 걸 볼 수 있다. 이걸 탭 인디케이터라고 하는데 이것의 색을 바꾸는 옵션이다.
app:tabIndicatorHeight = 탭 인디케이터의 높이를 설정하는 옵션이다.
참고)
developer.android.com/guide/navigation/navigation-swipe-view?hl=ko
'Android' 카테고리의 다른 글
[Android] ScrollView 안의 Constraint Layout에서 뷰가 안 보일 때 해결법 (0) | 2021.02.12 |
---|---|
[Android] 코틀린으로 카카오 로그인 구현하기 (0) | 2021.02.11 |
[Android] 액션바, 상태바 색깔 바꾸는 방법 (0) | 2021.02.09 |
[Android] 안드로이드 스튜디오에서 토큰으로 깃허브 로그인하는 방법 (0) | 2021.02.08 |
[Android] Kotlin으로 레트로핏 사용 시 나오는 에러 해결법 정리 (0) | 2021.02.08 |