LoginSignup
7
4

More than 3 years have passed since last update.

Android + ViewPager2で特定のページ(ポジション)を最初に表示する

Posted at

概要

ViewPager2を使ってカレンダーの実装をしていたのですが、みなさんもご存知だと思うのですがカレンダーは先の月だけではなく前の月もスクロールしたら見れますよね?
それを実装するためにはViewPagerで真ん中辺りのページを開く必要があったのでその方法を記載します。

試してだめだったこと

ViewPager2について調べてみると、currentItemなるものがあり、そちらが現在のItem(ページ)を示すみたいだったので、そこの値をかえればいいのでは?と思い

MainActivity.kt
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)

        val pager = ScreenSlidePagerAdapter(this)
        binding.pager.adapter = pager
        //ここで指定
        binding.pager.currentItem = 4
    }

    private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
        override fun getItemCount(): Int = Int.MAX_VALUE

        override fun createFragment(position: Int): Fragment = CalendarFragment(position)
    }

一旦このように実装してみたのですが、起動してみると一番最初のページスタートになってしまいました...

成功した例

そこで色々調べてみると、ただcurrentItemの値を返るだけではだめなようで、オプションも設定する必要があるとのこと。
https://stackoverflow.com/questions/56311862/viewpager2-default-position
ここの記事では時間を開けて処理を実行してるのですが、おそらくそれはする必要がなく

        binding.pager.setCurrentItem(4, false)

こんな感じで特定のページを指定してあげるだけで良さそう。

実行結果

スクリーンショット 2020-06-26 23.43.41.png

昨日の記事を読んでいた方にはわかると思うのですが、月を表示するようにしたところ10月スタートになりました。(ただこれでは困るので6月の状態で途中スタートにしたい)

(+α)月の表示調節

カレンダーはほぼ無限スクロールなので開始位置はIntのMAX_VALUEの半分スタートにします。

MainActivity.kt
binding.pager.setCurrentItem(Int.MAX_VALUE / 2, false)

そしてフラグメントの方で今月(6月)を真ん中に表示しつつ月のラベルを渡すには

CalendarFragment.kt
        val default = Int.MAX_VALUE / 2
        binding = FragmentCalendarBinding.inflate(inflater, container, false)
        inflater.inflate(R.layout.fragment_calendar, container, false)
        val calendar = Calendar.getInstance()
        val year = 2019
        val month = 6
        val minDay = 1
        calendar.set(year, month, 1)
        calendar.add(Calendar.MONTH, position - default)
        val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
        val blankDays = calendar.get(Calendar.DAY_OF_WEEK)

        val dayArray: MutableList<String> = mutableListOf()
        for (i in minDay until blankDays) {
            dayArray.add("")
        }
        for (i in minDay..maxDay) {
            dayArray.add(i.toString())
        }
        binding.date = dayArray.toTypedArray()
        binding.monthData = (((month - 1 + (position - default)) % 12) + 1).toString() + "月"

        return binding.root

こんな感じに書けばよいかと。

最終的な実行結果

無限スクロール_.gif

左右にスクロールでき、ちゃんと月も正しい値になりました!!

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4