Android Native - Animate Alternating Yin Yang Symbol - Part 1

dimitrilc 1 Tallied Votes 101 Views Share

Introduction

Taking what we already learned from the previous tutorials about drawing custom shapes and animating along elements along a Path. In this tutorial, we will combine what we learned about animation so far to create an alternating Yin Yang symbol.

To those unfamiliar with the Yin Yang symbol, let us quickly visit the anatomy of the Yin Yang symbol itself.

YinYangExplanation.jpg

Based on the information from Wikipedia, in the Yin Yang symbol, Yin refers to the dark side, while Yang refers to the brightside.

For the rest of the tutorial, the following terms will be used:
Yin: the dark side.
Yang: the bright side.
Yin Dot: the black dot contained in the Yang side.
Yang Dot: the white dot contained in the Yin side.
Yin Yang Curve: the S-shaped curve that separates the Yin and the Yang.

Goals

At the end of the tutorial, you would have learned:

  1. How to animate an alternating Yin Yang symbol.

Tools Required

  1. Android Studio. The version used in this tutorial is Android Studio Dolphin | 2021.3.1.

Prerequisite Knowledge

  1. Intermedia Android.
  2. Basic Android animation.
  3. Custom Drawable.
  4. Custom Path.

Project Setup

To follow along with the tutorial, perform the steps below:

  1. Create a new Android project with the default Empty Activity.

  2. Replace the code inside activity_main.xml with the code below.

     <?xml version="1.0" encoding="utf-8"?>
     <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:background="@color/teal_200"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <ImageView
            android:id="@+id/yin_yang_background"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintDimensionRatio="1:1"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:srcCompat="@tools:sample/backgrounds/scenic" />
    
     </androidx.constraintlayout.widget.ConstraintLayout>

The attributes

android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1"

on the ImageView will constraint its height equal to its width.

The Plan

Normally, we can draw both the Yin and the Yang manually, but we can actually take a shortcut and skip drawing the complex teardrop-shape for the Yang entirely. To save time, we paint the entire background with Color.WHITE to make it the Yang. For the Yin, we can simply draw it with Color.Black.

Yin_Yang_Plan.png

Because we only have to draw the Yin, we also only have to animate the Yin side later on.

Draw The Yang (Bright)

Because the Yang side is simply a circular background with one solid color, we will start with it first.

  1. Replace your onCreate() with the method below.

     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        val yinYang = findViewById<ImageView>(R.id.yin_yang).apply {
            setImageDrawable(YinYang())
        }
     }
  2. Create your custom Drawable called YinYang with the code below.

     class YinYang: Drawable() {
        private val yangPaint = Paint().apply {
            color = Color.WHITE
        }
    
        override fun draw(canvas: Canvas) {
            drawYang(canvas)
            drawYin(canvas)
            drawYangDot(canvas)
            drawYinDot(canvas)
        }
    
        private fun drawYang(canvas: Canvas){
        }
    
        private fun drawYin(canvas: Canvas){
        }
    
        private fun drawYangDot(canvas: Canvas){
        }
    
        private fun drawYinDot(canvas: Canvas){
        }
    
        override fun setAlpha(alpha: Int) {
            // no op
        }
    
        override fun setColorFilter(colorFilter: ColorFilter?) {
            // no op
        }
    
        @Deprecated("Deprecated in Superclass")
        override fun getOpacity() = PixelFormat.OPAQUE
     }
  3. Because the drawing for the Yang, Yin, Yin Dot, and Yang Dot can get pretty complex, I have separated each part into its own private functions. We will work on them one by one.

  4. Notice the yangPaint instance variable at the top of the class definition. We will use it to draw both the Yang and the Yang Dot.

  5. The Yang must be a perfect circle with the radius as wide as half the width of its container. To draw the Yang, we use the implementation below.

     private fun drawYang(canvas: Canvas){
        canvas.drawCircle(
            bounds.exactCenterX(),
            bounds.exactCenterY(),
            bounds.exactCenterX(),
            yangPaint
        )
     }

Screenshot_1666224779.png

  1. Inside each Drawable implementation, the bounds are available via getBounds() (Java) or just the property syntax bounds (Kotlin). This bounds property contains the coordinates of the Drawable’s container, such as the center or the top, left, right, bottom coordinates. Using the coordinates of the exact center of the container bounds, we were able to calculate the circle radius, and (x,y) center, which were provided to the drawCircle() method.

Summary

We are completed with the first part of the tutorial, please continue on part two here.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.