Android: Animated Button

Homan Huang
3 min readNov 15, 2020

If you were using Android Studio, you knew it has a boring button effect (Google: 😨). When you run an app, you’ll see the button has no effect at all. “Click”, nothing shows up. And 😱you tap for tens of times after and you ask yourself whether the button isn’t working. 🤬You may ask for the relatives of the programmer. You know what I mean. So the button effect is important for a popular app. It’s easy to code:

  • MotionEvent.ACTION_UP: → Do sth.
  • MotionEvent.ACTION_DOWN: →Do sth.

You can even save the code to input the onClickListener☺🙂☺👍.

— — === MenU === — —

👨‍💻1. How to create an Animation folder
🐱‍🏍2
. XML Effect: scale_up &. scale-down
🧗‍♂3
. Implement Effect — View.OnTouchListener
👨‍🚀4
. Use Effects in the Activity
👁‍🗨5
. Test Result

👨‍💻1. How to create an Animation folder

< === Menu

Right-click “res” → “New” → “Android Resource Directory”:

OK

🐱‍🏍2. XML Effect: scale_up &. scale-down

< === Menu

Right-click “anim” → “New” → “Animation Resource File”:

OK

Same step to add another file:

OK

scale_up.xml: Ratio =1.2.

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1"
android:fromYScale="1"
android:toXScale="1.2"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:duration="100"
/>

scale_down: Ratio = 1

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1.2"
android:fromYScale="1.2"
android:toXScale="1"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="100"
/>

You see. They are a group of settings.

🧗‍♂3. Implement Effect — View.OnTouchListener

< === Menu

The MotionEvent.ACTION_DOWN and MotionEvent.ACTION_UP are member of View.OnTouchListener. So you need to return a value of View.OnTouchListener.

@SuppressLint("ClickableViewAccessibility")
fun fabAnimateToAction(...): View.OnTouchListener {

I am using CoordinateLayout as my buttons. The effect needs to change(DOWN) and back to normal(UP). Or you will mess the app when you press back button. It fun to watch the app keeps changing itself, isn’t it? So, you need two animation effects. Finally, you want the button to do something. I will add a function reference.

@SuppressLint("ClickableViewAccessibility")
fun fabAnimateToAction(
mFab: CoordinatorLayout,
anim1: Animation,
anim2:
Animation,
onClickAction:
KFunction0<Unit>
): View.OnTouchListener {
return View.OnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_UP -> {
mFab.startAnimation(anim1)
onClickAction()
}
MotionEvent.ACTION_DOWN -> {
mFab.startAnimation(anim2)
}
}
true
}
}

👨‍🚀4. Use Effects in the Activity

< === Menu

It’s simple to use the effects. Here is my example from my Bluetooth project:

I store the effect in UiHelper.kt and call from MainActivity.kt

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

...

// UI
private val inputFab: CoordinatorLayout by lazy {
findViewById(R.id.inputFab) }
private val editFab: CoordinatorLayout by lazy {
findViewById(R.id.editFab) }
private val purchaseFab: CoordinatorLayout by lazy {
findViewById(R.id.purchaseFab) }
private lateinit var scaleUp: Animation
private lateinit var scaleDown: Animation
... @SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
...

// Button Animation Effects
scaleUp = AnimationUtils.loadAnimation(
this, R.anim.scale_up)
scaleDown = AnimationUtils.loadAnimation(
this, R.anim.scale_down)

inputFab.setOnTouchListener(
fabAnimateToAction(
inputFab, scaleDown, scaleUp, ::toInputActivity
)
)
editFab.setOnTouchListener(
fabAnimateToAction(
editFab, scaleDown, scaleUp, ::toEditActivity
)
)
purchaseFab.setOnTouchListener(
fabAnimateToAction(
purchaseFab, scaleDown, scaleUp,
::toPurchaseRecordActivity
)
)
}
fun toInputActivity() {
val intent = Intent(this, InputActivity::class.java)
startActivity(intent)
}

fun toEditActivity() {
val intent = Intent(this, EditActivity::class.java)
startActivity(intent)
}

fun toPurchaseRecordActivity() {
val intent = Intent(
this, PurchaseRecordActivity::class.java)
startActivity(intent)
}

companion object {
const val tag = "MainAct: "
}
}

👁‍🗨5. Test Result:

< === Menu

Cool! It’s working fine. You can try shake-it-up or many things you want to take effect.

--

--

Homan Huang

Computer Science BS from SFSU. I studied and worked on Android system since 2017. If you are interesting in my past works, please go to my LinkedIn.