質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

2990閲覧

ViewPager2で表示しているカレンダーの無限スクロールを行う方法

Haruto513

総合スコア52

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2020/10/14 04:06

編集2020/10/14 04:51

実現したいこと

見た目や操作などを好きにカスタマイズしたいので、リサイクラービューとViewPager2を使ってカレンダーを作成しました。
過去未来何年分でもページスクロールによってカレンダーを表示できるようにしたいと考えているのですが、なかなか上手く表示させることができません。

以下のようなコードで、現在カレンダーを画面に表示させています。
実装はこの記事を参考にしています。

・カレンダーの表示

kotlin

1 2class CalendarFragment(private val currentYear: Int, private val currentMonth: Int, val currentDay: Int) : Fragment() { 3 4 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 5 return inflater.inflate(R.layout.fragment_calendar, container, false) 6 } 7 8 override fun onStart() { 9 super.onStart() 10 val text = "${currentYear}${currentMonth}月" 11 current_year_month.text = text 12 13 calendar_view.layoutManager = GridLayoutManager(activity, 7) 14 calendar_view.adapter = CalendarAdapter((activity as MainActivity).calendarItems) 15 createCalendar() 16 } 17 18 private fun createCalendar() { 19 val calendar = Calendar.getInstance() 20 21 val main = activity!! as MainActivity 22 main.currentYear = currentYear 23 main.currentMonth = currentMonth 24 val dayOfMonth = calendar.getActualMaximum(Calendar.DATE) 25 main.calendarItems.clear() 26 for(day in 1..dayOfMonth) { 27 val map = mutableMapOf<String, Any>() 28 map["day"] = day 29 calendar.set(currentYear, currentMonth - 1, day) 30 val week = calendar.get(Calendar.DAY_OF_WEEK) 31 map["dayOfWeek"] = week 32 main.calendarItems.add(map) 33 } 34 val previousMonthDays = main.calendarItems[0]["dayOfWeek"] as Int - 1 35 if(previousMonthDays != 0) { 36 for (count in 1..previousMonthDays) { 37 val map = mutableMapOf<String, Any>("day" to "", "dayOfWeek" to "") 38 main.calendarItems.add(0, map) 39 } 40 } 41 calendar_view.adapter?.notifyDataSetChanged() 42 calendar.clear() 43 } 44 45 private inner class DateCell(view: View): RecyclerView.ViewHolder(view) { 46 var cell: LinearLayout = view.cell 47 var date: TextView = view.tv_date 48 var memo: TextView = view.tv_memo 49 } 50 51 private inner class CalendarAdapter(val items: MutableList<MutableMap<String,Any>>) : RecyclerView.Adapter<DateCell>() { 52 override fun getItemCount(): Int { 53 return items.size 54 } 55 56 override fun onBindViewHolder(holder: DateCell, position: Int) { 57 val item = items[position] 58 holder.date.text = item["day"].toString() 59 if(currentDay.toString() == item["day"].toString()) { 60 holder.date.setTextColor(Color.parseColor("#ff7f50")) 61 }else{ 62 holder.date.setTextColor(Color.BLACK) 63 } 64 } 65 66 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DateCell { 67 return DateCell(layoutInflater.inflate(R.layout.date_cell,parent,false)) 68 } 69 } 70 71

そしてこのカレンダーを表示するページを実装しているのが以下のコードです。
こちらはこのページの記事を参考にしました。

Kotlin

1 2class MainActivity : AppCompatActivity() { 3 4 val calendarItems: MutableList<MutableMap<String,Any>> = mutableListOf() 5 var currentYear = 0 6 var currentMonth = 0 7 var currentDay = 0 8 9 override fun onCreate(savedInstanceState: Bundle?) { 10 super.onCreate(savedInstanceState) 11 setContentView(R.layout.activity_main) 12 13 val pAdapter = PagerAdapter(this) 14 calendar_pager.adapter = pAdapter 15 calendar_pager.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback() { 16 private var jump_position = -1 17 override fun onPageSelected(position: Int) { 18 super.onPageSelected(position) 19 if (position == 0) { 20 jump_position = 3 21 pAdapter.overPrevious() 22 }else if (position == 4) { 23 jump_position = 1 24 pAdapter.overNext() 25 } 26 val itemId = PagerAdapter(this@MainActivity).getItemId(position) 27 Toast.makeText(applicationContext, itemId.toString(), Toast.LENGTH_LONG).show() 28 } 29 override fun onPageScrollStateChanged(state: Int) { 30 super.onPageScrollStateChanged(state) 31 if(state == ViewPager2.SCROLL_STATE_IDLE && jump_position >= 0) { 32 calendar_pager.setCurrentItem(jump_position ,false) 33 jump_position = -1 34 } 35 } 36 }) 37 calendar_pager.currentItem = 2 38 } 39} 40 41var overNext = 2 42var overPrevious = -2 43 44class PagerAdapter(fragment: FragmentActivity): FragmentStateAdapter(fragment) { 45 46 companion object { 47 val calendar = Calendar.getInstance() 48 val currentYear = calendar.get(Calendar.YEAR) 49 val currentMonth = calendar.get(Calendar.MONTH) + 1 50 val currentDay = calendar.get(Calendar.DATE) 51 } 52 53 //初期データ 54 val fmList = mutableListOf<Fragment>( 55 CalendarFragment(currentYear,currentMonth - 2,0), 56 CalendarFragment(currentYear,currentMonth - 1,0), 57 CalendarFragment(currentYear,currentMonth,currentDay), 58 CalendarFragment(currentYear,currentMonth + 1,0), 59 CalendarFragment(currentYear,currentMonth + 2,0) 60 ) 61 62 override fun createFragment(position: Int): Fragment { 63 return when(position) { 64 0 -> fmList[0] 65 1 -> fmList[1] 66 2 -> fmList[2] 67 3 -> fmList[3] 68 4 -> fmList[4] 69 else -> fmList[2] 70 } 71 } 72 73 override fun getItemId(position: Int): Long { 74 return super.getItemId(position) 75 } 76 77 override fun getItemCount() = 5 78 79 //初期データにする 80 fun initializeData() { 81 fmList.clear() 82 for (i in 0 until 5) { 83 fmList.add(CalendarFragment(currentYear,currentMonth - 2,0)) 84 fmList.add(CalendarFragment(currentYear,currentMonth - 1,0)) 85 fmList.add(CalendarFragment(currentYear,currentMonth,currentDay)) 86 fmList.add(CalendarFragment(currentYear,currentMonth + 1,0)) 87 fmList.add(CalendarFragment(currentYear,currentMonth + 2,0)) 88 } 89 } 90 91 //0にたどり着き、3に飛んだ時、後ろの三つのデータを削除する。そして前三つを補填する 92 fun overNext() { 93 for (index in 1..3) { 94 fmList.removeAt(fmList.size - 1) 95 } 96 for (index in 1..3) { 97 overNext += 1 98 println(currentMonth + overNext) 99 if(currentMonth + overNext > 12) { 100 fmList.add( 101 fmList.size - 1, 102 CalendarFragment(currentYear + 1, (currentMonth + overNext) - 12, 0) 103 ) 104 }else { 105 fmList.add( 106 fmList.size - 1, 107 CalendarFragment(currentYear, currentMonth + overNext, 0) 108 ) 109 } 110 } 111 } 112 113 //4にたどり着き、1に飛んだ時、前の三つのデータを削除する。そして、後ろ三つを補填する。 114 fun overPrevious() { 115 for (index in 1..3) { 116 fmList.removeAt(0) 117 } 118 for (index in 1..3) { 119 overPrevious -= 1 120 println(currentMonth + overPrevious) 121 if(currentMonth + overPrevious < 1) { 122 fmList.add(CalendarFragment(currentYear - 1, 12 - (currentMonth + overPrevious), 0)) 123 }else{ 124 fmList.add(CalendarFragment(currentYear, currentMonth + overPrevious, 0)) 125 } 126 } 127 128 } 129 130} 131

しかし、ページを延々とスクロールすることはできるのですが、3カ月以降と以前のカレンダーのデータが生成されず、どうしたものかと悩んでいます。
どのようにすれば、3カ月以降と以前のカレンダーを表示できるようになるでしょうか。
どなたかにアドバイスを頂けたら幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

フラグメントを配列に入れるのではなく、ViewPager2をリサイクラービューのようにして実装したところ、上手く行きました。

Kotlin

1 2 val calendarInfo: MutableList<MutableMap<String,Any>> = mutableListOf() 3 4  calendar_pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { 5 private var jumpPosition = -1 6 override fun onPageSelected(position: Int) { 7 super.onPageSelected(position) 8 if (position == 0) { 9 jumpPosition = 3 10 rewindData() 11 } else if (position == 4) { 12 jumpPosition = 1 13 forwardData() 14 } 15 } 16 17 override fun onPageScrollStateChanged(state: Int) { 18 super.onPageScrollStateChanged(state) 19 if (state == ViewPager.SCROLL_STATE_IDLE && jumpPosition >= 0) { 20 calendar_pager.adapter?.notifyDataSetChanged() 21 calendar_pager.setCurrentItem(jumpPosition, false) 22 jumpPosition = -1 23 } 24 } 25 26 }) 27 28 29 30 fun forwardData() { 31 for (i in 1..3) { 32 calendarInfo.removeAt(0) 33 } 34 35 for (i in 1..3) { 36 val nextMonth = calendarInfo[calendarInfo.size - 1]["month"] as Int + 1 37 val currentYear = calendarInfo[calendarInfo.size - 1]["year"] as Int 38 if(nextMonth > 12) { 39 calendarInfo.add(mutableMapOf("year" to currentYear + 1, "month" to nextMonth - 12, "day" to 0)) 40 }else { 41 calendarInfo.add(mutableMapOf("year" to currentYear, "month" to nextMonth, "day" to 0)) 42 } 43 } 44 } 45 46 fun rewindData() { 47 for (i in 1..3) { 48 calendarInfo.removeAt(5 - i) 49 } 50 51 for (i in 1..3) { 52 val previousMonth = calendarInfo[0]["month"] as Int - 1 53 val currentYear = calendarInfo[0]["year"] as Int 54 if(previousMonth < 1) { 55 calendarInfo.add(0, mutableMapOf("year" to currentYear - 1, "month" to 12 - previousMonth, "day" to 0)) 56 }else{ 57 calendarInfo.add(0, mutableMapOf("year" to currentYear, "month" to previousMonth, "day" to 0)) 58 } 59 } 60 } 61 62

投稿2020/10/14 08:16

Haruto513

総合スコア52

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問