본문 바로가기

Android/Android Lecture

안드로이드 강의 9. TabLayout & ViewPager 와 BaseActivity사용

아령하세요~잇! 효그니에요!!

오늘은 안드로이드 ViewPager와 TabLayout관련한 강의를 할 생각이에요!

TabLayout은 카카오톡이나 구글플레이 등에서 흔하게 볼 수 있는데 탭 메뉴를 표현하는것이에요 

(Ex. FaceBook, Google PlayStore 등...)

그리고 탭을 누를 때마다 아래 화면이 마치 페이지가 넘어가듯이 변하는데요, 이 부분이 ViewPager입니다!

그럼 안스를 켜볼까요?

 

우선은 Build.Gradle에 

implementation 'com.android.support:design:28.0.0'

를 implementation을 해줍니다!

 

 

그리고 전 차시에서 만들었던 Fragment를 또한번 생성해주세요!

class TestFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        return inflater.inflate(R.layout.fragment_test, container, false)
    }
}

이렇게요!

그리고 activity_main에 

<?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:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="#03a9f4"
            app:layout_scrollFlags="scroll|enterAlways">
            <TextView
                android:id="@+id/toolbar_tv"
                android:textSize="20sp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                android:textColor="@android:color/white" />

        </android.support.v7.widget.Toolbar>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabBackground="@android:color/white"
            app:tabIndicatorColor="#c862ff"
            app:tabSelectedTextColor="#03a9f4" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</LinearLayout>

이렇게 생성해줄까요?

그 다음 MainActivity로 넘어가서

class MainActivity : BaseActivity() {

    override var viewId: Int = R.layout.activity_main
    override var toolbarId: Int? = R.id.toolbar
    private lateinit var toast: Toast
    private var backKeyPressedTime: Long = 200
    private var mViewPager: ViewPager? = null

    @SuppressLint("ShowToast")
    override fun onCreate() {
        showActionBar()


        mViewPager = findViewById(R.id.viewPager)
        mViewPager!!.adapter = PagerAdapter(supportFragmentManager)
        mViewPager!!.currentItem = 0

        val tabLayout = findViewById<View>(R.id.tabs) as TabLayout
        tabLayout.setupWithViewPager(mViewPager)


        tabLayout.getTabAt(0)!!.text = "1"
        tabLayout.getTabAt(1)!!.text = "2"
        tabLayout.getTabAt(2)!!.text = "3"
        tabLayout.getTabAt(3)!!.text = "4"

        mViewPager!!.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))
        tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab) = tab.select()

            override fun onTabUnselected(tab: TabLayout.Tab) {

            }

            override fun onTabReselected(tab: TabLayout.Tab) {

            }
        })

    }

    override fun onBackPressed() {

        if (System.currentTimeMillis() > backKeyPressedTime + 500) {
            backKeyPressedTime = System.currentTimeMillis()
            toast.show()
            return
        }

        if (System.currentTimeMillis() <= backKeyPressedTime + 500) {
            toast.cancel()
            this.finish()
        }
    }

    inner class PagerAdapter(supportFragmentManager: FragmentManager) : FragmentStatePagerAdapter(supportFragmentManager) {

        override fun getItem(position: Int): Fragment? {

            return when (position) {
                0 ->
                    TestFragment()
                1 ->
                    TestFragment()
                2 ->
                    TestFragment()
                3 ->
                    TestFragment()
                else ->
                    null
            }
        }

        override fun getCount(): Int = 4
    }
}

이렇게 생성해줍니다! 

viewpager와 tab layout을 이어줄 adapter가 바로 PagerAdapter에요! 

FragmentStatePagerAdapter를 상속받아서 FragmentManager 형식의 상위 생성자를 호출해주는 형식이에요!

그리고 getItem 메소드와 getCount 메소드를 오버라이드하여 구현해줘요!

그런데 여러분의 MainActivity에선 에러가 날꺼에요.

왜일까요?

바로 BaseActivity가 없어서에요

많은 개발자들이 BaseActivity 를 만들어 배포하고 이를통해서 컨트롤 하는데 대부분 이유는 LifeCycle에 

맞춰 편리하게 코드하기 위해서 사용을 하는거에요!

이런 BaseActivity 저같은경우는 

abstract class BaseActivity : AppCompatActivity() {

    private var instance: BaseActivity? = null
    private var mToolbarHeight = 0
    private var mAnimDuration = 0

    private var mVaActionBar: ValueAnimator? = null

    protected abstract var viewId: Int
    protected abstract var toolbarId: Int?

    protected abstract fun onCreate()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        instance = this

        setContentView(viewId)

        if (toolbarId != null)
            findViewById<Toolbar>(toolbarId!!).let {
                setSupportActionBar(it)
                supportActionBar?.setDisplayShowTitleEnabled(false)
            }
        onCreate()
    }

    fun hideActionBar() {
        toolbarId?.let {
            val mToolbar = findViewById<Toolbar>(toolbarId!!)

            if (mToolbarHeight == 0)
                mToolbarHeight = mToolbar.height

            if (mVaActionBar != null && mVaActionBar!!.isRunning)
                return@let

            mVaActionBar = ValueAnimator.ofInt(mToolbarHeight, 0)
            mVaActionBar?.addUpdateListener {
                ValueAnimator.AnimatorUpdateListener { animation ->
                    mToolbar.layoutParams.height = animation.animatedValue as Int
                    mToolbar.requestLayout()
                }
            }

            mVaActionBar?.addUpdateListener {
                object : AnimatorListenerAdapter() {
                    override fun onAnimationEnd(animation: Animator?) {
                        supportActionBar?.hide()
                    }
                }
            }

            mVaActionBar!!.duration = mAnimDuration.toLong()
            mVaActionBar?.start()

        }
    }

    fun showActionBar() {
        toolbarId?.let {
            val mToolbar = findViewById<Toolbar>(toolbarId!!)

            if (mVaActionBar != null && mVaActionBar!!.isRunning)
                return@let

            mVaActionBar = ValueAnimator.ofInt(0, mToolbarHeight)
            mVaActionBar?.addUpdateListener {
                ValueAnimator.AnimatorUpdateListener { animation ->
                    mToolbar.layoutParams.height = animation.animatedValue as Int
                    mToolbar.requestLayout()
                }
            }

            mVaActionBar?.addUpdateListener {
                object : AnimatorListenerAdapter() {
                    override fun onAnimationEnd(animation: Animator?) {
                        supportActionBar?.hide()
                    }
                }
            }

            mVaActionBar!!.duration = mAnimDuration.toLong()
            mVaActionBar?.start()

        }
    }
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home -> finish()
        }
        return super.onOptionsItemSelected(item)
    }
    // <- 버튼 누를 시 뒤로가기

}

이런식으로 사용하는데 앞으로 강의할때 자주 보일테니 꼭 참고해주세요!

이제 이 BaseActivity를 생성하게되면!

에러가 사라지고...실행을 하게되면?

이렇게 이쁘게 생성된답니다!

근데 안에 아무것도 없어서 밋밋하네요...

다음시간부터는 이 내부를 채울만한 멋있는 뷰부터 서버 연동 등을 배워볼거에요! 그럼 다음시간에 만나요!

여러분 정말 수고하셨어요~!