Skip to content

Commit aea1992

Browse files
authored
Allow overriding calculateExtraLayoutSpace in the layout manager (#601)
1 parent 0e1b654 commit aea1992

File tree

9 files changed

+83
-7
lines changed

9 files changed

+83
-7
lines changed

view/api/view.api

+14
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public class com/kizitonwose/calendar/view/CalendarView : androidx/recyclerview/
1414
public final fun getDayBinder ()Lcom/kizitonwose/calendar/view/MonthDayBinder;
1515
public final fun getDaySize ()Lcom/kizitonwose/calendar/view/DaySize;
1616
public final fun getDayViewResource ()I
17+
public final fun getLayoutHelper ()Lcom/kizitonwose/calendar/view/LayoutHelper;
1718
public final fun getMonthFooterBinder ()Lcom/kizitonwose/calendar/view/MonthHeaderFooterBinder;
1819
public final fun getMonthFooterResource ()I
1920
public final fun getMonthHeaderBinder ()Lcom/kizitonwose/calendar/view/MonthHeaderFooterBinder;
@@ -39,6 +40,7 @@ public class com/kizitonwose/calendar/view/CalendarView : androidx/recyclerview/
3940
public final fun setDayBinder (Lcom/kizitonwose/calendar/view/MonthDayBinder;)V
4041
public final fun setDaySize (Lcom/kizitonwose/calendar/view/DaySize;)V
4142
public final fun setDayViewResource (I)V
43+
public final fun setLayoutHelper (Lcom/kizitonwose/calendar/view/LayoutHelper;)V
4244
public final fun setMonthFooterBinder (Lcom/kizitonwose/calendar/view/MonthHeaderFooterBinder;)V
4345
public final fun setMonthFooterResource (I)V
4446
public final fun setMonthHeaderBinder (Lcom/kizitonwose/calendar/view/MonthHeaderFooterBinder;)V
@@ -72,6 +74,14 @@ public final class com/kizitonwose/calendar/view/DaySize : java/lang/Enum {
7274
public static fun values ()[Lcom/kizitonwose/calendar/view/DaySize;
7375
}
7476

77+
public abstract interface class com/kizitonwose/calendar/view/LayoutHelper {
78+
public abstract fun calculateExtraLayoutSpace (Landroidx/recyclerview/widget/RecyclerView$State;[I)V
79+
}
80+
81+
public final class com/kizitonwose/calendar/view/LayoutHelper$DefaultImpls {
82+
public static fun calculateExtraLayoutSpace (Lcom/kizitonwose/calendar/view/LayoutHelper;Landroidx/recyclerview/widget/RecyclerView$State;[I)V
83+
}
84+
7585
public final class com/kizitonwose/calendar/view/MarginValues {
7686
public static final field Companion Lcom/kizitonwose/calendar/view/MarginValues$Companion;
7787
public fun <init> ()V
@@ -128,6 +138,7 @@ public class com/kizitonwose/calendar/view/WeekCalendarView : androidx/recyclerv
128138
public final fun getDayBinder ()Lcom/kizitonwose/calendar/view/WeekDayBinder;
129139
public final fun getDaySize ()Lcom/kizitonwose/calendar/view/DaySize;
130140
public final fun getDayViewResource ()I
141+
public final fun getLayoutHelper ()Lcom/kizitonwose/calendar/view/LayoutHelper;
131142
public final fun getScrollPaged ()Z
132143
public final fun getWeekFooterBinder ()Lcom/kizitonwose/calendar/view/WeekHeaderFooterBinder;
133144
public final fun getWeekFooterResource ()I
@@ -148,6 +159,7 @@ public class com/kizitonwose/calendar/view/WeekCalendarView : androidx/recyclerv
148159
public final fun setDayBinder (Lcom/kizitonwose/calendar/view/WeekDayBinder;)V
149160
public final fun setDaySize (Lcom/kizitonwose/calendar/view/DaySize;)V
150161
public final fun setDayViewResource (I)V
162+
public final fun setLayoutHelper (Lcom/kizitonwose/calendar/view/LayoutHelper;)V
151163
public final fun setScrollPaged (Z)V
152164
public final fun setWeekFooterBinder (Lcom/kizitonwose/calendar/view/WeekHeaderFooterBinder;)V
153165
public final fun setWeekFooterResource (I)V
@@ -187,6 +199,7 @@ public class com/kizitonwose/calendar/view/YearCalendarView : androidx/recyclerv
187199
public final fun getDayBinder ()Lcom/kizitonwose/calendar/view/MonthDayBinder;
188200
public final fun getDaySize ()Lcom/kizitonwose/calendar/view/DaySize;
189201
public final fun getDayViewResource ()I
202+
public final fun getLayoutHelper ()Lcom/kizitonwose/calendar/view/LayoutHelper;
190203
public final fun getMonthColumns ()I
191204
public final fun getMonthFooterBinder ()Lcom/kizitonwose/calendar/view/MonthHeaderFooterBinder;
192205
public final fun getMonthFooterResource ()I
@@ -225,6 +238,7 @@ public class com/kizitonwose/calendar/view/YearCalendarView : androidx/recyclerv
225238
public final fun setDayBinder (Lcom/kizitonwose/calendar/view/MonthDayBinder;)V
226239
public final fun setDaySize (Lcom/kizitonwose/calendar/view/DaySize;)V
227240
public final fun setDayViewResource (I)V
241+
public final fun setLayoutHelper (Lcom/kizitonwose/calendar/view/LayoutHelper;)V
228242
public final fun setMonthColumns (I)V
229243
public final fun setMonthFooterBinder (Lcom/kizitonwose/calendar/view/MonthHeaderFooterBinder;)V
230244
public final fun setMonthFooterResource (I)V

view/src/main/java/com/kizitonwose/calendar/view/CalendarView.kt

+6
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,12 @@ public open class CalendarView : RecyclerView {
183183
}
184184
}
185185

186+
/**
187+
* Interface with methods that can be overridden
188+
* in the internal layout manager.
189+
*/
190+
public var layoutHelper: LayoutHelper? = null
191+
186192
private val scrollListenerInternal = object : OnScrollListener() {
187193
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {}
188194
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.kizitonwose.calendar.view
2+
3+
import androidx.recyclerview.widget.LinearLayoutManager
4+
import androidx.recyclerview.widget.RecyclerView
5+
import com.kizitonwose.calendar.view.internal.CalendarLayoutManager
6+
7+
/**
8+
* An interface with methods that can be overridden
9+
* in the internal [LinearLayoutManager].
10+
*/
11+
public interface LayoutHelper {
12+
/**
13+
* Calculates the amount of extra space (in pixels) that should be laid out by
14+
* [CalendarLayoutManager] and stores the result in [extraLayoutSpace].
15+
* [extraLayoutSpace[0]] should be used for the extra space at the top in a vertical
16+
* calendar or left in a horizontal calendar, and extraLayoutSpace[1] should be used for
17+
* the extra space at the bottom in a vertical calendar or right in a horizontal calendar.
18+
*
19+
* @see [LinearLayoutManager.calculateExtraLayoutSpace]
20+
*/
21+
public fun calculateExtraLayoutSpace(state: RecyclerView.State, extraLayoutSpace: IntArray) {}
22+
}

view/src/main/java/com/kizitonwose/calendar/view/WeekCalendarView.kt

+6
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ public open class WeekCalendarView : RecyclerView {
150150
}
151151
}
152152

153+
/**
154+
* Interface with methods that can be overridden
155+
* in the internal layout manager.
156+
*/
157+
public var layoutHelper: LayoutHelper? = null
158+
153159
private val scrollListenerInternal = object : OnScrollListener() {
154160
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {}
155161
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {

view/src/main/java/com/kizitonwose/calendar/view/YearCalendarView.kt

+6
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,12 @@ public open class YearCalendarView : RecyclerView {
326326
}
327327
}
328328

329+
/**
330+
* Interface with methods that can be overridden
331+
* in the internal layout manager.
332+
*/
333+
public var layoutHelper: LayoutHelper? = null
334+
329335
private val scrollListenerInternal = object : OnScrollListener() {
330336
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {}
331337
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {

view/src/main/java/com/kizitonwose/calendar/view/internal/CalendarLayoutManager.kt

+15
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.view.ViewGroup
66
import androidx.recyclerview.widget.LinearLayoutManager
77
import androidx.recyclerview.widget.LinearSmoothScroller
88
import androidx.recyclerview.widget.RecyclerView
9+
import com.kizitonwose.calendar.view.LayoutHelper
910
import com.kizitonwose.calendar.view.MarginValues
1011

1112
internal abstract class CalendarLayoutManager<IndexData, DayData>(
@@ -18,6 +19,7 @@ internal abstract class CalendarLayoutManager<IndexData, DayData>(
1819
abstract fun getItemMargins(): MarginValues
1920
abstract fun scrollPaged(): Boolean
2021
abstract fun notifyScrollListenerIfNeeded()
22+
abstract fun getLayoutHelper(): LayoutHelper?
2123

2224
fun scrollToIndex(indexData: IndexData) {
2325
val position = getaItemAdapterPosition(indexData)
@@ -70,6 +72,19 @@ internal abstract class CalendarLayoutManager<IndexData, DayData>(
7072
}
7173
}
7274

75+
override fun calculateExtraLayoutSpace(state: RecyclerView.State, extraLayoutSpace: IntArray) {
76+
val layoutHelper = getLayoutHelper()
77+
if (layoutHelper != null) {
78+
layoutHelper.calculateExtraLayoutSpace(state, extraLayoutSpace)
79+
// If the interface is provided but the method is not overridden.
80+
if (extraLayoutSpace.isEmpty()) {
81+
super.calculateExtraLayoutSpace(state, extraLayoutSpace)
82+
}
83+
} else {
84+
super.calculateExtraLayoutSpace(state, extraLayoutSpace)
85+
}
86+
}
87+
7388
private inner class CalendarSmoothScroller(position: Int, val day: DayData?) :
7489
LinearSmoothScroller(calView.context) {
7590
init {

view/src/main/java/com/kizitonwose/calendar/view/internal/monthcalendar/MonthCalendarLayoutManager.kt

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.kizitonwose.calendar.view.internal.monthcalendar
22

33
import com.kizitonwose.calendar.core.CalendarDay
44
import com.kizitonwose.calendar.view.CalendarView
5+
import com.kizitonwose.calendar.view.LayoutHelper
56
import com.kizitonwose.calendar.view.MarginValues
67
import com.kizitonwose.calendar.view.internal.CalendarLayoutManager
78
import com.kizitonwose.calendar.view.internal.dayTag
@@ -18,4 +19,5 @@ internal class MonthCalendarLayoutManager(private val calView: CalendarView) :
1819
override fun getItemMargins(): MarginValues = calView.monthMargins
1920
override fun scrollPaged(): Boolean = calView.scrollPaged
2021
override fun notifyScrollListenerIfNeeded() = adapter.notifyMonthScrollListenerIfNeeded()
22+
override fun getLayoutHelper(): LayoutHelper? = calView.layoutHelper
2123
}

view/src/main/java/com/kizitonwose/calendar/view/internal/weekcalendar/WeekCalendarLayoutManager.kt

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.kizitonwose.calendar.view.internal.weekcalendar
22

3+
import com.kizitonwose.calendar.view.LayoutHelper
34
import com.kizitonwose.calendar.view.MarginValues
45
import com.kizitonwose.calendar.view.WeekCalendarView
56
import com.kizitonwose.calendar.view.internal.CalendarLayoutManager
@@ -17,4 +18,5 @@ internal class WeekCalendarLayoutManager(private val calView: WeekCalendarView)
1718
override fun getItemMargins(): MarginValues = calView.weekMargins
1819
override fun scrollPaged(): Boolean = calView.scrollPaged
1920
override fun notifyScrollListenerIfNeeded() = adapter.notifyWeekScrollListenerIfNeeded()
21+
override fun getLayoutHelper(): LayoutHelper? = calView.layoutHelper
2022
}

view/src/main/java/com/kizitonwose/calendar/view/internal/yearcalendar/YearCalendarLayoutManager.kt

+10-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.view.View
55
import android.view.ViewGroup
66
import androidx.recyclerview.widget.LinearSmoothScroller
77
import com.kizitonwose.calendar.core.CalendarDay
8+
import com.kizitonwose.calendar.view.LayoutHelper
89
import com.kizitonwose.calendar.view.MarginValues
910
import com.kizitonwose.calendar.view.YearCalendarView
1011
import com.kizitonwose.calendar.view.internal.CalendarLayoutManager
@@ -24,6 +25,8 @@ internal class YearCalendarLayoutManager(private val calView: YearCalendarView)
2425
override fun getItemMargins(): MarginValues = calView.yearMargins
2526
override fun scrollPaged(): Boolean = calView.scrollPaged
2627
override fun notifyScrollListenerIfNeeded() = adapter.notifyYearScrollListenerIfNeeded()
28+
override fun getLayoutHelper(): LayoutHelper? = calView.layoutHelper
29+
2730
fun smoothScrollToMonth(month: YearMonth) {
2831
val indexPosition = adapter.getAdapterPosition(month)
2932
if (indexPosition == NO_INDEX) return
@@ -42,18 +45,18 @@ internal class YearCalendarLayoutManager(private val calView: YearCalendarView)
4245
calView.post {
4346
val itemView = calView.findViewHolderForAdapterPosition(indexPosition)?.itemView
4447
?: return@post
45-
val offset = calculateDayViewOffsetInParent(month, itemView)
48+
val offset = calculateMonthViewOffsetInParent(month, itemView)
4649
scrollToPositionWithOffset(indexPosition, -offset)
4750
calView.post { notifyScrollListenerIfNeeded() }
4851
}
4952
}
5053
}
5154

52-
private fun calculateDayViewOffsetInParent(month: YearMonth, itemView: View): Int {
53-
val dayView = itemView.findViewWithTag<View>(monthTag(month)) ?: return 0
55+
private fun calculateMonthViewOffsetInParent(month: YearMonth, itemView: View): Int {
56+
val monthView = itemView.findViewWithTag<View>(monthTag(month)) ?: return 0
5457
val rect = Rect()
55-
dayView.getDrawingRect(rect)
56-
(itemView as ViewGroup).offsetDescendantRectToMyCoords(dayView, rect)
58+
monthView.getDrawingRect(rect)
59+
(itemView as ViewGroup).offsetDescendantRectToMyCoords(monthView, rect)
5760
return if (orientation == VERTICAL) rect.top else rect.left
5861
}
5962

@@ -72,7 +75,7 @@ internal class YearCalendarLayoutManager(private val calView: YearCalendarView)
7275
if (month == null) {
7376
return dy
7477
}
75-
val offset = calculateDayViewOffsetInParent(month, view)
78+
val offset = calculateMonthViewOffsetInParent(month, view)
7679
return dy - offset
7780
}
7881

@@ -81,7 +84,7 @@ internal class YearCalendarLayoutManager(private val calView: YearCalendarView)
8184
if (month == null) {
8285
return dx
8386
}
84-
val offset = calculateDayViewOffsetInParent(month, view)
87+
val offset = calculateMonthViewOffsetInParent(month, view)
8588
return dx - offset
8689
}
8790
}

0 commit comments

Comments
 (0)