Animate Relative layout width change - android

Am trying to do a simple animation in order scale a relative layout's width. I managed to do it using this code but the animation is done very quickly even with 5000ms duration. I cant see the intermidiate results. Any suggestion?
RelativeLayout baseLayer;
RelativeLayout fillLayer;
public void animate(int duration){
Animation a = new Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
fillLayer.getLayoutParams().width = (int)(baseLayer.getLayoutParams().width * interpolatedTime);
fillLayer.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration(duration);
a.setInterpolator(new LinearInterpolator());
fillLayer.startAnimation(a);
}

I have found the solution. The problem was that i was calling the animation method from OnStart(). Now am calling it from onWindowFocusChanged().
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
testBar.animate(2000,0.8);
}
RelativeLayout baseLayer;
RelativeLayout fillLayer;
public void animate(int duration,float fillPercentage){
final int targetWidth = (int)(baseLayer.getMeasuredWidth() * fillPercentage);
Animation a = new Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
fillLayer.getLayoutParams().width = (int)(targetWidth * interpolatedTime);
fillLayer.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration(duration);
a.setInterpolator(new LinearInterpolator());
fillLayer.startAnimation(a);
}
And throughout this procedure I have found from other post an alternative way to do the same job. But again it the method need to be called form the onWindowFocusChanged().
ValueAnimator.ofObject(new WidthEvaluator(fillLayer), fillLayer.getLayoutParams().width, targetWidth).setDuration(2000).start();
class WidthEvaluator extends IntEvaluator {
private View v;
public WidthEvaluator(View v) {
this.v = v;
}
#Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int num = (Integer)super.evaluate(fraction, (Integer)startValue, (Integer)endValue);
ViewGroup.LayoutParams params = v.getLayoutParams();
params.width = num;
v.setLayoutParams(params);
return num;
}
}
[Update Solution]
Following to that I have added my custom views into a ListView and then the problems started again. ListView should be getting ready before views get their actual size. So the animation wasn't able to be done because getMeasuredWidth() was returning always 0 (this was and the problem from the beginning).
So what i did is i used this code snippet in OnCreate().
ViewTreeObserver vto = listBars.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (!HackClass.GlobalDrawnFlag) {
adapter.notifyDataSetChanged();
HackClass.GlobalDrawnFlag = true;
}
}
});
And this inside my list adapter class
if (item.getMeasuredWidth==0)
HackClass.GlobalDrawnFlag = false;
else
HackClass.GlobalDrawnFlag = true;
This approach solved all my problems apparently. However is that a good solution ? Any other suggestion is welcome.

Related

Enlarge animation in android

I want to achieve the below animation in android I have tried scenes but scenes do not work with text as per docs it is confirmed :
"If you try to resize a TextView with an animation, the text will pop to a new location before the object has completely resized. To avoid this problem, do not animate the resizing of views that contain text."
Please any solution , the enlarged layout text can contain images too.
animation video
this thing worked some how ,but the animation is little jittery,I guess layout height final value is attained first and layoutWidth later, have to fix this. this is my enlarge/reduce animation :
public class EnlargeAnimation extends Animation {
private final int diffHeight;
private final int diffWidth;
private final int initialHeight;
private final int initialWidth;
private final View targetView;
public EnlargeAnimation(View targetView, float targetHeight, float targetWidth) {
this.targetView = targetView;
this.initialHeight = targetView.getMeasuredHeight();
this.initialWidth = targetView.getMeasuredWidth();
this.diffHeight = (int) (targetHeight-initialHeight);
this.diffWidth = (int) (targetWidth-initialWidth);
}
#Override
public boolean willChangeBounds() {
return true;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float newHeight = initialHeight + diffHeight * interpolatedTime;
float newWidth = initialWidth + diffWidth * interpolatedTime;
targetView.getLayoutParams().height = (int) newHeight;
targetView.getLayoutParams().width = (int) newWidth;
targetView.requestLayout();
}
}
this is when enlarge animation is called :
I am using viewpager so i have to make padding negative to enlarge the card size :
ValueAnimator paddingAnimator = ValueAnimator.ofInt(20, -10).setDuration(400);
paddingAnimator.setInterpolator(new LinearInterpolator());
paddingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int padding = (int) animation.getAnimatedValue();
view.setPadding(padding,
(int) DeviceUtils.convertDpToPx(50, v.getContext()), padding,
(int) DeviceUtils.convertDpToPx(50, v.getContext()));
view.requestLayout();
}
});
viewPagerItemSizeListener.onEnlarged();
EnlargeAnimation
enlargeAnimation =
new EnlargeAnimation(cardView, screenHeight, screenWidth);
enlargeAnimation.setDuration(400);
enlargeAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
paddingAnimator.start();
seeExampleText.setVisibility(View.INVISIBLE);
}
#Override
public void onAnimationEnd(Animation animation) {
stage.setVisibility(View.GONE);
cardEnlargedWidth = cardView.getLayoutParams().width;
cardEnlargedHeight = cardView.getLayoutParams().height;
crossContianer.setVisibility(View.VISIBLE);
detailTextContianer.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
view.startAnimation(enlargeAnimation);
I guess no one is reading it, but if something is confusing about variables let me know i will edit the answer.

How to set smoothly animation to progressBar in android

In my project I want use ProgressBar and I want set smoothly countdown animation.
I write below codes for smoothly animation and when set 1000ms (1s) for duration show smoothly animation, but I want set 10000ms (10s) for duration.
When set 10000ms (10s) for duration not smoothly animation and show Fragmentary countdown.
But I want set 10000ms for duration and show smoothly countdown.
public class SimpleFrag extends Fragment {
TextView toolbar_title;
RelativeLayout toolbar;
private ProgressBar progressBar;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_simple, container, false);
ButterKnife.bind(this, view);
toolbar_title = getActivity().findViewById(R.id.toolbar_title);
toolbar = getActivity().findViewById(R.id.toolbar);
progressBar = view.findViewById(R.id.progress);
return view;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#SuppressLint("ObjectAnimatorBinding")
#Override
public void run() {
ProgressBarAnimation mProgressAnimation = new ProgressBarAnimation(progressBar, 79, 0);
mProgressAnimation.setDuration(10000);
progressBar.startAnimation(mProgressAnimation);
}
}, 50);
}
}
public class ProgressBarAnimation extends Animation {
private ProgressBar progressBar;
private float from;
private float to;
public ProgressBarAnimation(ProgressBar progressBar, float from, float to) {
super();
this.progressBar = progressBar;
this.from = from;
this.to = to;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
float value = from + (to - from) * interpolatedTime;
progressBar.setProgress((int) value);
}
}
}
How can I it? please help me . Thanks all <3
Take what you have now, and delete your setUserVisibleHint() method and your ProgressBarAnimation class. Add this:
private void setUpObserver() {
progressBar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
startAnimation();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
progressBar.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
else {
progressBar.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}
private void startAnimation() {
int width = progressBar.getWidth();
progressBar.setMax(width);
ValueAnimator animator = ValueAnimator.ofInt(0, width);
animator.setInterpolator(new LinearInterpolator());
animator.setStartDelay(0);
animator.setDuration(10_000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (int) valueAnimator.getAnimatedValue();
progressBar.setProgress(value);
}
});
animator.start();
}
Then, inside your onCreateView() method, call setUpObserver() right before you return view;
The setUpObserver() method uses an OnGlobalLayoutListener to make sure that the system waits until the ProgressBar is measured an laid out before starting the animation.
The startAnimation() method is what takes care of actually setting up and running the animation. You can modify the values passed to setStartDelay() and setDuration() as you see fit.
The trick to this solution is making sure that the maximum value for the progress bar is equal to its width, meaning that each increment of "progress" is equal to one pixel on the screen. The android framework animation takes care of making sure everything runs as smoothly as possible.
Edit
If you want to be able to control the start/end points for the animation (rather than just go from empty to full), make these changes:
Change the declaration of startAnimation() to this:
private void startAnimation(float startPercent, float endPercent)
Delete this line from inside startAnimation()
ValueAnimator animator = ValueAnimator.ofInt(0, width);
and add these lines instead:
int start = (int) (startPercent * width);
int end = (int) (endPercent * width);
ValueAnimator animator = ValueAnimator.ofInt(start, end);
Finally, call startAnimation() by passing in fractional percentages:
startAnimation(0.79f, 0.10f); // will animate from 79% to 10%

RecyclerView Q&A

I'm creating a Q&A where each question is a card. The answer starts showing the first line, but when its clicked it should expanded to show the full answer.
When an answer is expanded/collapsed the rest of the RecyclerView should animate to make room for the expansion or collapse to avoid showing a blank space.
I watched the talk on RecyclerView animations, and believe I want a custom ItemAnimator, where I override animateChange. At that point I should create an ObjectAnimator to animate the height of the View's LayoutParams. Unfortunately I'm having a hard time tying it all together. I also return true when overriding canReuseUpdatedViewHolder, so we reuse the same viewholder.
#Override
public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) {
return true;
}
#Override
public boolean animateChange(#NonNull RecyclerView.ViewHolder oldHolder,
#NonNull final RecyclerView.ViewHolder newHolder,
#NonNull ItemHolderInfo preInfo,
#NonNull ItemHolderInfo postInfo) {
Log.d("test", "Run custom animation.");
final ColorsAdapter.ColorViewHolder holder = (ColorsAdapter.ColorViewHolder) newHolder;
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) holder.tvColor.getLayoutParams();
ObjectAnimator halfSize = ObjectAnimator.ofInt(holder.tvColor.getLayoutParams(), "height", params.height, 0);
halfSize.start();
return super.animateChange(oldHolder, newHolder, preInfo, postInfo);
}
Right now I'm just trying to get something to animate, but nothing happens... Any ideas?
I think your animation was not working because you cannot animate LayoutParams that way although it would be neat if you could. I tried the code you had and all it did was make my view jump to the new height. Only way I found to get this to work was to use a ValueAnimator as you can see in the example below.
I noticed some shortcomings when using the DefaultItemAnimator to show/hide a view by updating its visibility. Although it did make room for the new view and animated the rest of the items up and down based on the visibility of the expandable view, I noticed it did not animate the height of the expandable view. It simply faded into place and out of place using alpha value only.
Below is a custom ItemAnimator that has size and alpha animations based on hiding/showing a LinearLayout in the ViewHolder layout. It also allows the reuse of the same ViewHolder and attempts handling partial animations correctly if the user taps the header quickly:
public static class MyAnimator extends DefaultItemAnimator {
#Override
public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) {
return true;
}
private HashMap<RecyclerView.ViewHolder, AnimatorState> animatorMap = new HashMap<>();
#Override
public boolean animateChange(#NonNull RecyclerView.ViewHolder oldHolder, #NonNull final RecyclerView.ViewHolder newHolder, #NonNull ItemHolderInfo preInfo, #NonNull ItemHolderInfo postInfo) {
final ValueAnimator heightAnim;
final ObjectAnimator alphaAnim;
final CustomAdapter.ViewHolder vh = (CustomAdapter.ViewHolder) newHolder;
final View expandableView = vh.getExpandableView();
final int toHeight; // save height for later in case reversing animation
if(vh.isExpanded()) {
expandableView.setVisibility(View.VISIBLE);
// measure expandable view to get correct height
expandableView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
toHeight = expandableView.getMeasuredHeight();
alphaAnim = ObjectAnimator.ofFloat(expandableView, "alpha", 1f);
} else {
toHeight = 0;
alphaAnim = ObjectAnimator.ofFloat(expandableView, "alpha", 0f);
}
heightAnim = ValueAnimator.ofInt(expandableView.getHeight(), toHeight);
heightAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
expandableView.getLayoutParams().height = (Integer) heightAnim.getAnimatedValue();
expandableView.requestLayout();
}
});
AnimatorSet animSet = new AnimatorSet()
.setDuration(getChangeDuration());
animSet.playTogether(heightAnim, alphaAnim);
animSet.addListener(new Animator.AnimatorListener() {
private boolean isCanceled;
#Override
public void onAnimationStart(Animator animation) { }
#Override
public void onAnimationEnd(Animator animation) {
if(!vh.isExpanded() && !isCanceled) {
expandableView.setVisibility(View.GONE);
}
dispatchChangeFinished(vh, false);
animatorMap.remove(newHolder);
}
#Override
public void onAnimationCancel(Animator animation) {
isCanceled = true;
}
#Override
public void onAnimationRepeat(Animator animation) { }
});
AnimatorState animatorState = animatorMap.get(newHolder);
if(animatorState != null) {
animatorState.animSet.cancel();
// animation already running. Set start current play time of
// new animations to keep them smooth for reverse animation
alphaAnim.setCurrentPlayTime(animatorState.alphaAnim.getCurrentPlayTime());
heightAnim.setCurrentPlayTime(animatorState.heightAnim.getCurrentPlayTime());
animatorMap.remove(newHolder);
}
animatorMap.put(newHolder, new AnimatorState(alphaAnim, heightAnim, animSet));
dispatchChangeStarting(newHolder, false);
animSet.start();
return false;
}
public static class AnimatorState {
final ValueAnimator alphaAnim, heightAnim;
final AnimatorSet animSet;
public AnimatorState(ValueAnimator alphaAnim, ValueAnimator heightAnim, AnimatorSet animSet) {
this.alphaAnim = alphaAnim;
this.heightAnim = heightAnim;
this.animSet = animSet;
}
}
}
This is the result using a slightly modified RecyclerView demo.
Update:
Just noticed your use case is actually a bit different after rereading the question. You have a text view and only want to show a single line of it and then later expand it to show all lines. Fortunately that simplifies the custom animator:
public static class MyAnimator extends DefaultItemAnimator {
#Override
public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder viewHolder) {
return true;
}
private HashMap<RecyclerView.ViewHolder, ValueAnimator> animatorMap = new HashMap<>();
#Override
public boolean animateChange(#NonNull RecyclerView.ViewHolder oldHolder, #NonNull final RecyclerView.ViewHolder newHolder, #NonNull ItemHolderInfo preInfo, #NonNull ItemHolderInfo postInfo) {
ValueAnimator prevAnim = animatorMap.get(newHolder);
if(prevAnim != null) {
prevAnim.reverse();
return false;
}
final ValueAnimator heightAnim;
final CustomAdapter.ViewHolder vh = (CustomAdapter.ViewHolder) newHolder;
final TextView tv = vh.getExpandableTextView();
if(vh.isExpanded()) {
tv.measure(View.MeasureSpec.makeMeasureSpec(((View) tv.getParent()).getWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.UNSPECIFIED);
heightAnim = ValueAnimator.ofInt(tv.getHeight(), tv.getMeasuredHeight());
} else {
Paint.FontMetrics fm = tv.getPaint().getFontMetrics();
heightAnim = ValueAnimator.ofInt(tv.getHeight(), (int)(Math.abs(fm.top) + Math.abs(fm.bottom)));
}
heightAnim.setDuration(getChangeDuration());
heightAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
tv.getLayoutParams().height = (Integer) heightAnim.getAnimatedValue();
tv.requestLayout();
}
});
heightAnim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
dispatchChangeFinished(vh, false);
animatorMap.remove(newHolder);
}
#Override
public void onAnimationCancel(Animator animation) { }
#Override
public void onAnimationStart(Animator animation) { }
#Override
public void onAnimationRepeat(Animator animation) { }
});
animatorMap.put(newHolder, heightAnim);
dispatchChangeStarting(newHolder, false);
heightAnim.start();
return false;
}
}
And the new demo:
You don't have to implement a custom ItemAnimator the default DefaultItemAnimator already supports what you need. However you need to tell this Animator which views changed. I guess you are calling notifyDataSetChanged() in your adapter. This prevents the animation for a single changed item in the RecyclerView (in your case the expand/collapse of the item).
You should use notifyItemChanged(int position) for the items that were changed. Here is a short itemClicked(int position) method that expands/collapses views in the RecyclerView. The field expandedPosition keeps track of the currently expanded item:
private void itemClicked(int position) {
if (expandedPosition == -1) {
// selected first item
expandedPosition = position;
notifyItemChanged(position);
} else if (expandedPosition == position) {
// collapse currently expanded item
expandedPosition = -1;
notifyItemChanged(position);
} else {
// collapse previously expanded item and expand new item
int oldExpanded = expandedPosition;
expandedPosition = position;
notifyItemChanged(oldExpanded);
notifyItemChanged(position);
}
}
This is the result:
According the documentation, you need to return false in animateChange or call runPendingAnimations later. Try returning false.
http://developer.android.com/reference/android/support/v7/widget/RecyclerView.ItemAnimator.html
Try this class:
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.graphics.Paint;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.TextView;
/**
* Created by ankitagrawal on 2/14/16.
*/
public class AnimatedViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
private int originalHeight = 0;
private boolean mIsViewExpanded = false;
private TextView textView;
// ..... CODE ..... //
public AnimatedViewHolder(View v) {
super(v);
v.setOnClickListener(this);
// Initialize other views, like TextView, ImageView, etc. here
// If isViewExpanded == false then set the visibility
// of whatever will be in the expanded to GONE
if (!mIsViewExpanded) {
// Set Views to View.GONE and .setEnabled(false)
textView.setLines(1);
}
}
#Override
public void onClick(final View view) {
// Declare a ValueAnimator object
ValueAnimator valueAnimator;
if(mIsViewExpanded) {
view.measure(View.MeasureSpec.makeMeasureSpec(((View) view.getParent()).getWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.UNSPECIFIED);
mIsViewExpanded = false;
valueAnimator = ValueAnimator.ofInt(view.getHeight(), view.getMeasuredHeight());
} else {
Paint.FontMetrics fm = ((TextView)view).getPaint().getFontMetrics();
valueAnimator = ValueAnimator.ofInt(view.getHeight(), (int) (Math.abs(fm.top) + Math.abs(fm.bottom)));
mIsViewExpanded = true;
}
valueAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) { }
#Override
public void onAnimationStart(Animator animation) { }
#Override
public void onAnimationRepeat(Animator animation) { }
});
valueAnimator.setDuration(200);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
view.getLayoutParams().height = (Integer) animation.getAnimatedValue();
view.requestLayout();
}
});
valueAnimator.start();
}
}
The Advantage of this approach is it only add animation to onClick event and that best suits your requirement.
adding animation to viewholder will be too burdensome to your requirement.
and itemAnimator as per doc are animation for layout out items so also not best suits your requirement.
For expand & collapse animation android there is github library for it.
ExpandableRecyclerView
1).Add dependencies in the build.gradle file
dependencies {
compile 'com.android.support:recyclerview-v7:22.2.0'
compile 'com.bignerdranch.android:expandablerecyclerview:1.0.3'
}
Image of Expand & Collapse Animation
2) Expand & Collapse animation for RecyclerView animation
public static class ExampleViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
private int originalHeight = 0;
private boolean isViewExpanded = false;
private YourCustomView yourCustomView
public ExampleViewHolder(View v) {
super(v);
v.setOnClickListener(this);
// Initialize other views, like TextView, ImageView, etc. here
// If isViewExpanded == false then set the visibility
// of whatever will be in the expanded to GONE
if (isViewExpanded == false) {
// Set Views to View.GONE and .setEnabled(false)
yourCustomView.setVisibility(View.GONE);
yourCustomView.setEnabled(false);
}
}
#Override
public void onClick(final View view) {
// If the originalHeight is 0 then find the height of the View being used
// This would be the height of the cardview
if (originalHeight == 0) {
originalHeight = view.getHeight();
}
// Declare a ValueAnimator object
ValueAnimator valueAnimator;
if (!mIsViewExpanded) {
yourCustomView.setVisibility(View.VISIBLE);
yourCustomView.setEnabled(true);
mIsViewExpanded = true;
valueAnimator = ValueAnimator.ofInt(originalHeight, originalHeight + (int) (originalHeight * 2.0)); // These values in this method can be changed to expand however much you like
} else {
mIsViewExpanded = false;
valueAnimator = ValueAnimator.ofInt(originalHeight + (int) (originalHeight * 2.0), originalHeight);
Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out
a.setDuration(200);
// Set a listener to the animation and configure onAnimationEnd
a.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
yourCustomView.setVisibility(View.INVISIBLE);
yourCustomView.setEnabled(false);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
// Set the animation on the custom view
yourCustomView.startAnimation(a);
}
valueAnimator.setDuration(200);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
view.getLayoutParams().height = value.intValue();
view.requestLayout();
}
});
valueAnimator.start();
}
}
Hope this will help you.

Expand Animation to work on both sides? (on negative axis)

I implemented an ExpandAnimation on view like this:
#Override
protected void applyTransformation(float interpolatedTime,
Transformation t) {
LayoutParams lp =
(LayoutParams) view.getLayoutParams();
if(rightAnimation){
lp.width = (int) (mStartWidth + mDeltaWidth *
interpolatedTime);
view.setLayoutParams(lp);
}else{
}
}
With this animation my view expands and shrinks.
What i want to do is to implement this animation to the other side (to -x side) as well. But i get confused a little bit, since shrinking the width will not work.
(Since minus widths or heights are not allowed)
Does anyone know a better way to implement expand animation to the left (-x) or up(-y) side as well?
Or maybe mirroring the view?
Finally I achieved to make a left hand side expand animation. Here is the code:
private class ExpandAnimation extends Animation implements Animation.AnimationListener {
private final int mStartWidth;
private final int mDeltaWidth;
int delta;
public ExpandAnimation(int startWidth, int endWidth) {
mStartWidth = startWidth;
mDeltaWidth = endWidth - startWidth;
RelativeLayout.LayoutParams param = (RelativeLayout.LayoutParams) getLayoutParams();
delta = param.width;
setAnimationListener(this);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
RelativeLayout.LayoutParams param = (RelativeLayout.LayoutParams) getLayoutParams();
delta = param.width;
if(param.width <= 0){
delta = 0;
}
param.width = (int) (mStartWidth + mDeltaWidth *
interpolatedTime);
if(delta != 0){
delta = (int) (mStartWidth + mDeltaWidth *
interpolatedTime) - delta;
}
param.leftMargin -=delta;
setLayoutParams(param);
}
#Override
public boolean willChangeBounds() {
return true;
}
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
setText(text);
requestLayout();
mExpanded = !mExpanded;
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
For a reason that I don't know, width comes as -2 in the start. So i filter out that by an if. Apply Transformation method does the job.

Android: No Animation is played (several buttons implementing the same animation effect)

I would like to apply the same alphaanimation for button A, B and C, and therefore implemented the following codes:
public void onCreate(Bundle savedInstanceState)
{
animation = new MutableAlphaAnimation();
animation.setAnimationListener(this);
btn_A.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
animation.setResetBlocked(true);
btn_A.setAnimation(animation);
animation.setResetBlocked(false);
animation.start(0.0f, 0.5f, FADE_IN_DURATION);
btn_A.invalidate();
}
});
}
public class MutableAlphaAnimation extends Animation
{
private float mFromAlpha;
private float mToAlpha;
private boolean resetBlocked;
public MutableAlphaAnimation()
{
}
public void start(float fromAlpha, float toAlpha, long duration)
{
mFromAlpha = fromAlpha;
mToAlpha = toAlpha;
setDuration(duration);
setStartTime(START_ON_FIRST_FRAME);
}
public void setResetBlocked(boolean resetBlocked)
{
this.resetBlocked = resetBlocked;
}
#Override
public void reset()
{
if (! resetBlocked) super.reset();
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
#Override
public boolean willChangeTransformationMatrix()
{
return false;
}
#Override
public boolean willChangeBounds()
{
return false;
}
}
Question:
btn_A, B and C are implemented with the same setOnClickListener. However, when they are pressed, nothing happen. Why? How can the above be modified?
Thanks!
You aren't applying your transformation to btn_home. Yes you set the it to the animation, but your animation class never touches btn_home. Your t.setAlpha... should really be btn_home.setAlpha..., so pass in the view using the constructor and then you can use it with any view in the future.

Categories

Resources