Connect Session 6
Custom Views,
ValueAnimator,
and Miscellaneous Topics
Hussein El Feky | Jan 7-13, 2023
Reminder
Projects 3, 4, 5, 6 and 7 Deadline
(Graduation Date)
23rd February, 2023
Agenda
1
Custom Views
2
ValueAnimator
5
Q&A Time
4
Project 3 Tips
3
Miscellaneous
Prerequisites
Canvas and Paint
Paint
Canvas
Canvas API
Paint API
Paint Antialiasing
Canvas Coordinate Plane
@JvmOverloads
class CustomView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
...
}
IS EQUIVALENT TO
class CustomView : View {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttrs: Int) : super(context, attrs, defStyleAttrs)
...
}
Custom View Constructor Parameters
The Context in which the view is running in, through which it can access the current theme, resources, etc.
This is used when a view is being constructed from an XML file, supplying attributes that were specified in the XML file.
An attribute in the current theme that contains a reference to a style resource that supplies default values for the view. It can be 0 to not look for defaults.
Custom Attributes Example
<declare-styleable name="RouteView">
<attr name="routeColor" format="color" />
<attr name="orientation" format="enum">
<enum name="vertical" value="0" />
<enum name="horizontal" value="1" />
</attr>
<attr name="shape" format="enum">
<enum name="single" value="0" />
<enum name="middle" value="1" />
<enum name="left" value="2" />
<enum name="right" value="3" />
<enum name="start" value="4" />
<enum name="end" value="5" />
</attr>
</declare-styleable>
View.invalidate() vs. View.requestLayout()
Short Answer
Draw
Measure + Draw
View.onMeasure()
A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement for either the width or the height. A MeasureSpec is comprised of a size and a mode. There are three possible modes:
View.onDraw()
RouteView Custom View
DialView (Fan Controller) Custom View
DialView (Fan Controller) Custom View | Angles
DialView (Fan Controller) Custom View | Trigonometry
Delegates.observable
/**
* Returns a property delegate for a read/write property that calls a specified callback
* function when changed.
*/
var number: Int by Delegates.observable(0) { _, oldValue, newValue ->
println("Old Value: $oldValue, New Value: $newValue")
}
fun main() {
number = 20 // Print 0, 20
number = 40 // Print 20, 40
number = 10 // Print 40, 10
}
Delegates.vetoable
/**
* Returns a property delegate for a read/write property that calls a specified callback
* function when changed, allowing the callback to veto the modification.
*/
var max: Int by Delegates.vetoable(0) { _, oldValue, newValue ->
newValue > oldValue
}
fun main() {
println(max) // 0
max = 10
println(max) // 10
max = 5
println(max) // 10
}
ValueAnimator
valueAnimator = ValueAnimator.ofInt(0, 360).setDuration(1000).apply {
addUpdateListener {
progress = it.animatedValue as Int
invalidate()
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator) {...}
override fun onAnimationEnd(animation: Animator) {...}
override fun onAnimationPause(animation: Animator) {...}
override fun onAnimationResume(animation: Animator) {...}
override fun onAnimationCancel(animation: Animator) {...}
override fun onAnimationRepeat(animation: Animator) {...}
})
interpolator = LinearInterpolator()
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.RESTART
start()
}
Animation Interpolators
Animation Interpolators | Demo
Resource Qualifiers
Next Session
Project 3 (LoadApp) Tips
Project 3 (LoadApp) Tips | Part 1
Project 3 (LoadApp) Tips | Part 2
Resources
Q&A Time
Ask me anything.