Skip to content

Commit cc02252

Browse files
authored
Combine date label handling for single-line and multi-line (alamkanak#151)
* Combine single-line and multi-line day label drawing into one * Simplify header row updating
1 parent f8f51bd commit cc02252

File tree

13 files changed

+309
-277
lines changed

13 files changed

+309
-277
lines changed

core/src/main/java/com/alamkanak/weekview/DayLabelDrawer.kt

Lines changed: 0 additions & 67 deletions
This file was deleted.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.alamkanak.weekview
2+
3+
import android.graphics.Canvas
4+
import java.util.Calendar
5+
6+
internal class DayLabelsDrawer<T>(
7+
private val config: WeekViewConfigWrapper,
8+
private val cache: WeekViewCache<T>
9+
) : Drawer {
10+
11+
override fun draw(
12+
drawingContext: DrawingContext,
13+
canvas: Canvas
14+
) {
15+
val left = config.timeColumnWidth
16+
val top = 0f
17+
val right = canvas.width.toFloat()
18+
val bottom = config.getTotalHeaderHeight()
19+
20+
canvas.drawInRect(left, top, right, bottom) {
21+
drawingContext.dateRangeWithStartPixels.forEach { (date, startPixel) ->
22+
drawLabel(date, startPixel, this)
23+
}
24+
}
25+
}
26+
27+
private fun drawLabel(day: Calendar, startPixel: Float, canvas: Canvas) {
28+
val key = day.toEpochDays()
29+
val textLayout = cache.dateLabelLayouts[key]
30+
31+
canvas.withTranslation(
32+
x = startPixel + config.widthPerDay / 2,
33+
y = config.headerRowPadding.toFloat()
34+
) {
35+
textLayout.draw(this)
36+
}
37+
}
38+
}

core/src/main/java/com/alamkanak/weekview/HeaderRowHeightUpdater.kt

Lines changed: 0 additions & 42 deletions
This file was deleted.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.alamkanak.weekview
2+
3+
import android.text.StaticLayout
4+
import android.util.SparseArray
5+
import java.util.Calendar
6+
7+
internal class HeaderRowUpdater<T>(
8+
private val config: WeekViewConfigWrapper,
9+
private val cache: WeekViewCache<T>,
10+
private val eventsCacheWrapper: EventsCacheWrapper<T>
11+
) : Updater {
12+
13+
private var previousHorizontalOrigin: Float? = null
14+
private val previousAllDayEventIds = mutableSetOf<Long>()
15+
16+
private val eventsCache: EventsCache<T>
17+
get() = eventsCacheWrapper.get()
18+
19+
override fun isRequired(drawingContext: DrawingContext): Boolean {
20+
val didScrollHorizontally = previousHorizontalOrigin != config.currentOrigin.x
21+
val currentTimeColumnWidth = config.timeTextWidth + config.timeColumnPadding * 2
22+
val didTimeColumnChange = currentTimeColumnWidth != config.timeColumnWidth
23+
val allDayEvents = eventsCache[drawingContext.dateRange]
24+
.filter { it.isAllDay }
25+
.map { it.id }
26+
.toSet()
27+
val didEventsChange = allDayEvents.hashCode() != previousAllDayEventIds.hashCode()
28+
return (didScrollHorizontally || didTimeColumnChange || didEventsChange).also {
29+
previousAllDayEventIds.clear()
30+
previousAllDayEventIds += allDayEvents
31+
}
32+
}
33+
34+
override fun update(drawingContext: DrawingContext) {
35+
val dateLabels = updateDateLabels(drawingContext)
36+
updateHeaderHeight(drawingContext, dateLabels)
37+
}
38+
39+
private fun updateDateLabels(drawingContext: DrawingContext): List<StaticLayout> {
40+
val textLayouts = drawingContext.dateRange.map { date ->
41+
date.toEpochDays() to calculateStaticLayoutForDate(date)
42+
}.toMap()
43+
44+
cache.dateLabelLayouts.clear()
45+
cache.dateLabelLayouts += textLayouts
46+
47+
return textLayouts.values.toList()
48+
}
49+
50+
private fun updateHeaderHeight(
51+
drawingContext: DrawingContext,
52+
dateLabels: List<StaticLayout>
53+
) {
54+
val maximumLayoutHeight = dateLabels.map { it.height.toFloat() }.max() ?: 0f
55+
config.headerTextHeight = maximumLayoutHeight
56+
drawingContext.refreshHeaderHeight()
57+
}
58+
59+
private fun DrawingContext.refreshHeaderHeight() {
60+
val visibleEvents = eventsCache[dateRange].filter { it.isAllDay }
61+
config.hasEventInHeader = visibleEvents.isNotEmpty()
62+
config.refreshHeaderHeight()
63+
}
64+
65+
private fun calculateStaticLayoutForDate(date: Calendar): StaticLayout {
66+
val dayLabel = config.dateFormatter(date)
67+
return dayLabel.toTextLayout(
68+
textPaint = if (date.isToday) config.todayHeaderTextPaint else config.headerTextPaint,
69+
width = config.totalDayWidth.toInt()
70+
)
71+
}
72+
73+
private operator fun <E> SparseArray<E>.plusAssign(elements: Map<Int, E>) {
74+
elements.entries.forEach { put(it.key, it.value) }
75+
}
76+
}

core/src/main/java/com/alamkanak/weekview/MultiLineDayLabelHeightUpdater.kt

Lines changed: 0 additions & 75 deletions
This file was deleted.

core/src/main/java/com/alamkanak/weekview/TextExtensions.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.alamkanak.weekview
22

3+
import android.os.Build.VERSION.SDK_INT
4+
import android.text.Layout
35
import android.text.SpannableStringBuilder
46
import android.text.StaticLayout
7+
import android.text.TextPaint
58
import android.text.style.StyleSpan
69

710
internal val StaticLayout.lineHeight: Int
@@ -10,3 +13,25 @@ internal val StaticLayout.lineHeight: Int
1013
internal fun SpannableStringBuilder.setSpan(
1114
styleSpan: StyleSpan
1215
) = setSpan(styleSpan, 0, length, 0)
16+
17+
internal fun CharSequence.toTextLayout(
18+
textPaint: TextPaint,
19+
width: Int,
20+
alignment: Layout.Alignment = Layout.Alignment.ALIGN_NORMAL,
21+
spacingMultiplier: Float = 1f,
22+
spacingExtra: Float = 0f,
23+
includePad: Boolean = false
24+
) = if (SDK_INT >= 23) {
25+
StaticLayout.Builder
26+
.obtain(this, 0, length, textPaint, width)
27+
.setAlignment(alignment)
28+
.setLineSpacing(spacingExtra, spacingMultiplier)
29+
.setIncludePad(includePad)
30+
.build()
31+
} else {
32+
@Suppress("DEPRECATION")
33+
StaticLayout(this, textPaint, width, alignment, spacingMultiplier, spacingExtra, includePad)
34+
}
35+
36+
internal val StaticLayout.maxLineLength: Float
37+
get() = (0 until lineCount).map { getLineWidth(it) }.max() ?: 0f

0 commit comments

Comments
 (0)