I have a ListView whose items need to be collapsed with an animation and then deleted. I use Animation for collapsing items, and after it's done collapsing I delete the item from the ListView (by deleting it from data list and calling notifyDataSetChanged). To detect if animation is done I check if interpolatedTime == 1.0 in applyTransformation method. The problem is that applyTransformation is called twice with `interpolatedTime' == 1, so I can't really rely on that (otherwise I can delete two items instead of just one). Why is this happening? Here's some of my code:
public static void collapseAndDelete(final View v, final ArrayList<AlarmClock> alarmClockArrayList,
final AlarmsArrayAdapter adapter, final int position) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime == 1) {
alarmClockArrayList.remove(position);
adapter.notifyDataSetChanged();
} else {
v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
v.requestLayout();
v.setAlpha(1.0f - interpolatedTime);
}
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration(400);
v.startAnimation(a);
}
Implement animation listener to catch final callback
r.setAnimationListener(new OAnimationListener(this));
example of the class:
public class OAnimationListener implements AnimationListener{
private MyView vv;
public OAnimationListener(MyView vv) {
// TODO Auto-generated constructor stub
this.vv = vv;
}
#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) {
if (vv != null)
vv.stopAnim(2); //or any wanted callback
}
}
do not forget to setup this:
r.setRepeatCount(0);
r.setFillAfter(true);
Related
I am looking for height animation for RelativeLayout. Normally it should be starting from base value to the height of the layout. I was trying to write with EasyAndroidAnimation library. But could not succeed. Below code is attached. It is bouncing up from the base. I need something smooth.
new BounceAnimation(this.LayoutGraph)
.setBounceDistance(50)
.setNumOfBounces(5)
.setDuration(500)
.animate();
Also I am looking for something easy like this as I have to use the approach for many layouts:
layout.startfrom(basevalue)
layout.to(height of the layout)
layout.animate()
Any help will be appreciated.
CODE Adding*
As Requested Please find the below code which I am trying.
I am calling the animation by calling the below code.
expand(this.mFirstGraph);
expand method
public void expand(final View v) {
v.measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
int i = (int)(0.075F * this.mWidthScreen);
//this.mFirstGraph.getLayoutParams().height = i;
int length=(int)(0.425F * this.mWidthScreen * (this.maxTemp - this.mWeatherModel.mWeekHighTemperatures[0]) / this.ratioTemp);
final int targetHeight = i+ length;
Log.e("BASIC5", "targetHeight: "+targetHeight);
// 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
? LinearLayout.LayoutParams.WRAP_CONTENT
: (int)(targetHeight * interpolatedTime);
v.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
public void animate() {
// TODO Auto-generated method stub
}
};
// 1dp/ms
//a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
a.setDuration(2000);
Log.e("BASIC5", "Duration value: "+ (int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
a.setInterpolator(new AccelerateInterpolator(3));
v.startAnimation(a);
}
public 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;
}
public void animate() {
// TODO Auto-generated method stub
}
};
// 1dp/ms
//a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
a.setDuration(200);
//a.setInterpolator(new DecelerateInterpolator());
v.startAnimation(a);
}
Problems identified currently
The animation is not smooth.
Height is not proper. Which I am currently working on it.
Maybe this basic example could help you:
public void expand(final View v) {
v.measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.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
? LinearLayout.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));
//a.setInterpolator(new AccelerateInterpolator(3));
v.startAnimation(a);
}
public 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));
//a.setInterpolator(new DecelerateInterpolator());
v.startAnimation(a);
}
I have a custom view kind of like a progress bar. inside this view i have an ObjectAnimator.AnimatorUpdateListener which i'm trying to use to call invalidate on the view. However, my view is not updating! I tried to add a button which simply changed the value to something else and called invalidate once and it worked, my view updated to reflect the value change.
Am I missing something here? Am I calling invalidate too many times or something?
My "progressbar" starts with a float at 0, and the animation is supposed to animate it to 100. Calling a method to update it to 50 and call invalidate works, but the ObjectAnimator doesnt seem to be calling invalidate.
Everything is being called on the UI Thread
ObjectAnimator does not call invalidate() - your method should do it when needed
ObjectAnimator oAnimator = ObjectAnimator.ofInt(view,"someproperty",0,100)
void setSomeProperty(value) {
mValue = value
invalidate()
}
I have used this and it worked.
public interface ProgressAnimationListener {
public void onAnimationStart();
public void onAnimationFinish();
public void onAnimationProgress(int progress);
}
private ObjectAnimator progressBarAnimator;
public synchronized void animateProgressTo(final int start, final int end, final int duration, final ProgressAnimationListener listener) {
stopAnimation();
setProgress(start);
progressBarAnimator = ObjectAnimator.ofFloat(this, "animateProgress", start, end);
progressBarAnimator.setDuration(duration);
progressBarAnimator.setInterpolator(new LinearInterpolator());
progressBarAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationCancel(final Animator animation) {
}
#Override
public void onAnimationEnd(final Animator animation) {
setProgress(end);
if (listener != null) {
listener.onAnimationFinish();
}
}
#Override
public void onAnimationRepeat(final Animator animation) {
}
#Override
public void onAnimationStart(final Animator animation) {
if (listener != null) {
listener.onAnimationStart();
}
}
});
progressBarAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(final ValueAnimator animation) {
int progress = ((Float) animation.getAnimatedValue()).intValue();
if (progress != getProgress()) {
//Log.d(TAG, progress + "");
setProgress(progress);
if (listener != null) {
listener.onAnimationProgress(progress);
}
}
}
});
progressBarAnimator.start();
}
public synchronized boolean isAnimationRunning() {
return progressBarAnimator != null && progressBarAnimator.isRunning();
}
public synchronized void stopAnimation() {
if (isAnimationRunning()) {
progressBarAnimator.cancel();
progressBarAnimator = null;
}
}
I have a RelativeLayout having the visibility gone containing 3 action buttons. I want to animate this layout to SlideUp and SlideDown on clicking on an dropdown image.
Here is a utility class that could do this for you:
public class AnimExpandCollapse {
public static void expand(final View v) {
v.measure( LayoutParams.MATCH_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);
}
public static void setViewToWrappedHeight(View v) {
v.getLayoutParams().height = LayoutParams.WRAP_CONTENT;
}
public static void collapse(final View v) {
collapse(v, null, true, 0);
}
public static void collapse(final View v, Animation.AnimationListener animationListener, boolean autoDuration, int duration) {
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
if (autoDuration) {
a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
} else {
a.setDuration(duration);
}
if (animationListener!=null) a.setAnimationListener(animationListener);
v.startAnimation(a);
}}
I want do a animate scroll like Jquery´s (in this web page works when you click in top menu´s options) in android. is it possible? I have seen that exists scrollTo but is possible to do with animation and not like jumps. Thank you very much.
Using ObjectAnimator, This is a sample for scrolling to top :
public void scroolToTop() {
int x = 0;
int y = 0;
ObjectAnimator xTranslate = ObjectAnimator.ofInt(mScrollView, "scrollX", x);
ObjectAnimator yTranslate = ObjectAnimator.ofInt(mScrollView, "scrollY", y);
AnimatorSet animators = new AnimatorSet();
animators.setDuration(1000L);
animators.playTogether(xTranslate, yTranslate);
animators.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator arg0) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animator arg0) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator arg0) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationCancel(Animator arg0) {
// TODO Auto-generated method stub
}
});
animators.start();
}
I have implemented an animation for a Layout that must flow downwards and upwards. The animation precisely must flow in both low that high. This gridview is located above a ExpandbleListView. So, when I close all the groups the animation is very fluid. When the groups on the list are open, with many elements, however the animation is triggered, it is not as fluid as I would like it to be. I'll post the code of my animation:
public void expand(final View v) {
v.measure(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
final int targtetHeight = 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) (targtetHeight * interpolatedTime);
v.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
Interpolator i = AnimationUtils.loadInterpolator(this,
android.R.anim.linear_interpolator);
a.setInterpolator(i);
a.setDuration(200);
v.startAnimation(a);
}
and :
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(200);
v.startAnimation(a);
}
How can I do to make the animation smoother?
--> Edit: I was wrong code, I corrected