Skip to content

Commit 9bc3f03

Browse files
authored
Add week number feature (alamkanak#146)
* Add week number feature * Fix issue where week number didn't consider manually set first day of week
1 parent 8860c12 commit 9bc3f03

File tree

9 files changed

+138
-6
lines changed

9 files changed

+138
-6
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ internal val Calendar.dayOfWeek: Int
4343
internal val Calendar.dayOfMonth: Int
4444
get() = get(Calendar.DAY_OF_MONTH)
4545

46+
internal val Calendar.weekOfYear: Int
47+
get() = get(Calendar.WEEK_OF_YEAR)
48+
4649
internal val Calendar.month: Int
4750
get() = get(Calendar.MONTH)
4851

@@ -191,8 +194,10 @@ internal fun firstDayOfYear(): Calendar {
191194
}
192195
}
193196

194-
internal fun getDateRange(start: Int, end: Int): List<Calendar> {
195-
return (start..end).map { today() + Days(it - 1) }
197+
internal fun WeekViewConfigWrapper.createDateRange(start: Int, end: Int): List<Calendar> {
198+
val firstDate = today()
199+
firstDate.firstDayOfWeek = firstDayOfWeek
200+
return (start..end).map { firstDate + Days(it - 1) }
196201
}
197202

198203
internal val Calendar.isWeekend: Boolean

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal class DrawingContext(
2929
val modifiedEnd = if (isNotScrolling) end - 1 else end
3030

3131
dateRange.clear()
32-
dateRange += getDateRange(start, modifiedEnd)
32+
dateRange += config.createDateRange(start, modifiedEnd)
3333

3434
updateStartPixels()
3535

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

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

33
import android.graphics.Canvas
4+
import android.graphics.Paint
5+
import android.graphics.Rect
6+
import android.graphics.RectF
7+
import kotlin.math.roundToInt
48

59
internal class HeaderRowDrawer<T : Any>(
610
private val view: WeekView<T>,
@@ -14,9 +18,50 @@ internal class HeaderRowDrawer<T : Any>(
1418
val width = view.width.toFloat()
1519
canvas.drawRect(0f, 0f, width, config.headerHeight, config.headerBackgroundPaint)
1620

21+
if (config.showWeekNumber) {
22+
canvas.drawWeekNumber(drawingContext)
23+
}
24+
1725
if (config.showHeaderRowBottomLine) {
18-
val top = config.headerHeight - config.headerRowBottomLineWidth
19-
canvas.drawLine(0f, top, width, top, config.headerRowBottomLinePaint)
26+
val y = config.headerHeight - config.headerRowBottomLineWidth
27+
canvas.drawLine(0f, y, width, y, config.headerRowBottomLinePaint)
2028
}
2129
}
30+
31+
private fun Canvas.drawWeekNumber(drawingContext: DrawingContext) {
32+
val weekNumber = drawingContext.dateRange.first().weekOfYear.toString()
33+
34+
val bounds = config.weekNumberBounds
35+
val textPaint = config.weekNumberTextPaint
36+
37+
val textHeight = textPaint.textHeight
38+
val textOffset = (textHeight / 2f).roundToInt() - textPaint.descent().roundToInt()
39+
40+
val width = textPaint.getTextBounds("52").width() * 2.5f
41+
val height = textHeight * 1.5f
42+
43+
val backgroundRect = RectF(
44+
bounds.centerX() - width / 2f,
45+
bounds.centerY() - height / 2f,
46+
bounds.centerX() + width / 2f,
47+
bounds.centerY() + height / 2f
48+
)
49+
50+
drawRect(bounds, config.headerBackgroundPaint)
51+
52+
val backgroundPaint = config.weekNumberBackgroundPaint
53+
val radius = config.weekNumberBackgroundCornerRadius.toFloat()
54+
drawRoundRect(backgroundRect, radius, radius, backgroundPaint)
55+
56+
drawText(weekNumber, bounds.centerX(), bounds.centerY() + textOffset, textPaint)
57+
}
58+
}
59+
60+
internal val Paint.textHeight: Int
61+
get() = (descent() - ascent()).roundToInt()
62+
63+
internal fun Paint.getTextBounds(text: String): Rect {
64+
val rect = Rect()
65+
getTextBounds(text, 0, text.length, rect)
66+
return rect
2267
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ internal class WeekViewConfig(
4545
var todayHeaderTextColor: Int = 0
4646
var singleLineHeader: Boolean = false
4747

48+
// Week number
49+
var showWeekNumber: Boolean = false
50+
var weekNumberTextColor: Int = 0
51+
var weekNumberTextSize: Int = 0
52+
var weekNumberBackgroundColor: Int = 0
53+
var weekNumberBackgroundCornerRadius: Int = 0
54+
4855
// Event chips
4956
var eventCornerRadius: Int = 0
5057
var eventTextSize: Int = 0
@@ -158,6 +165,13 @@ internal class WeekViewConfig(
158165
todayHeaderTextColor = getColor(R.styleable.WeekView_todayHeaderTextColor, Defaults.HIGHLIGHT_COLOR)
159166
singleLineHeader = getBoolean(R.styleable.WeekView_singleLineHeader, true)
160167

168+
// Week number
169+
showWeekNumber = a.getBoolean(R.styleable.WeekView_showWeekNumber, false)
170+
weekNumberTextColor = a.getColor(R.styleable.WeekView_weekNumberTextColor, Color.WHITE)
171+
weekNumberTextSize = a.getDimensionPixelSize(R.styleable.WeekView_weekNumberTextSize, Defaults.textSize(context))
172+
weekNumberBackgroundColor = a.getColor(R.styleable.WeekView_weekNumberBackgroundColor, Color.LTGRAY)
173+
weekNumberBackgroundCornerRadius = a.getDimensionPixelSize(R.styleable.WeekView_weekNumberBackgroundCornerRadius, 0)
174+
161175
// Event chips
162176
eventCornerRadius = getDimensionPixelSize(R.styleable.WeekView_eventCornerRadius, 0)
163177
eventTextSize = getDimensionPixelSize(R.styleable.WeekView_eventTextSize, Defaults.textSize(context))

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.alamkanak.weekview
33
import android.graphics.Paint
44
import android.graphics.PointF
55
import android.graphics.Rect
6+
import android.graphics.RectF
67
import android.graphics.Typeface
78
import android.text.TextPaint
89
import com.alamkanak.weekview.Constants.UNINITIALIZED
@@ -329,6 +330,60 @@ internal class WeekViewConfigWrapper(
329330
val headerRowBottomLineWidth: Float
330331
get() = if (showHeaderRowBottomLine) headerRowBottomLinePaint.strokeWidth else 0f
331332

333+
var showWeekNumber: Boolean
334+
get() = config.showWeekNumber
335+
set(value) {
336+
config.showWeekNumber = value
337+
}
338+
339+
var weekNumberTextColor: Int
340+
get() = config.weekNumberTextColor
341+
set(value) {
342+
config.weekNumberTextColor = value
343+
}
344+
var weekNumberTextSize: Int
345+
get() = config.weekNumberTextSize
346+
set(value) {
347+
config.weekNumberTextSize = value
348+
}
349+
var weekNumberBackgroundColor: Int
350+
get() = config.weekNumberBackgroundColor
351+
set(value) {
352+
config.weekNumberBackgroundColor = value
353+
}
354+
var weekNumberBackgroundCornerRadius: Int
355+
get() = config.weekNumberBackgroundCornerRadius
356+
set(value) {
357+
config.weekNumberBackgroundCornerRadius = value
358+
}
359+
360+
private val _weekNumberBounds: RectF = RectF()
361+
362+
val weekNumberBounds: RectF
363+
get() = _weekNumberBounds.apply {
364+
left = 0f
365+
top = 0f
366+
right = timeColumnWidth
367+
bottom = headerHeight
368+
}
369+
370+
private val _weekNumberTextPaint: Paint = TextPaint(Paint.ANTI_ALIAS_FLAG)
371+
372+
val weekNumberTextPaint: Paint
373+
get() = _weekNumberTextPaint.apply {
374+
color = weekNumberTextColor
375+
textAlign = Paint.Align.CENTER
376+
textSize = weekNumberTextSize.toFloat()
377+
typeface = this@WeekViewConfigWrapper.typeface
378+
}
379+
380+
private val _weekNumberBackgroundPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
381+
382+
val weekNumberBackgroundPaint: Paint
383+
get() = _weekNumberBackgroundPaint.apply {
384+
color = weekNumberBackgroundColor
385+
}
386+
332387
val singleLineHeader: Boolean
333388
get() = config.singleLineHeader
334389

core/src/main/res/values/attrs.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
<attr name="todayHeaderTextColor" format="color" />
5050
<attr name="singleLineHeader" format="boolean" />
5151

52+
<!-- Week number -->
53+
<attr name="showWeekNumber" format="boolean" />
54+
<attr name="weekNumberTextColor" format="color" />
55+
<attr name="weekNumberTextSize" format="dimension" />
56+
<attr name="weekNumberBackgroundColor" format="color" />
57+
<attr name="weekNumberBackgroundCornerRadius" format="dimension" />
58+
5259
<!-- Event chips -->
5360
<attr name="eventCornerRadius" format="dimension" />
5461
<attr name="eventTextSize" format="dimension" />

sample/src/main/res/layout/activity_basic.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,17 @@
3434
app:showNowLine="true"
3535
app:showNowLineDot="true"
3636
app:showTimeColumnSeparator="true"
37+
app:showWeekNumber="true"
3738
app:singleDayHorizontalMargin="8dp"
3839
app:timeColumnBackgroundColor="#ffffffff"
3940
app:timeColumnPadding="8dp"
4041
app:timeColumnSeparatorColor="@color/header_bottom_line"
4142
app:timeColumnSeparatorStrokeWidth="1dp"
4243
app:timeColumnTextColor="@color/toolbar_text"
4344
app:timeColumnTextSize="12sp"
44-
app:todayHeaderTextColor="@color/accent" />
45+
app:todayHeaderTextColor="@color/accent"
46+
app:weekNumberBackgroundColor="@color/dark_gray"
47+
app:weekNumberBackgroundCornerRadius="@dimen/corner_radius"
48+
app:weekNumberTextColor="@android:color/white" />
4549

4650
</LinearLayout>

sample/src/main/res/values/colors.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
<color name="toolbar_text">#8f000000</color>
1010
<color name="accent">#2789e4</color>
1111
<color name="divider">#E2E2E2</color>
12+
<color name="dark_gray">#aeaeae</color>
1213
</resources>

sample/src/main/res/values/dimens.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
<dimen name="default_space">16dp</dimen>
44
<dimen name="border_width">1dp</dimen>
55
<dimen name="no_border_width">0dp</dimen>
6+
<dimen name="corner_radius">8dp</dimen>
67
</resources>

0 commit comments

Comments
 (0)