I added this solution here since there is none and also to help anyone who might learn Android development using kotlin with this book in the future.
This is to first reverse the sunset based on a boolean value.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide() // hide actionBar
sceneView = findViewById(R.id.scene)
sunView = findViewById(R.id.imgSun)
skyView = findViewById(R.id.imgSky)
sunReflection = findViewById(R.id.imgSunReflection)
seaView = findViewById(R.id.imgSeaView)
sceneView.setOnClickListener {
animation()
}
}
private fun animation() {
sunState = if (sunState) {
startAnimation()
false // will reverse the value
} else {
reverseAnimation()
true // and so on
}
}```
And the reverse animation, the startAnimation() will not need to be touched for this.
// Our reverse animation.
private fun reverseAnimation() {
/** Second animator set **/
val sunYStart = sunView.top.toFloat()
val sunYEnd = skyView.height.toFloat()
val heightAnimator2 = ObjectAnimator
.ofFloat(sunView, "y", sunYEnd, sunYStart)
.setDuration(3000)
heightAnimator2.interpolator = AccelerateInterpolator()
val sunsetSkyAnimator2 = ObjectAnimator
.ofInt(skyView, "backgroundColor", blueSkyColor, sunsetSkyColor)
.setDuration(3000)
sunsetSkyAnimator2.setEvaluator(ArgbEvaluator())
val blueSkyColor = ObjectAnimator
.ofInt(skyView, "backgroundColor", sunsetSkyColor, blueSkyColor)
.setDuration(1500)
blueSkyColor.setEvaluator(ArgbEvaluator())
val refStart = sunReflection.top.toFloat()
val refEnd = seaView.height.toFloat()
val sunReflectAnimator = ObjectAnimator
.ofFloat(sunReflection, "y", refEnd, refStart)
.setDuration(3000)
val animatorSet2 = AnimatorSet()
animatorSet2.play(heightAnimator2) // play heightAnimator with sunsetSky, also play heightAnimator before blueSky
.with(sunsetSkyAnimator2)
.with(sunReflectAnimator)
.before(blueSkyColor)
animatorSet2.start()
}
For the second and last challenge, to make the sun “Pulsate with heat” or give it a spinning halo of rays. And to also add sun reflection on the sea and make it reverse when clicked.
sun_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
android:thickness="5dp"
android:useLevel="false">
<solid android:color="@color/heat" />
<corners android:topLeftRadius="10dp" android:topRightRadius="10dp"
android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp"/>
<size android:width="50dp"/>
<!-- Line around the edge of the sun -->
<stroke
android:dashWidth="5dp"
android:dashGap="10dp"
android:width="10dp"
android:color="@color/heat" />
</shape>
sun_reflection.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<rotate android:fromDegrees="45" android:toDegrees="45" android:pivotX="-40%" android:pivotY="87%" >
<shape android:shape="rectangle" >
<stroke android:color="@color/bright_sun" android:width="10dp"/>
<solid android:color="@color/bright_sun" />
</shape>
</rotate>
</item>
</layer-list>
Our layout : activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scene"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/imgSky"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.61"
android:background="@color/blue_sky">
<ImageView
style="@style/sun_image"
android:id="@+id/imgSun"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center"
android:src="@drawable/sun"
android:rotation="0"
android:padding="13dp"/>
</FrameLayout>
<FrameLayout
android:id="@+id/imgSeaView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.39"
android:background="@color/sea">
<ImageView
android:id="@+id/imgSunReflection"
android:layout_width="220dp"
android:layout_height="225dp"
android:layout_gravity="center"
android:src="@drawable/sun_reflection"
android:rotation="180"
android:layout_marginBottom="20dp"/>
</FrameLayout>
</LinearLayout>
And then finally our code for the halo and reflection Implementation in MainActivity.kt
// function will move the top of the sunView to the bottom of the skyView
private fun startAnimation() {
val sunYStart = sunView.top.toFloat()
val sunYEnd = skyView.height.toFloat()
// Object animator is a property animator that repeatedly calls different setter functions with different values to move the
// views around the screen
val heightAnimator = ObjectAnimator
.ofFloat(sunView, "y", sunYStart, sunYEnd)
.setDuration(3000)
// will change the speed of our animation's movement
heightAnimator.interpolator = AccelerateInterpolator()
// This will animate the sky from blue_color to sunset_color
val sunsetSkyAnimator = ObjectAnimator
.ofInt(skyView, "backgroundColor", blueSkyColor, sunsetSkyColor)
.setDuration(3000)
sunsetSkyAnimator.setEvaluator(ArgbEvaluator()) // ArgbEvaluator() tells ObjectAnimator exactly what the value is.
val nightSkyAnimator = ObjectAnimator
.ofInt(skyView, "backgroundColor", sunsetSkyColor, nightSkyColor)
.setDuration(1500)
nightSkyAnimator.setEvaluator(ArgbEvaluator())
// BASED ON A CHALLENGE.
val sunYHeatStart = 0f
val sunYHeatEnd = 360f
val heatAnimator = ObjectAnimator
.ofFloat(sunView, "rotation", sunYHeatStart, sunYHeatEnd)
.setDuration(9000)
heatAnimator.repeatCount = ObjectAnimator.INFINITE
// BASED ON A CHALLENGE. Sun reflection
val refStart = sunReflection.top.toFloat()
val refEnd = seaView.height.toFloat()
val sunReflectAnimator = ObjectAnimator
.ofFloat(sunReflection, "y", refStart, refEnd)
.setDuration(3000)
/** This is a simpler Implementation of animator.start() in which we will start all the animation at the same time. **/
val animatorSet = AnimatorSet()
animatorSet.play(heightAnimator) // play heightAnimator with sunsetSky, also play heightAnimator before nightSky
.with(sunsetSkyAnimator)
.with(sunReflectAnimator)
.with(heatAnimator)
.before(nightSkyAnimator)
animatorSet.start()
}