How to shrink a finishing activity to a rectangle - android

In my Android app, I have a floating Activity. It's started from outside my app using ActivityOptions.makeScaleUpAnimation to scale up from an "originating" rectangle. When my Activity finishes, I'd like it to do the reverse of that animation: i.e. it shrinks back to that rectangle as it fades out.
I know I can get the rectangle with getIntent().getSourceBounds(), and I'd hoped to be able to use overridePendingTransition() when finishing to achieve this effect, but overridePendingTransition() can only accept a fixed XML resource: there doesn't seem to be a way to make that animation depend on the source bounds. Is there something else I can use to achieve this effect?
My app is for API 11+, but as it's a cosmetic effect only, I'd be satisfied with a solution that depends on a later version.

I don think there is a way to scale down the activity window other than the overridePendingTransition call. However this code may help:
Scale up
ActivityOptions opts = ActivityOptions.makeCustomAnimation(getActivity(), R.anim.scale_up, 0);
startActivity(new Intent(this, SecondActivity.class),opts.toBundle());
Here is the scale_up animation file:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="0"
android:toXScale="1.0"
android:fromYScale="0"
android:toYScale="1.0"
android:pivotX="50%p"
android:pivotY="50%p"
android:duration="500"/>
</set>
Scale down
Call this code from the exiting activity:
finish();
overridePendingTransition(0, R.anim.scale_down);
Here is the scale_down animation file:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:toXScale="0"
android:fromYScale="1.0"
android:toYScale="0"
android:pivotX="50%p"
android:pivotY="50%p"
android:duration="250"/>
</set>
You can vary the X and Y scale to get the desired rectangle. Hope this helps.

Based on my last comment, here is the solution which i have tried and it works. You may have to modify to suit your requirements.
Implement a Activity with Transparent background and with no title inside the manifest:
<activity
android:name="com.example.backgroundsensor.AnimatedActivity"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
android:label="Animated activity" />
and let it set the content view with a layout as :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
tools:ignore="MergeRootFrame" >
<View
android:id="#+id/visibleAreaView"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center"
android:background="#android:color/holo_green_dark" />
</FrameLayout>
The visibleAreaView is the one you will see on the screen, since activity is transparent. You can set the bounds of the view in OnCreate of the activity().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animated_activity);
// set the bounds of the animateView
}
Also, Override the finish method something like this:
boolean animateFirst=true;
#Override
public void finish() {
if(animateFirst)
{
animateFirst = false;
loadAnim();
}else
{
super.finish();
}
}
public void loadAnim() {
View v = findViewById(R.id.animateView);
float x= v.getX() + v.getRight()/2;
float y = v.getY();
anim = new ScaleAnimation(1.0f, 0.0f,1.0f, 0.0f, x, y);
anim.setDuration(300);
anim.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
findViewById(R.id.animateView).setVisibility(View.GONE);
AnimatedActivity.this.finish();
}
});
v.startAnimation(anim);
}

Related

Android change background image with fade in/out animation

I wrote code which can change background image random every 5 second.now i want to use fade in/out animation to change background image,but I do not know how I can use this animation.
This is a my source:
void handlechange() {
Handler hand = new Handler();
hand.postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// change image here
change();
}
private void change() {
// TODO Auto-generated method stub
Random rand = new Random();
int index = rand.nextInt(image_rundow.length);
mapimg.setBackgroundResource(image_rundow[index]);
handlechange();
}
}, 4000);
}
At the moment everything is OK. I can change background image random,but I don't know how can I use animation fade in/out.
If anyone knows solution please help me,
thanks.
You need to call these codes.
First, you have to make two xml files for fade in & out animation like this.
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:fillAfter="true"
android:duration="2000"
/>
</set>
fade_out.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.0"
android:fillAfter="true"
android:duration="2000"
/>
</set>
Second, you have to run animation of imageView like below and also you have to set AnimationListener to change fadeout when fadein finish.
Animation fadeOut = AnimationUtils.loadAnimation(YourActivity.this, R.anim.fade_out);
imageView.startAnimation(fadeOut);
fadeOut.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
Animation fadeIn = AnimationUtils.loadAnimation(YourActivity.this, R.anim.fade_in);
imageView.startAnimation(fadeIn);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
For fade in animation , create new folder named 'anim' in your res folder and inside it, create 'fade_in.xml' with following code
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:duration="#android:integer/config_mediumAnimTime"
android:fromAlpha="0.0"
android:interpolator="#android:anim/decelerate_interpolator"
android:toAlpha="1.0" />
</set>
now to run this animation on your imageview, use following code in your activity
Animation anim = AnimationUtils.loadAnimation(YourActivity.this, R.anim.fade_in);
imageView.setAnimation(anim);
anim.start();
for fadeout animation, just swap values of android:fromAlpha and android:toAlpha
Hope this helps.
You can use relativeLayout, and add one layer of background view which set both height and width match_parent. All other UI element should put on top of this view. In your code. Define fadeOut and fadeIn animation. Find that background view by id, then do this:
xxxBackground.startAnimation(fadeOut);
xxxBackground.setBackgroundResource(R.drawable.your_random_pic);
xxxBackground.startAnimation(fadeIn);
You can use some interpolator to tune the performance.
You need AnimationDrawable with animation.
First step AnimationDrawable
-Create a file /res/anim/anim_android.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="false">
<item android:drawable="#drawable/android_1"
android:duration="100"/>
<item android:drawable="#drawable/android_2"
android:duration="100"/>
<item android:drawable="#drawable/android_3"
android:duration="100"/>
<item android:drawable="#drawable/android_4"
android:duration="100"/>
<item android:drawable="#drawable/android_5"
android:duration="100"/>
<item android:drawable="#drawable/android_6"
android:duration="100"/>
<item android:drawable="#drawable/android_7"
android:duration="100"/>
</animation-list>
-Add a ImageView with android:src="#anim/anim_android".
<ImageView
android:id="#+id/myanimation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#anim/anim_android" />
Second step
-In your activity create AnimationDrawable and Animation
AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
animationDrawable.setOneShot(true);
animationDrawable.start();
Animation animation = AnimationUtils.loadAnimation(YourActivity.this, android.R.anim.fade_in);
imageView.setAnimation(animation);
animation.start();
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
Animation fadeOut = AnimationUtils.loadAnimation(YourActivity.this, android.R.anim.fade_out);
imageView.startAnimation(fadeOut);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
you don't need Handler.
Answer by kimkevin animates a View (be it an ImageView, TextView etc.) and not a background of a View. Which means if you want to just highlight any View, you'll have to add another View behind it (lets call it backgroundView) and animate that backgroundView.
Use the following code for animating background of a view
val startColor = view.solidColor
val endColor = ContextCompat.getColor(context, R.color.your_color)
val colorAnim = ObjectAnimator.ofInt(view, "backgroundColor", startColor, endColor, startColor)
colorAnim.duration = 2000
colorAnim.setEvaluator(ArgbEvaluator())
colorAnim.start()

Make activity animate from top to bottom

I am writing an Android app where I want the activity to appear by animating in from the bottom of the screen to the top. I am able to do this with code from here:
How to translate the activity from top to bottom and viceversa?
However, I am not able to do the vice-versa animation wherein the Activity would disappear by sliding from the top to the bottom of the screen.
I used the code in the above link; the activity appears by sliding up, but when disappearing, it fades out, instead of sliding to the bottom.
I even tried putting the code in onCreate() :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
overridePendingTransition(R.anim.appear_from_bottom, R.anim.disappear_to_bottom);
setContentView(R.layout.activity_all_metadata_display);
initializePage();
}
You need to define your "slide up" animations from the linked question, and some new "slide down" animations that reverse the process.
The important parts of the animations to look at are the fromYDelta and toYDelta values. These define the Y-positions (of the top of your view) at the start & end of the animations.
slide_in_up.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="#android:integer/config_longAnimTime"
android:fromYDelta="100%p"
android:toYDelta="0%p" />
slide_out_up.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="#android:integer/config_longAnimTime"
android:fromYDelta="0%p"
android:toYDelta="-100%p" />
slide_in_down.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="#android:integer/config_longAnimTime"
android:fromYDelta="-100%p"
android:toYDelta="0%p" />
slide_out_down.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="#android:integer/config_longAnimTime"
android:fromYDelta="0%p"
android:toYDelta="100%p" />
For the "slide up" animations, you should have overridden the pending transition in your onResume() method like this:
protected void onResume()
{
super.onResume();
overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up);
}
For the "slide down" animations, do something similar in your onPause() method:
protected void onPause()
{
super.onPause();
overridePendingTransition(R.anim.slide_in_down, R.anim.slide_out_down);
}
Some tutorials suggest using the wrong life-cycle methods:
onCreate() is not called every time the activity is shown
onDestroy() is not called every time the activity is taken away
Rather use methods that are called every time there is a screen transition:
onResume() is called when the activity is shown to the user
onPause() is called when the activity is going to be taken away
For more info on these methods specifically, check the Android developer site:
Pausing and Resuming an Activity
When your screen is displayed, it will slide in from the bottom.
When a new screen is displayed, your screen will slide back down.
Two ways of doing this:
1. Using styles
Assuming you wish to implement this for all activities, in your base theme define the following entry:
<item name="android:windowAnimationStyle">#style/ActivityAnimations</item>
Then define the following style:
<style name="ActivityAnimations" parent="android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">#anim/appear_from_bottom</item>
<item name="android:activityOpenExitAnimation">#anim/hold</item>
<item name="android:activityCloseEnterAnimation">#anim/hold</item>
<item name="android:activityCloseExitAnimation">#anim/disappear_to_bottom</item>
</style>
Where #anim/hold can be something like this:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" >
<translate
android:duration="1000"
android:zAdjustment="bottom" />
</set>
2. Using overridePendingTransition()
Override finish():
#Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.hold, R.anim.disappear_to_bottom);
}
Override onBackPressed():
#Override
public void onBackPressed() {
finish();
}
Override onOptionsItemSelected():
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
In your main xml file. Add id of the root tag and pass this to function. like
/** The Constant ANIM_NO. */
public static final int ANIM_NO = 0;
public static void topToDown(Context context, View target, int type,
int duration) {
if (type == UtilityAnimations.ANIM_NO) {
UtilityAnimations.topToDown(context, target, duration);
} else {
final Animation animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -1.0f,
Animation.RELATIVE_TO_SELF, 0.0f);
animation.setDuration(duration != 0 ? duration
: UtilityAnimations.DURATION_MEDIAM);
animation.setInterpolator(UtilityAnimations.getInterpolator(
context, type));
target.startAnimation(animation);
}
}
you can vice-versa your transition by overriding the Transition in your onPause() :
#Override
protected void onPause()
{
super.onPause();
overridePendingTransition(R.anim.appear_from_bottom, R.anim.disappear_to_bottom);
}

How to animate button in android?

I am making an android app, and I have a button which leads to a messaging place. On the activity with the button, I check if there is any unread messages, and if so I want to do something to the button to let the user know that there is something unread.
I was thinking of having the button sorta vibrate horizontally like 3 shakes every 2 or 3 seconds.
I know how to run a thread in the background which does something every x milliseconds. But what I don't know what to do is shake it horizontally 3 times.
Can anyone help with this?
I was thinking of using the sin function, for the animation, I can use output from a sin function to get values that go up and down, which I can set the horizontal position of the button... But this seems too extreme, is there a better way?
I can't comment on #omega's comment because I don't have enough reputation but the answer to that question should be something like:
shake.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100" <!-- how long the animation lasts -->
android:fromDegrees="-5" <!-- how far to swing left -->
android:pivotX="50%" <!-- pivot from horizontal center -->
android:pivotY="50%" <!-- pivot from vertical center -->
android:repeatCount="10" <!-- how many times to swing back and forth -->
android:repeatMode="reverse" <!-- to make the animation go the other way -->
android:toDegrees="5" /> <!-- how far to swing right -->
Class.java
Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
view.startAnimation(shake);
This is just one way of doing what you want, there may be better methods out there.
create shake.xml in anim folder
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="10"
android:duration="1000"
android:interpolator="#anim/cycle" />
and cycle.xml in anim folder
<?xml version="1.0" encoding="utf-8"?>
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:cycles="4" />
now add animation on your code
Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
anyview.startAnimation(shake);
If you want vertical animation, change fromXdelta and toXdelta value to fromYdelta and toYdelta value
Class.Java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_with_the_button);
final Animation myAnim = AnimationUtils.loadAnimation(this, R.anim.milkshake);
Button myButton = (Button) findViewById(R.id.new_game_btn);
myButton.setAnimation(myAnim);
}
For onClick of the Button
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(myAnim);
}
});
Create the anim folder in res directory
Right click on, res -> New -> Directory
Name the new Directory anim
create a new xml file name it milkshake
milkshake.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:fromDegrees="-5"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="10"
android:repeatMode="reverse"
android:toDegrees="5" />
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
public class HeightAnimation extends Animation {
protected final int originalHeight;
protected final View view;
protected float perValue;
public HeightAnimation(View view, int fromHeight, int toHeight) {
this.view = view;
this.originalHeight = fromHeight;
this.perValue = (toHeight - fromHeight);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
view.getLayoutParams().height = (int) (originalHeight + perValue * interpolatedTime);
view.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
}
uss to:
HeightAnimation heightAnim = new HeightAnimation(view, view.getHeight(), viewPager.getHeight() - otherView.getHeight());
heightAnim.setDuration(1000);
view.startAnimation(heightAnim);
Dependency
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}}
and then add dependency
dependencies {
compile 'com.github.varunest:sparkbutton:1.0.5'
}
Usage
XML
<com.varunest.sparkbutton.SparkButton
android:id="#+id/spark_button"
android:layout_width="40dp"
android:layout_height="40dp"
app:sparkbutton_activeImage="#drawable/active_image"
app:sparkbutton_inActiveImage="#drawable/inactive_image"
app:sparkbutton_iconSize="40dp"
app:sparkbutton_primaryColor="#color/primary_color"
app:sparkbutton_secondaryColor="#color/secondary_color" />
Java (Optional)
SparkButton button = new SparkButtonBuilder(context)
.setActiveImage(R.drawable.active_image)
.setInActiveImage(R.drawable.inactive_image)
.setDisabledImage(R.drawable.disabled_image)
.setImageSizePx(getResources().getDimensionPixelOffset(R.dimen.button_size))
.setPrimaryColor(ContextCompat.getColor(context, R.color.primary_color))
.setSecondaryColor(ContextCompat.getColor(context, R.color.secondary_color))
.build();
In Kotlin, this way after XML:
Define a View:
val playDel = findViewById<ImageView>(R.id.player_del)
Find a Animation: Here from Android Lib
val imgAnim = AnimationUtils.loadAnimation(this, android.R.anim.fade_out)
Connect to the View
playDel.animation=imgAnim
First create shake.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:fromDegrees="-5"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="10"
android:repeatMode="reverse"
android:toDegrees="5" />
Class.java
Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
view.startAnimation(shake);

Drawable displayed before tween animation

I have an activity (A) that launches another activity (B) after a calculation. My problem is that when Activity B is launched, an arrow drawable that is supposed to move from left to right while incrementing in size (scaled from .33 to 1) is first displayed for a very short fraction of time before it starts the tween animation. The end result is a bothering flicker of the full size drawable right before it starts animating.
Everything seems to point that the problem is related to the animation file (.xml) and not to the java class. This can be observed when I delete the line arrowImage.startAnimation(arrowExtent); in the following code:
protected void arrowAnimation(Animation arrowExtent) {
// TODO Auto-generated method stub
arrowImage.setImageResource(R.drawable.arrowimage);
arrowImage.startAnimation(arrowExtent);
arrowExtent.setFillAfter(true);
I have tried the following:
Using setImageDrawable instead of setImageResource to the Drawable object.
Setting arrowImage.setFillBefore(false);
Any recommendations will be greatly appreciated.
The animation xml is as follows:
<?xml version="1.0" encoding="utf-8"?>
<set android:interpolator="#android:anim/accelerate_decelerate_interpolator">
<scale
android:fromXScale="0.33"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="0"
android:duration="1000"
android:fillBefore="false" />
<translate
android:fromXDelta="0%"
android:toXDelta="75%p"
android:duration="1000" />
</set>
When activity start you should make ImageView invisible in xml or in onCreate() and when animation starts, you should change it to visible.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// referencing views etc.
arrowImage.setVisibility(View.INVISIBLE);
// or make image invisible in xml
}
protected void arrowAnimation(Animation arrowExtent) {
arrowExtent.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
arrowImage.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) { }
#Override
public void onAnimationEnd(Animation animation) { }
});
arrowImage.setImageResource(R.drawable.arrowimage);
arrowImage.startAnimation(arrowExtent);
}

How to preserve the ending values of an animation?

I use API 10.
I have an ImageView nested inside of a LinearLayout. The ImageView has an OnClickListener (or an OnTouchListener, I'm sure which one I ll use at the end). The ImageView is centered on the screen, and when clicked it performs the following animation.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillEnabled="true"
android:fillAfter="true"
>
<alpha
android:fromAlpha="1"
android:toAlpha="0"
android:duration ="500"
/>
<translate
android:fromXDelta="0%"
android:toXDelta="-100%p"
android:duration ="1000"
/>
</set>
The problem is that after the animation ends, it returns to its first position, faded out to 0, but it is still clickable even if it doesn't show up. I click on an empty space where the ImageView was first positioned, and it performs the the animation again. Like clicking a ghost.
How do I make it so that the ImageView stays at the position written at android:toXDelta ??
You can set an animationListener to your animation to tackle the problem, I created this simple fonction:
public void startAnimation(final View v, final int animationResourceId, AnimationListener l){
Animation anim;
if(v!=null){ // can be null, after change of orientation
anim = AnimationUtils.loadAnimation(v.getContext(),resId);
v.setAnimation(anim);
anim.setAnimationListener(l);
v.startAnimation(anim);
}
}
Then every time I need to animate an view, I can do something like this:
startAnimation(myView, R.anim.my_anim, new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
myView.setVisibility(View.GONE);
}
});

Categories

Resources