概要
ViewPager2を使ってカレンダーの実装をしていたのですが、みなさんもご存知だと思うのですがカレンダーは先の月だけではなく前の月もスクロールしたら見れますよね?
それを実装するためにはViewPagerで真ん中辺りのページを開く必要があったのでその方法を記載します。
試してだめだったこと
ViewPager2について調べてみると、currentItemなるものがあり、そちらが現在のItem(ページ)を示すみたいだったので、そこの値をかえればいいのでは?と思い
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)
こんな感じで特定のページを指定してあげるだけで良さそう。
実行結果

昨日の記事を読んでいた方にはわかると思うのですが、月を表示するようにしたところ10月スタートになりました。(ただこれでは困るので6月の状態で途中スタートにしたい)
(+α)月の表示調節
カレンダーはほぼ無限スクロールなので開始位置はIntのMAX_VALUEの半分スタートにします。
binding.pager.setCurrentItem(Int.MAX_VALUE / 2, false)
そしてフラグメントの方で今月(6月)を真ん中に表示しつつ月のラベルを渡すには
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
こんな感じに書けばよいかと。
最終的な実行結果
左右にスクロールでき、ちゃんと月も正しい値になりました!!