Foggy day

Android(Kotlin) - FlexibleViewPagerHeight when you want to apply wrapContent to viewPager 본문

Android

Android(Kotlin) - FlexibleViewPagerHeight when you want to apply wrapContent to viewPager

jinhan38 2020. 12. 26. 16:48

 

Normal viewpager does not have the wrapContent attribute applied. However, someTimes we need to set height of the ViewPager to match the contents. So I created a CustomViewPager class that extends ViewPager and The CustomViewPager allows you to flexibly set height of ChildViews.

 

To understand this post, you must have a basic understanding of ViewPager.

 

 

Video preview

 

 

 


 

 

1. CustomViewPager

First of all, make a CustomViewPager that extends ViewPager.

 

class CustomViewPager : ViewPager {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

        var heightMeasureSpec = heightMeasureSpec

        var height = 0
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            child.measure(
                widthMeasureSpec,
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            )
            val h = child.measuredHeight
            if (h > height) height = h
        }

        if (height != 0) {
            heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }
}

 

 

 

2. Make 3 ViewPagerItems

The view height and backgroundColor of eash fragment was set diffrently.

 

1) FlexibleFragmentFirst

class FlexibleFragmentFirst : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_flexible_first, container, false)
    }

}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/brand_purple"
    tools:context=".viewPager.flexibleHeight.FlexibleFragmentFirst">

    <View
        android:layout_width="match_parent"
        android:layout_height="300dp"/>

</FrameLayout>

 

2) FlexibleFragmentSecond

class FlexibleFragmentSecond : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_flexible_second, container, false)
    }

}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/brand_green"
    tools:context=".viewPager.flexibleHeight.FlexibleFragmentSecond">

    <View
        android:layout_width="match_parent"
        android:layout_height="200dp"/>
    
</FrameLayout>

 

3) FlexibleFragmentThird

class FlexibleFragmentThird : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_flexible_third, container, false)
    }

}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/brand_blue"
    tools:context=".viewPager.flexibleHeight.FlexibleFragmentThird">

    <View
        android:layout_width="match_parent"
        android:layout_height="100dp" />
    
</FrameLayout>

 

 

 

3. Make a ViewPagerAdapter

class ViewPagerAdapter : FragmentPagerAdapter {

    constructor(fm: FragmentManager) : super(fm)

    private var fragmentArrayList = ArrayList<Fragment>()

    override fun getCount(): Int {
        return fragmentArrayList.size
    }

    override fun getItem(position: Int): Fragment {
        return fragmentArrayList[position]
    }

    fun addItem(fragment: Fragment) {
        this.fragmentArrayList.add(fragment)
    }

}

 

 

 

4. Now, connect the fragments inside the viewpager.

 

1) activity_flexible_view_pager_height.xml

To distinguish it from the viewpager, I made the backgroundColor gray.

The package path name of CustomViewPager will be different depending on your package Name.

<?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"
    android:background="@color/brand_gray"
    android:orientation="vertical"
    tools:context=".viewPager.flexibleHeight.FlexibleViewPagerHeightActivity">


    <com.jinhanexample.viewPager.flexibleHeight.CustomViewPager
        android:id="@+id/flexibleViewPager"
        android:layout_width="match_parent"
        android:layout_height="400dp" />

</LinearLayout>

 

2) FlexibleViewPagerHeightActivity 

If you specify a int value for offscreenPageLimit, the height of the viewpager is set to the fragment with the largest height value. Because I set 300dp on FlexibleFragmentFirst, the height of my ViewPager is set to 300dp.

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

        val first = FlexibleFragmentFirst()
        val second = FlexibleFragmentSecond()
        val third = FlexibleFragmentThird()

        flexibleViewPager.offscreenPageLimit = 3

        val viewPagerAdapter = ViewPagerAdapter(supportFragmentManager)
        viewPagerAdapter.addItem(first)
        viewPagerAdapter.addItem(second)
        viewPagerAdapter.addItem(third)
        flexibleViewPager.adapter = viewPagerAdapter
    }
}