From 98380342fde3bd9ffe23a7b3dc4211fc14d0c2bb Mon Sep 17 00:00:00 2001 From: pelmenstar1 Date: Wed, 14 Jul 2021 21:38:33 +0300 Subject: [PATCH 1/4] Don't use nullable types on primitive to avoid tons of (un)boxing Type Int? in Kotlin JVM maps to reference type Integer. It causes memory allocations. In our case, nullability isn't necessary and can be avoided. To save compatibility with the last version of the library, on some variables types are explicitly marked. _activeThumb's type is changed to non-nullable because the library never expects variable to be null. --- .../joery/timerangepicker/TimeRangePicker.kt | 174 ++++++++++-------- 1 file changed, 93 insertions(+), 81 deletions(-) diff --git a/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt b/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt index b0e2109..5a85a88 100644 --- a/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt +++ b/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt @@ -29,7 +29,6 @@ import java.time.LocalTime import java.util.* import javax.xml.datatype.DatatypeFactory import kotlin.math.* -import kotlin.properties.Delegates class TimeRangePicker @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 @@ -46,26 +45,27 @@ class TimeRangePicker @JvmOverloads constructor( private val _sliderCapRect: RectF = RectF() private var _sliderWidth: Int = 8.px - private var _sliderColor by Delegates.notNull() - private var _sliderRangeColor by Delegates.notNull() - private var _sliderRangeGradientStart: Int? = null - private var _sliderRangeGradientMiddle: Int? = null - private var _sliderRangeGradientEnd: Int? = null + private var _sliderColor: Int = 0xFFE1E1E1.toInt() + private var _sliderRangeColor: Int = COLOR_NONE + + private var _sliderRangeGradientStart: Int = COLOR_NONE + private var _sliderRangeGradientMiddle: Int = COLOR_NONE + private var _sliderRangeGradientEnd: Int = COLOR_NONE private var _thumbSize: Int = 28.px private var _thumbSizeActiveGrow: Float = 1.2f private var _thumbIconStart: Drawable? = null private var _thumbIconEnd: Drawable? = null - private var _thumbColor by Delegates.notNull() + private var _thumbColor: Int = COLOR_NONE private var _thumbColorAuto: Boolean = true - private var _thumbIconColor: Int? = null - private var _thumbIconSize: Int? = null + private var _thumbIconColor: Int = COLOR_NONE + private var _thumbIconSize: Int = -1 private var _clockVisible: Boolean = true private var _clockFace: ClockFace = ClockFace.APPLE private var _clockLabelSize = 15.sp - private var _clockLabelColor by Delegates.notNull() - private var _clockTickColor by Delegates.notNull() + private var _clockLabelColor: Int = COLOR_NONE + private var _clockTickColor: Int = COLOR_NONE private var _minDurationMinutes: Int = 0 private var _maxDurationMinutes: Int = 24 * 60 @@ -91,11 +91,11 @@ class TimeRangePicker @JvmOverloads constructor( private var _angleStart: Float = 0f private var _angleEnd: Float = 0f - private var _activeThumb: Thumb? = null + private var _activeThumb = Thumb.NONE private var _touchOffsetAngle: Float = 0.0f private val _isGradientSlider: Boolean - get() = _sliderRangeGradientStart != null && _sliderRangeGradientEnd != null + get() = _sliderRangeGradientStart != COLOR_NONE && _sliderRangeGradientEnd != COLOR_NONE private val _thumbPositionCache = PointF() @@ -122,8 +122,6 @@ class TimeRangePicker @JvmOverloads constructor( _thumbColor = Color.BLUE } - _sliderColor = 0xFFE1E1E1.toInt() - val textColorPrimary = context.getTextColor(android.R.attr.textColorPrimary) _clockTickColor = textColorPrimary @@ -196,17 +194,18 @@ class TimeRangePicker @JvmOverloads constructor( attr.getColor(R.styleable.TimeRangePicker_trp_sliderRangeColor, _sliderRangeColor) // Slider gradient - val gradientStart = - attr.getColor(R.styleable.TimeRangePicker_trp_sliderRangeGradientStart, -1) - val gradientMiddle = - attr.getColor(R.styleable.TimeRangePicker_trp_sliderRangeGradientMiddle, -1) - val gradientEnd = - attr.getColor(R.styleable.TimeRangePicker_trp_sliderRangeGradientEnd, -1) - if (gradientStart != -1 && gradientEnd != -1) { - _sliderRangeGradientStart = gradientStart - _sliderRangeGradientMiddle = gradientMiddle - _sliderRangeGradientEnd = gradientEnd - } + _sliderRangeGradientStart = attr.getColor( + R.styleable.TimeRangePicker_trp_sliderRangeGradientStart, + COLOR_NONE + ) + _sliderRangeGradientMiddle = attr.getColor( + R.styleable.TimeRangePicker_trp_sliderRangeGradientMiddle, + COLOR_NONE + ) + _sliderRangeGradientEnd = attr.getColor( + R.styleable.TimeRangePicker_trp_sliderRangeGradientEnd, + COLOR_NONE + ) // Thumb _thumbSize = attr.getDimension( @@ -221,10 +220,8 @@ class TimeRangePicker @JvmOverloads constructor( val thumbColor = attr.getColor(R.styleable.TimeRangePicker_trp_thumbColor, 0) _thumbColor = if (thumbColor == 0) _thumbColor else thumbColor _thumbColorAuto = thumbColor == 0 - val iconColor = attr.getColor(R.styleable.TimeRangePicker_trp_thumbIconColor, 0) - _thumbIconColor = if (iconColor == 0) null else iconColor - val iconSize = attr.getDimension(R.styleable.TimeRangePicker_trp_thumbIconSize, -1f) - _thumbIconSize = if (iconSize == -1f) null else iconSize.toInt() + _thumbIconColor = attr.getColor(R.styleable.TimeRangePicker_trp_thumbIconColor, COLOR_NONE) + _thumbIconSize = attr.getDimension(R.styleable.TimeRangePicker_trp_thumbIconSize, -1f).toInt() _thumbIconStart = attr.getDrawable(R.styleable.TimeRangePicker_trp_thumbIconStart)?.mutate() _thumbIconEnd = attr.getDrawable(R.styleable.TimeRangePicker_trp_thumbIconEnd)?.mutate() @@ -265,15 +262,15 @@ class TimeRangePicker @JvmOverloads constructor( } private fun updatePaint() { - _thumbStartPaint.apply { - style = Paint.Style.FILL - color = - if (_thumbColorAuto && _isGradientSlider) _sliderRangeGradientStart!! else _thumbColor - } - _thumbEndPaint.apply { - style = Paint.Style.FILL - color = - if (_thumbColorAuto && _isGradientSlider) _sliderRangeGradientEnd!! else _thumbColor + _thumbStartPaint.style = Paint.Style.FILL + _thumbEndPaint.style = Paint.Style.FILL + + if(_thumbColorAuto && _isGradientSlider) { + _thumbStartPaint.color = _sliderRangeGradientStart + _thumbEndPaint.color = _sliderRangeGradientEnd + } else { + _thumbStartPaint.color = _thumbColor + _thumbEndPaint.color = _thumbColor } _sliderPaint.apply { @@ -316,11 +313,11 @@ class TimeRangePicker @JvmOverloads constructor( val positions: FloatArray val colors: IntArray - val gradientStart = _sliderRangeGradientStart!! - val gradientEnd = _sliderRangeGradientEnd!! + val gradientStart = _sliderRangeGradientStart + val gradientEnd = _sliderRangeGradientEnd val gradientMiddle = _sliderRangeGradientMiddle - if (gradientMiddle == null) { + if (gradientMiddle == COLOR_NONE) { resizeCacheIfNeeded(2) positions = _gradientPositionsCache @@ -354,12 +351,15 @@ class TimeRangePicker @JvmOverloads constructor( } private fun updateThumbIconColors() { - if (_thumbIconColor != null) { - if (_thumbIconStart != null) { - DrawableCompat.setTint(_thumbIconStart!!, _thumbIconColor!!) + if (_thumbIconColor != COLOR_NONE) { + val iconStart = _thumbIconStart + val iconEnd = _thumbIconEnd + + if (iconStart != null) { + DrawableCompat.setTint(iconStart, _thumbIconColor) } - if (_thumbIconEnd != null) { - DrawableCompat.setTint(_thumbIconEnd!!, _thumbIconColor!!) + if (iconEnd != null) { + DrawableCompat.setTint(iconEnd, _thumbIconColor) } } @@ -452,7 +452,7 @@ class TimeRangePicker @JvmOverloads constructor( canvas, startThumbX, startThumbY, 0f, - if (_isGradientSlider) _sliderRangeGradientStart!! else _sliderRangeColor + if (_isGradientSlider) _sliderRangeGradientStart else _sliderRangeColor ) drawThumb( canvas, @@ -474,7 +474,7 @@ class TimeRangePicker @JvmOverloads constructor( canvas, endThumbX, endThumbY, 180f, - if (_isGradientSlider) _sliderRangeGradientEnd!! else _sliderRangeColor + if (_isGradientSlider) _sliderRangeGradientEnd else _sliderRangeColor ) drawThumb( canvas, @@ -532,8 +532,12 @@ class TimeRangePicker @JvmOverloads constructor( ) if (icon != null) { - val iconSize = - _thumbIconSize?.toFloat() ?: min(24.px.toFloat(), _thumbSize * 0.625f) + val iconSize = if(_thumbIconSize != -1) { + _thumbIconSize.toFloat() + } else { + min(24.px.toFloat(), _thumbSize * 0.625f) + } + icon.setBounds( (x - iconSize / 2).toInt(), (y - iconSize / 2).toInt(), @@ -565,7 +569,7 @@ class TimeRangePicker @JvmOverloads constructor( postInvalidate() - return onDragChangeListener?.onDragStart(_activeThumb!!) ?: true + return onDragChangeListener?.onDragStart(_activeThumb) ?: true } else { false } @@ -618,7 +622,7 @@ class TimeRangePicker @JvmOverloads constructor( } } - anglesChanged(_activeThumb!!) + anglesChanged(_activeThumb) postInvalidate() return true } @@ -635,7 +639,7 @@ class TimeRangePicker @JvmOverloads constructor( updateGradient() postInvalidate() - onDragChangeListener?.onDragStop(_activeThumb!!) + onDragChangeListener?.onDragStop(_activeThumb) _activeThumb = Thumb.NONE return true } @@ -647,15 +651,16 @@ class TimeRangePicker @JvmOverloads constructor( private fun anglesChanged(thumb: Thumb) { updateGradient() - if (onTimeChangeListener != null) { + val listener = onTimeChangeListener + if (listener != null) { if (thumb == Thumb.START || thumb == Thumb.BOTH) { - onTimeChangeListener?.onStartTimeChange(startTime) + listener.onStartTimeChange(startTime) } if (thumb == Thumb.END || thumb == Thumb.BOTH) { - onTimeChangeListener?.onEndTimeChange(endTime) + listener.onEndTimeChange(endTime) } if (thumb == Thumb.START || thumb == Thumb.END) { - onTimeChangeListener?.onDurationChange(duration) + listener.onDurationChange(duration) } } } @@ -877,8 +882,8 @@ class TimeRangePicker @JvmOverloads constructor( @ColorInt get() = _sliderRangeColor set(@ColorInt value) { - _sliderRangeGradientStart = null - _sliderRangeGradientEnd = null + _sliderRangeGradientStart = COLOR_NONE + _sliderRangeGradientEnd = COLOR_NONE _sliderRangeColor = value updatePaint() } @@ -890,11 +895,11 @@ class TimeRangePicker @JvmOverloads constructor( sliderRangeColor = ContextCompat.getColor(context, value) } - var sliderRangeGradientStart + var sliderRangeGradientStart: Int? @ColorInt - get() = _sliderRangeGradientStart + get() = _sliderRangeGradientStart.nullIfNone() set(@ColorInt value) { - _sliderRangeGradientStart = value + _sliderRangeGradientStart = value ?: COLOR_NONE updatePaint() } @@ -905,11 +910,11 @@ class TimeRangePicker @JvmOverloads constructor( sliderRangeGradientStart = ContextCompat.getColor(context, value) } - var sliderRangeGradientMiddle + var sliderRangeGradientMiddle: Int? @ColorInt - get() = _sliderRangeGradientMiddle + get() = _sliderRangeGradientMiddle.nullIfNone() set(@ColorInt value) { - _sliderRangeGradientMiddle = value + _sliderRangeGradientMiddle = value ?: COLOR_NONE updatePaint() } @@ -920,11 +925,11 @@ class TimeRangePicker @JvmOverloads constructor( sliderRangeGradientMiddle = ContextCompat.getColor(context, value) } - var sliderRangeGradientEnd + var sliderRangeGradientEnd: Int? @ColorInt - get() = _sliderRangeGradientEnd + get() = _sliderRangeGradientEnd.nullIfNone() set(@ColorInt value) { - _sliderRangeGradientEnd = value + _sliderRangeGradientEnd = value ?: COLOR_NONE updatePaint() } @@ -950,11 +955,11 @@ class TimeRangePicker @JvmOverloads constructor( postInvalidate() } - var thumbColor + var thumbColor: Int? @ColorInt - get() = _thumbColor + get() = _thumbColor.nullIfNone() set(@ColorInt value) { - _thumbColor = value + _thumbColor = value ?: COLOR_NONE _thumbColorAuto = false updatePaint() } @@ -1001,18 +1006,18 @@ class TimeRangePicker @JvmOverloads constructor( thumbIconEnd = ContextCompat.getDrawable(context, value) } - var thumbIconSize - get() = _thumbIconSize - set(@ColorInt value) { - _thumbIconSize = value + var thumbIconSize: Int? + get() = if(_thumbIconSize == -1) null else _thumbIconSize + set(value) { + _thumbIconSize = value ?: -1 postInvalidate() } - var thumbIconColor + var thumbIconColor: Int? @ColorInt - get() = _thumbIconColor + get() = _thumbIconColor.nullIfNone() set(@ColorInt value) { - _thumbIconColor = value + _thumbIconColor = value ?: COLOR_NONE updateThumbIconColors() } @@ -1038,7 +1043,7 @@ class TimeRangePicker @JvmOverloads constructor( postInvalidate() } - var clockTickColor + var clockTickColor: Int @ColorInt get() = _clockTickColor set(@ColorInt value) { @@ -1053,7 +1058,7 @@ class TimeRangePicker @JvmOverloads constructor( clockTickColor = ContextCompat.getColor(context, value) } - var clockLabelColor + var clockLabelColor: Int @ColorInt get() = _clockLabelColor set(@ColorInt value) { @@ -1076,6 +1081,13 @@ class TimeRangePicker @JvmOverloads constructor( postInvalidate() } + @ColorInt + private fun Int.nullIfNone(): Int? = if(this == COLOR_NONE) null else this + + companion object { + private const val COLOR_NONE: Int = 0x00c0ffee + } + open class Time(val totalMinutes: Int) { constructor(hr: Int, min: Int) : this(hr * 60 + min) From d231a95d122a706568d226810774264547ba3a9b Mon Sep 17 00:00:00 2001 From: "O. Khmaruk" Date: Sat, 28 Aug 2021 00:49:23 +0300 Subject: [PATCH 2/4] Don't use boxed types at all --- .../joery/timerangepicker/TimeRangePicker.kt | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt b/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt index 22049f6..4b0b2f2 100644 --- a/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt +++ b/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt @@ -934,11 +934,11 @@ class TimeRangePicker @JvmOverloads constructor( sliderRangeColor = ContextCompat.getColor(context, value) } - var sliderRangeGradientStart: Int? + var sliderRangeGradientStart: Int @ColorInt - get() = _sliderRangeGradientStart.nullIfNone() + get() = _sliderRangeGradientStart set(@ColorInt value) { - _sliderRangeGradientStart = value ?: COLOR_NONE + _sliderRangeGradientStart = value updatePaint() } @@ -949,11 +949,11 @@ class TimeRangePicker @JvmOverloads constructor( sliderRangeGradientStart = ContextCompat.getColor(context, value) } - var sliderRangeGradientMiddle: Int? + var sliderRangeGradientMiddle: Int @ColorInt - get() = _sliderRangeGradientMiddle.nullIfNone() + get() = _sliderRangeGradientMiddle set(@ColorInt value) { - _sliderRangeGradientMiddle = value ?: COLOR_NONE + _sliderRangeGradientMiddle = value updatePaint() } @@ -964,11 +964,11 @@ class TimeRangePicker @JvmOverloads constructor( sliderRangeGradientMiddle = ContextCompat.getColor(context, value) } - var sliderRangeGradientEnd: Int? + var sliderRangeGradientEnd: Int @ColorInt - get() = _sliderRangeGradientEnd.nullIfNone() + get() = _sliderRangeGradientEnd set(@ColorInt value) { - _sliderRangeGradientEnd = value ?: COLOR_NONE + _sliderRangeGradientEnd = value updatePaint() } @@ -995,11 +995,11 @@ class TimeRangePicker @JvmOverloads constructor( computeClockRadius() } - var thumbColor: Int? + var thumbColor: Int @ColorInt - get() = _thumbColor.nullIfNone() + get() = _thumbColor set(@ColorInt value) { - _thumbColor = value ?: COLOR_NONE + _thumbColor = value _thumbColorAuto = false updatePaint() } @@ -1046,18 +1046,18 @@ class TimeRangePicker @JvmOverloads constructor( thumbIconEnd = ContextCompat.getDrawable(context, value) } - var thumbIconSize: Int? - get() = if(_thumbIconSize == -1) null else _thumbIconSize + var thumbIconSize: Int + get() = _thumbIconSize set(value) { - _thumbIconSize = value ?: -1 + _thumbIconSize = value invalidate() } - var thumbIconColor: Int? + var thumbIconColor: Int @ColorInt - get() = _thumbIconColor.nullIfNone() + get() = _thumbIconColor set(@ColorInt value) { - _thumbIconColor = value ?: COLOR_NONE + _thumbIconColor = value updateThumbIconColors() } @@ -1125,9 +1125,6 @@ class TimeRangePicker @JvmOverloads constructor( invalidate() } - @ColorInt - private fun Int.nullIfNone(): Int? = if(this == COLOR_NONE) null else this - companion object { private const val COLOR_NONE: Int = 0x00c0ffee } From f99f534fffc694c7241fd2c48f7fc86af5711117 Mon Sep 17 00:00:00 2001 From: "O. Khmaruk" Date: Fri, 10 Sep 2021 21:22:16 +0300 Subject: [PATCH 3/4] Make COLOR_NONE public and fix ExampleActivity --- .../java/nl/joery/demo/timerangepicker/ExampleActivity.kt | 4 ++-- .../src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/src/main/java/nl/joery/demo/timerangepicker/ExampleActivity.kt b/demo/src/main/java/nl/joery/demo/timerangepicker/ExampleActivity.kt index 8aff534..95e3c63 100644 --- a/demo/src/main/java/nl/joery/demo/timerangepicker/ExampleActivity.kt +++ b/demo/src/main/java/nl/joery/demo/timerangepicker/ExampleActivity.kt @@ -121,7 +121,7 @@ class ExampleActivity : AppCompatActivity() { picker.sliderColor = Color.TRANSPARENT picker.thumbColor = Color.WHITE picker.sliderRangeGradientStart = Color.parseColor("#F79104") - picker.sliderRangeGradientMiddle = null + picker.sliderRangeGradientMiddle = TimeRangePicker.COLOR_NONE picker.sliderRangeGradientEnd = Color.parseColor("#F8C207") picker.thumbIconColor = Color.parseColor("#F79104") picker.thumbSizeActiveGrow = 1.0f @@ -135,7 +135,7 @@ class ExampleActivity : AppCompatActivity() { picker.thumbColor = Color.TRANSPARENT picker.thumbIconColor = Color.WHITE picker.sliderRangeGradientStart = Color.parseColor("#5663de") - picker.sliderRangeGradientMiddle = null + picker.sliderRangeGradientMiddle = TimeRangePicker.COLOR_NONE picker.sliderRangeGradientEnd = Color.parseColor("#6d7bff") picker.thumbSizeActiveGrow = 1.0f picker.clockFace = TimeRangePicker.ClockFace.SAMSUNG diff --git a/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt b/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt index 13a9722..97a128b 100644 --- a/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt +++ b/timerangepicker/src/main/java/nl/joery/timerangepicker/TimeRangePicker.kt @@ -1124,7 +1124,7 @@ class TimeRangePicker @JvmOverloads constructor( } companion object { - private const val COLOR_NONE: Int = 0x00c0ffee + const val COLOR_NONE: Int = 0x00c0ffee } open class Time(val totalMinutes: Int) { From 4d53e17e905cd0c448c518bad337b748aebb060d Mon Sep 17 00:00:00 2001 From: pelme Date: Sat, 22 Jan 2022 21:14:30 +0200 Subject: [PATCH 4/4] Restore version of libraries in demo --- demo/build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/demo/build.gradle b/demo/build.gradle index e858505..8c454f9 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -30,17 +30,17 @@ android { dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.5.0' + implementation 'androidx.core:core-ktx:1.6.0' implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation project(path: ':timerangepicker') - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - implementation 'com.google.android.material:material:1.3.0' + implementation 'com.google.android.material:material:1.4.0' implementation 'com.jaredrummler:colorpicker:1.1.0' implementation 'nl.joery.animatedbottombar:library:1.1.0' } \ No newline at end of file