Vamsi Challa Vamsi Challa - 8 days ago 8
Android Question

Android Animation - Scale up and Fade along with Background Transition

I am trying to do something like this.. Can someone point me in the right direction?

enter image description here

Right now, i am using a Scale Animation and FadeOut Animation. It looks like this..

enter image description here

How do i add background colour to this.. Also please keep in mind that i want this to work from ICS/Jellybean

My code till now...

fade_out_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.1"
android:duration="100" />
</set>


scale_up_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

<scale
android:duration="100"
android:fromXScale="0.1"
android:fromYScale="0.1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
</set>


activity_main.xml - just the relevant part

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">

<TextView
android:id="@+id/textView4"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:layout_margin="8dp"
android:background="@drawable/shape_circle"
android:gravity="center"
android:text="004"
android:textColor="@color/light_gray"
android:textSize="18sp" />

<View
android:id="@+id/outer_view"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_centerInParent="true"
android:visibility="invisible"
android:background="@drawable/shape_circle_yellow"/>


</RelativeLayout>


shape_circle.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="false" android:state_pressed="false" android:state_selected="false">
<shape android:shape="oval">

<solid android:color="@color/ash" /> <!-- Fill color -->

<stroke android:width="4dp" android:color="@color/medium_gray" /> <!-- Outerline color -->

</shape>
</item>
<item android:state_selected="true">

<shape android:shape="oval">
<solid android:color="@color/ash" /> <!-- Fill color -->

<stroke android:width="4dp" android:color="@color/yellow" /> <!-- Outerline color -->
</shape>
</item>
<item android:state_focused="true">

<shape android:shape="oval">
<solid android:color="@color/ash" /> <!-- Fill color -->

<stroke android:width="4dp" android:color="@color/yellow" /> <!-- Outerline color -->
</shape>
</item>
<item android:state_pressed="true">

<shape android:shape="oval">
<solid android:color="@color/ash" /> <!-- Fill color -->

<stroke android:width="4dp" android:color="@color/yellow" /> <!-- Outerline color -->
</shape>
</item>
</selector>


shape_circle_yellow.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:shape="oval">

<stroke android:color="@color/yellow"
android:width="4dp" />
</shape>


Java code:

textView4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

final View view2 = findViewById(R.id.outer_view);

Animation scale_up_animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.scale_up_animation);
final Animation fade_out_animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.fade_out_animation);

scale_up_animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
view2.setVisibility(View.VISIBLE);
}

@Override
public void onAnimationEnd(Animation animation) {
view2.startAnimation(fade_out_animation);
}

@Override
public void onAnimationRepeat(Animation animation) {

}
});

fade_out_animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {

}

@Override
public void onAnimationEnd(Animation animation) {
view2.setVisibility(View.INVISIBLE);
}

@Override
public void onAnimationRepeat(Animation animation) {

}
});

view2.startAnimation(scale_up_animation);
}
});

Answer

The most simple way to reach this effect on Android is to create few custom views. For example we can divide animation into two views (according to divide to conquer rule). First view let's name CircleButton. It will be button which can be in two states - default and selected.

State default State selected

Second view let's name CircularRippleEffect and it will be container for animation during state changing.

Circular Ripple Effect here

When we combine this views together we will obtain effect like this:

Final effect

So, The question is how to create CircleButton and CircularRippleEffect classes ;) The first one is simple. We should extend View class and Override onDraw method. In onDraw method we have to draw two circles (first is representing button background and second is yellow border). Our onDraw method will look like this:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, backgroundPaint);

    canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, borderPaint);
    drawCenter(canvas, textPaint, text);
}

We have to remember that our backgroundPaintshould have set style up as FILL by using method backgroundPaint.setStyle(FILL); and our borderPaint to STROKE. I set also proper colors for this Paint objects. The last thing we should do in onDraw method is drawing text on the center of the View. I've created drawCenter() method for this implementation, that can be found in this answer from stackoverflow http://stackoverflow.com/a/32081250/1722808

And that is all we should know about CircleButton class. Everything else is similar to every custom view.

The CircularRippleEffect class is more complicated. We also draw two circles, but we have to animate them smoothly. That is why the size of every shape depends on a progress value.

OnDraw method from this class looks like this:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    tempCanvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR);
    tempCanvas.drawCircle(getWidth() / 2, getHeight() / 2, outerCircleRadiusProgress * maxCircleSize, circlePaint);
    tempCanvas.drawCircle(getWidth() / 2, getHeight() / 2, innerCircleRadiusProgress
                * (maxCircleSize + ADDITIONAL_SIZE_TO_CLEAR_ANTIALIASING), maskPaint);
    canvas.drawBitmap(tempBitmap, 0, 0, null);
}

Implementing this is a little tricky. I've used

tempCanvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR);

because I wanted to obtain circle with transparent area inside. And to reach this effect we have to create tempCanvas and tempBitmap. Similar implementation here: Android canvas: draw transparent circle on image

The last step is combining this views together (we can do it in FrameLayout) and change state of this views in the same time when user clicks it. The whole source code you can find on my github account https://github.com/ljarka/CircleAnimation

Comments