Skip to content

Commit

Permalink
Merge pull request #146 from kizitonwose/dev
Browse files Browse the repository at this point in the history
Release 0.3.4
  • Loading branch information
kizitonwose authored Apr 11, 2020
2 parents 6d30314 + 4e38659 commit dddc0fe
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 11 deletions.
3 changes: 2 additions & 1 deletion library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$versions.kotlin_lang"
implementation "androidx.core:core-ktx:$versions.androidx_core_ktx"

// Expose ThreeTenABP so library users can use it directly.
api "com.jakewharton.threetenabp:threetenabp:$versions.threetenabp"
Expand All @@ -50,7 +51,7 @@ dependencies {
api "androidx.recyclerview:recyclerview:$versions.recyclerview"

testImplementation "junit:junit:$versions.junit"
testImplementation('org.threeten:threetenbp:1.3.7') {
testImplementation('org.threeten:threetenbp:1.4.2') {
// Use threetenBP library for tests as context will
// not be available to initialise threetenABP
exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
Expand Down
16 changes: 14 additions & 2 deletions library/src/main/java/com/kizitonwose/calendarview/CalendarView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.view.View.MeasureSpec.UNSPECIFIED
import android.view.ViewGroup
import androidx.annotation.Px
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import com.kizitonwose.calendarview.model.*
import com.kizitonwose.calendarview.ui.*
Expand Down Expand Up @@ -198,6 +197,15 @@ open class CalendarView : RecyclerView {
}
}

/**
* The duration in milliseconds of the animation used to adjust the CalendarView's
* height when [scrollMode] is [ScrollMode.PAGED] and the CalendarView's height is
* set to `wrap_content`. The height change happens when the CalendarView scrolls to
* a month which has less or more rows than the previous one. Default value is 200.
* To disable the animation, set this value to zero.
*/
var wrappedPageHeightAnimationDuration = 200

private var startMonth: YearMonth? = null
private var endMonth: YearMonth? = null
private var firstDayOfWeek: DayOfWeek? = null
Expand Down Expand Up @@ -234,6 +242,10 @@ open class CalendarView : RecyclerView {
maxRowCount = a.getInt(R.styleable.CalendarView_cv_maxRowCount, maxRowCount)
monthViewClass = a.getString(R.styleable.CalendarView_cv_monthViewClass)
hasBoundaries = a.getBoolean(R.styleable.CalendarView_cv_hasBoundaries, hasBoundaries)
wrappedPageHeightAnimationDuration = a.getInt(
R.styleable.CalendarView_cv_wrappedPageHeightAnimationDuration,
wrappedPageHeightAnimationDuration
)
a.recycle()
}

Expand Down Expand Up @@ -563,7 +575,7 @@ open class CalendarView : RecyclerView {
}
}

private val pagerSnapHelper = PagerSnapHelper()
private val pagerSnapHelper = CalenderPageSnapHelper()

/**
* Setup the CalendarView. You can call this any time to change the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.kizitonwose.calendarview.ui

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Rect
import android.os.Build
Expand All @@ -8,6 +9,7 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.annotation.LayoutRes
import androidx.core.view.ViewCompat
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.RecyclerView
import com.kizitonwose.calendarview.CalendarView
import com.kizitonwose.calendarview.model.*
Expand Down Expand Up @@ -164,6 +166,7 @@ internal class CalendarAdapter(

private var visibleMonth: CalendarMonth? = null
private var calWrapsHeight: Boolean? = null
private var initialLayout = true
fun notifyMonthScrollListenerIfNeeded() {
// Guard for cv.post() calls and other callbacks which use this method.
if (!isAttached) return
Expand Down Expand Up @@ -194,12 +197,14 @@ internal class CalendarAdapter(
// calculating height and uses the tallest one of the three meaning that the current index's
// view will end up having a blank space at the bottom unless the immediate previous and next
// indices are also missing the last row. I think there should be a better way to fix this.
if (calView.isHorizontal && calView.scrollMode == ScrollMode.PAGED) {
// New: Also fixes issue where the calendar does not wrap each month's height when in vertical,
// paged mode and just matches parent's height instead.
if (calView.scrollMode == ScrollMode.PAGED) {
val calWrapsHeight = calWrapsHeight ?: (calView.layoutParams.height == LP.WRAP_CONTENT).also {
// We modify the layoutParams so we save the initial value set by the user.
calWrapsHeight = it
}
if (calWrapsHeight.not()) return // Bug only happens when the CalenderView wraps its height.
if (!calWrapsHeight) return // Bug only happens when the CalenderView wraps its height.
val visibleVH =
calView.findViewHolderForAdapterPosition(visibleItemPos) as? MonthViewHolder ?: return
val newHeight = visibleVH.headerView?.height.orZero() +
Expand All @@ -208,13 +213,16 @@ internal class CalendarAdapter(
// by checking the number of visible(non-empty) rows.
visibleMonth.weekDays.size * calView.dayHeight +
visibleVH.footerView?.height.orZero()
if (calView.layoutParams.height != newHeight) {
calView.layoutParams = calView.layoutParams.apply {
this.height = newHeight
}
visibleVH.itemView.layoutParams = visibleVH.itemView.layoutParams.apply {
this.height = newHeight
if (calView.height != newHeight) {
ValueAnimator.ofInt(calView.height, newHeight).apply {
duration = if (initialLayout) 0 else calView.wrappedPageHeightAnimationDuration.toLong()
addUpdateListener {
calView.updateLayoutParams { height = it.animatedValue as Int }
visibleVH.itemView.requestLayout()
}
start()
}
if (initialLayout) initialLayout = false
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.kizitonwose.calendarview.ui

import android.view.View
import androidx.recyclerview.widget.OrientationHelper
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView

class CalenderPageSnapHelper : PagerSnapHelper() {

/**
* The default implementation of this method in [PagerSnapHelper.calculateDistanceToFinalSnap] uses the distance
* between the target view center vs RecyclerView center as final snap distance. This does not always give the
* desired result for calendar usage. For example in a vertical calendar when the RecyclerView is taller than
* the item view(e.g two or more visible months), we don't actually want the item view's center to be at the
* center of the RecyclerView when it snaps but instead we want the item view and RecyclerView top(in vertical)
* or left(in horizontal) to match at the end of the snap.
*/
override fun calculateDistanceToFinalSnap(layoutManager: RecyclerView.LayoutManager, targetView: View): IntArray {
return IntArray(2).apply {
this[0] = if (layoutManager.canScrollHorizontally())
distanceToStart(targetView, getHorizontalHelper(layoutManager)) else 0

this[1] = if (layoutManager.canScrollVertically())
distanceToStart(targetView, getVerticalHelper(layoutManager)) else 0
}
}

private fun distanceToStart(targetView: View, helper: OrientationHelper): Int {
val childStart = (helper.getDecoratedStart(targetView))
val containerStart = helper.startAfterPadding
return childStart - containerStart
}

private lateinit var verticalHelper: OrientationHelper
private lateinit var horizontalHelper: OrientationHelper

private fun getVerticalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
if (!::verticalHelper.isInitialized || verticalHelper.layoutManager != layoutManager) {
verticalHelper = OrientationHelper.createVerticalHelper(layoutManager)
}
return verticalHelper
}

private fun getHorizontalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
if (!::horizontalHelper.isInitialized || horizontalHelper.layoutManager != layoutManager) {
horizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager)
}
return horizontalHelper
}
}
6 changes: 6 additions & 0 deletions library/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,11 @@
<enum name="continuous" value="0" />
<enum name="paged" value="1" />
</attr>

<!-- The duration in milliseconds of the animation used to adjust the CalendarView's
height when `scrollMode` is `paged` and the CalendarView height is set to `wrap_content`.
The height change happens when the CalendarView scrolls to a month which has less or more
rows than the previous one. Default value is 200. To disable the animation, set this value to zero. -->
<attr name="cv_wrappedPageHeightAnimationDuration" format="integer" />
</declare-styleable>
</resources>

0 comments on commit dddc0fe

Please sign in to comment.