Dynamic Animation - Android - android

I currently have a button that when clicked an animation begins that shows a LinearLayout above the button. The LinearLayout is directly above it. In the xml file the LinearLayouts visibility is set to GONE. So when the button is clicked the visibility is set to VISIBLE. Then the animation begins. The animation is a slidedown animation. Everything works perfectly. But When the button is clicked the button jumps to the bottom of where the LinearLayout ends. Even though the LinearLayout is still going through the animation. How can I make the button move with the LinearLayout animation? I want everything to be a smooth transition. But the button jumps and it doesn't look very smooth.
LInearLayout Animation
<?xml version="1.0" encoding="utf-8"?>
<!-- slide down -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="500"
android:fromXScale="1.0"
android:fromYScale="0.0"
android:interpolator="#android:anim/linear_interpolator"
android:toXScale="1.0"
android:toYScale="1.0" />
</set>

I just ran into a very similar situation today.
I used a custom animation that re sizes the view.
The required height is measured and saved. Initially the height is set to 0 and it grows as the animation goes on. Finally it reaches the measured height and then it is set to wrap content as it was originally.
public static void expand(final View v) {
v.measure(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
final int targetHeight = v.getMeasuredHeight();
v.getLayoutParams().height = 0;
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? LayoutParams.WRAP_CONTENT
: (int)(targetHeight * interpolatedTime);
v.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
v should be the LinearLayout you would like to animate.
You can choose a fixed time duration if you preffer.
source: https://stackoverflow.com/a/13381228/1646326

Use custom animation, it's very easy you can change whatever you want in applytransformation,
interpolatedTime - this is current position like in % from start to end animation (and has float value from 0 to 1, so here using this interpolatedTime you can iterate anything you can imagine) ;)
static class HeightAnimation extends Animation{
private View view;
private int mViewHeightFrom;
private int mViewHeightTo;
public HeightAnimation(View view, int heightFrom, int heightTo){
this.view = view;
this.mViewHeightFrom = heightFrom;
this.mViewHeightTo = heightTo;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int)((mViewHeightTo - mViewHeightFrom)*interpolatedTime+0.5));
view.setLayoutParams(params);
}
#Override
public boolean willChangeBounds() {
return true;
}
#Override
public boolean isFillEnabled() {
return true;
}
}
and the usage:
public static void applyAnimationHeightTransformation(Context context, View view, int viewHeightFrom, int viewHeightTo, int duration, int animationOffsetMilisec){
HeightAnimation anim = new HeightAnimation(view, viewHeightFrom, viewHeightTo);
anim.setStartOffset(animationOffsetMilisec);
anim.setDuration(duration);
//anim.setInterpolator(new OvershootInterpolator()); // here interpolators can be used
if(view != null) {
view.setAnimation(anim);
view.startAnimation(anim);
}
}
for height to make easier using - use values in dp via transform to pixels:
public static int dpToPx(int dp) {
return (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, YourApplication.getMainContext().getResources().getDisplayMetrics()));
}

Related

2nd animation starts at top of screen instead of location of previous animation

I have two animations that are to occur one after the other. The first one works as expected, however, the 2nd animation jumps to the very top of the screen at the first animation's onAnimationEnd() call. A balloon ImageView "floats" up to the center of the screen, and it is supposed to expand (the rest will be implemented later. I'm just trying to get this part to work). The first animation is pure Java, not xml.
The second animation's xml (bounce.xml):
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="2000"
android:fromXScale="1.0"
android:toXScale="2.0"
android:fromYScale="1.0"
android:toYScale="2.0"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
My BounceInterpolator class:
public class BounceInterpolator implements Interpolator {
private double mAmplitude = 1;
private double mFrequency = 10;
BounceInterpolator(double amplitude, double frequency) {
mAmplitude = amplitude;
mFrequency = frequency;
}
public float getInterpolation(float time) {
return (float) (-1 * Math.pow(Math.E, -time/ mAmplitude) * Math.cos(mFrequency * time) + 1);
}
}
And finally the class where it all happens:
public class CelebrateActivity extends AppCompatActivity {
ImageView purple_balloon_1;
Animation anim;
Animation bounceAnim;
RelativeLayout layout;
MediaPlayer mediaPlayer;
DisplayMetrics displayMetrics;
static int height;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_celebrate);
displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
height = displayMetrics.heightPixels;
mediaPlayer = MediaPlayer.create(this, R.raw.first_love);
mediaPlayer.start();
layout = findViewById(R.id.relativeLayout);
purple_balloon_1 = findViewById(R.id.purple_balloon_1);
slideUp();
}
public void slideUp() {
Animation slide = null;
slide = new TranslateAnimation(0, 0, height, height / 2 - 100);
slide.setDuration(15000);
slide.setFillAfter(true);
slide.setFillEnabled(true);
purple_balloon_1.startAnimation(slide);
bounceAnim = AnimationUtils.loadAnimation(CelebrateActivity.this, R.anim.bounce);
BounceInterpolator interpolator = new BounceInterpolator(0.2, 20);
bounceAnim.setInterpolator(interpolator);
slide.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
purple_balloon_1.startAnimation(bounceAnim); //Where the 2nd animation is supposed to start. It works, but it jumps to the top of the screen.
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
}
Why does it jump to the top of the screen, and how can I set the Y coordinate to the location of the ImageView to prevent said jumping?
#pskink - Thank you for the tips. I went with ObjectAnimator and AnimatorSet. I got rid of both of my xml files and the BounceInterpolator class, which saved a lot of code in the process. The animation is working perfectly now.
Again, thank you.
public class CelebrateActivity extends AppCompatActivity {
ImageView purple_balloon_1;
//Animation slide;
//Animation grow;
AnimatorSet animatorSet;
RelativeLayout layout;
MediaPlayer mediaPlayer;
DisplayMetrics displayMetrics;
static int height;
public static final String TAG = "CelebrateActivity.this";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_celebrate);
displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
height = displayMetrics.heightPixels;
mediaPlayer = MediaPlayer.create(this, R.raw.first_love);
mediaPlayer.start();
layout = findViewById(R.id.relativeLayout);
purple_balloon_1 = findViewById(R.id.purple_balloon_1);
animatorSet = new AnimatorSet();
ObjectAnimator slide = ObjectAnimator.ofFloat(purple_balloon_1, "translationY", height, height / 2);
slide.setDuration(15000);
ObjectAnimator growX = ObjectAnimator.ofFloat(purple_balloon_1, "scaleX", 1.5f);
growX.setDuration(500);
ObjectAnimator growY = ObjectAnimator.ofFloat(purple_balloon_1, "scaleY", 1.5f);
growY.setDuration(500);
animatorSet.playTogether(growX, growY);
animatorSet.playSequentially(slide, growX);
animatorSet.start();
}
}

How to shrink and move the view in android?

I want to shrink and animate the Relative layout into right side like below Image, am using translate animation to move the layout to right side(translate animation working fine), but not able to shrink the view.Am not able to achieve like image.Can any one know help me to solve this issue.
Whenever click the button(Three line button) in relative layout.shrink the view and move it right side.
Translate animation code
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="#android:integer/config_mediumAnimTime"
android:fillAfter="true"
android:fillEnabled="true" >
<translate
android:fromXDelta="0"
android:toXDelta="90%" />
</set>
Java Code
bt1 = (Button)findViewById(R.id.button1);
bt1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (view_moved != 1) {
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.translate);
anim_lay.startAnimation(animation);
view_moved = 1;
}
}
});
View animation does not resample the views drawable, only applies scale matrix to it so it might become blurry or have artifacts. Use object/value animator to animate layout's height/width instead so that it is redrawn on every change.
ValueAnimator widthAnim = ValueAnimator.ofInt(viewGroup.getMeasuredWidth(), desiredWidth);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = viewGroup.getLayoutParams();
layoutParams.width = val;
viewGroup.setLayoutParams(layoutParams);
}
});
ValueAnimator heightAnim = ValueAnimator.ofInt(viewGroup.getMeasuredHeight(), desiredHeight);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = viewGroup.getLayoutParams();
layoutParams.height = val;
viewGroup.setLayoutParams(layoutParams);
}
});
AnimatorSet scaleAnimation = new AnimatorSet();
scaleAnimation.playTogether(widthAnim, heighthAnim);
scaleAnimation.setDuration(500).start();
where viewGroup is your RelativeLayout

Slidedown and slideup layout with animation

how can I display a layout in the center with slideUp when I press the button, and press again to hide ... slideDown in ANDROID
help me with that, thnkss
Create two animation xml under res/anim folder
slide_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="1000"
android:fromYDelta="0"
android:toYDelta="100%" />
</set>
slide_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="1000"
android:fromYDelta="100%"
android:toYDelta="0" />
</set>
Load animation Like bellow Code and start animation when you want According to your Requirement
//Load animation
Animation slide_down = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.slide_down);
Animation slide_up = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.slide_up);
// Start animation
linear_layout.startAnimation(slide_down);
I use these easy functions, it work like jquery slideUp slideDown, use it in an helper class, just pass your view :
public static void expand(final View v) {
v.measure(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
final int targetHeight = v.getMeasuredHeight();
// Older versions of android (pre API 21) cancel animations for views with a height of 0.
v.getLayoutParams().height = 1;
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? WindowManager.LayoutParams.WRAP_CONTENT
: (int)(targetHeight * interpolatedTime);
v.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1){
v.setVisibility(View.GONE);
}else{
v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
v.requestLayout();
}
}
#Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
Above method is working, but here are more realistic slide up and slide down animations from the top of the screen.
Just create these two animations under the anim folder
slide_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="-100%"
android:toYDelta="0" />
</set>
slide_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="0"
android:toYDelta="-100%" />
</set>
Load animation in java class like this
imageView.startAnimation(AnimationUtils.loadAnimation(getContext(),R.anim.slide_up));
imageView.startAnimation(AnimationUtils.loadAnimation(getContext(),R.anim.slide_down));
This doesn't work for me, I want to to like jquery slideUp / slideDown function, I tried this code, but it only move the content wich stay at the same place after animation end, the view should have a 0dp height at start of slideDown and the view height (with wrap_content) after the end of the animation.
From JAVA file: Use this is the method.
public class ViewAnimatorSlideUpDown {
public static void slideDown(final View view) {
if (view != null) {
view.setVisibility(View.VISIBLE);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = 1;
view.setLayoutParams(layoutParams);
view.measure(View.MeasureSpec.makeMeasureSpec(Resources.getSystem().getDisplayMetrics().widthPixels,
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED));
final int height = view.getMeasuredHeight();
ValueAnimator valueAnimator = ObjectAnimator.ofInt(1, height);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
if (height > value) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = value;
view.setLayoutParams(layoutParams);
} else {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
view.setLayoutParams(layoutParams);
}
}
});
valueAnimator.start();
}
}
public static void slideUp(final View view) {
if (view != null) {
view.post(new Runnable() {
#Override
public void run() {
final int height = view.getHeight();
ValueAnimator valueAnimator = ObjectAnimator.ofInt(height, 1);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
if (value > 0) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = value;
view.setLayoutParams(layoutParams);
} else {
view.setVisibility(View.GONE);
}
}
});
valueAnimator.start();
}
});
}
}
}
======================================================================
And Use it into Java file ex.
if (binding.llTheme.getVisibility() == View.GONE) {
ViewAnimatorSlideUpDown.slideDown(binding.llTheme);
binding.llTheme.setVisibility(View.VISIBLE);
} else {
binding.llTheme.setVisibility(View.GONE);
ViewAnimatorSlideUpDown.slideUp(binding.llTheme);
}
Done. ☻♥ keep it up.
I had a similar requirement in the app I am working on. And, I found a third-party library which does a slide-up, slide-down and slide-right in Android.
Refer to the link for more details: https://github.com/mancj/SlideUp-Android
To set up the library(copied from the ReadMe portion of its Github page on request):
Get SlideUp library
Add the JitPack repository to your build file. Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
maven { url "https://maven.google.com" } // or google() in AS 3.0
}
}
Add the dependency (in the Module gradle)
dependencies {
compile 'com.github.mancj:SlideUp-Android:2.2.1'
compile 'ru.ztrap:RxSlideUp2:2.x.x' //optional, for reactive listeners based on RxJava-2
compile 'ru.ztrap:RxSlideUp:1.x.x' //optional, for reactive listeners based on RxJava
}
To add the SlideUp into your project, follow these three simple steps:
Step 1:
create any type of layout
<LinearLayout
android:id="#+id/slideView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Step 2:
Find that view in your activity/fragment
View slideView = findViewById(R.id.slideView);
Step 3:
Create a SlideUp object and pass in your view
slideUp = new SlideUpBuilder(slideView)
.withStartState(SlideUp.State.HIDDEN)
.withStartGravity(Gravity.BOTTOM)
//.withSlideFromOtherView(anotherView)
//.withGesturesEnabled()
//.withHideSoftInputWhenDisplayed()
//.withInterpolator()
//.withAutoSlideDuration()
//.withLoggingEnabled()
//.withTouchableAreaPx()
//.withTouchableAreaDp()
//.withListeners()
//.withSavedState()
.build();
You may also refer to the sample project on the link. I found it quite useful.

Gmail like listview item remove

I'm trying to achieve something the Gmail app (ICS) offers on deleting message. I wan't all rows below deleted cell to move up and cover deleted cell.
Here is working animation:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" >
<translate android:fromYDelta="0%" android:toYDelta="-100%"
android:duration="#android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="#android:integer/config_mediumAnimTime" />
</set>
All I came up with so far is this:
public static List<View> getCellsBelow(ListView listView, int position) {
List<View> cells = new ArrayList<View>();
for (int i = position + 1; i <= listView.getLastVisiblePosition(); i++) {
cells.add(listView.getChildAt(i));
}
return cells;
}
I gather visible cells bellow the selected cell and then animate them in foreach. I fear this is performance disaster. I also have trouble notify adapter that it should reload it's content. normally I'd call notifyDataSetChanged on onAnimationEnd but now there are couple of animations playing one after another.
Any suggestions pals? Maybe there is something that allows to animate couple of views stimulatenously?
Update:: I recommend checking out this solution by Chet Haase who works at the Android team. Especially if you are not developing for Android 2.3 and lower.
This should be exactly what you want.
list.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent,
final View view, final int position, long id) {
removeRow(view, position);
return true;
}
});
private void removeRow(final View row, final int position) {
final int initialHeight = row.getHeight();
Animation animation = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime,
Transformation t) {
super.applyTransformation(interpolatedTime, t);
int newHeight = (int) (initialHeight * (1 - interpolatedTime));
if (newHeight > 0) {
row.getLayoutParams().height = newHeight;
row.requestLayout();
}
}
};
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
row.getLayoutParams().height = initialHeight;
row.requestLayout();
items.remove(position);
((BaseAdapter) list.getAdapter()).notifyDataSetChanged();
}
});
animation.setDuration(300);
row.startAnimation(animation);
}
The original author of this published the code as a Gist here: https://gist.github.com/2980593
and here is the original Google+ post from Roman Nurik: https://plus.google.com/113735310430199015092/posts/Fgo1p5uWZLu
You can try the ListView I made for this. It's on Github.

In android how to make a image grow from one point using animation?

In android how to make a image grow from one point using animation?
I mean to say is...i have a button ..and i want is when i click on that button my image must grow(ascending order) to grow bigger and bigger from that point ...and when again i click on that button again it must collapse gowing smaller and smaller to end at that point
Can any anybody help me in doing this using android animation?
i'm new to android
This can be achieved using View Animation utility. This scales the image from 100% to 140% for 1 sec
Place the following file in res/anim/scale.xml
<?xml version="1.0" encoding="utf-8"?>
<set android:shareInterpolator="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="1.4"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="1000" />
</set>
Java code
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final View view = findViewById(R.id.imageView1);
final Animation anim = AnimationUtils.loadAnimation(this, R.anim.scale);
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
view.startAnimation(anim);
}
});
}
I would suggest you look at this SO post:
Android: Expand/collapse animation
public class DropDownAnim extends Animation {
int targetHeight;
View view;
boolean down;
public DropDownAnim(View view, int targetHeight, boolean down) {
this.view = view;
this.targetHeight = targetHeight;
this.down = down;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
int newHeight;
if (down) {
newHeight = (int) (targetHeight * interpolatedTime);
} else {
newHeight = (int) (targetHeight * (1 - interpolatedTime));
}
view.getLayoutParams().height = newHeight;
view.requestLayout();
}
#Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
#Override
public boolean willChangeBounds() {
return true;
}
}
You would have to use that as an example as you want to apply it to your button.
Starting with Android 3.0, the preferred way of animating views is to
use the android.animation package APIs.These Animator-based classes change actual properties of the View object, ....
Or you can use a ViewPropertyAnimator for simple things - an image button that grows over a period of 1000ms to 1.4 x its size:
imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imageButton.animate().
scaleX(1.4f).
scaleY(1.4f).
setDuration(1000).start();
}
});

Categories

Resources