I implemented an animation for the item holder. However, When I tried to slide the view up and down, I noticed that the view items sometimes get animated and sometimes they don't, basically it's very random. Is there a cause for this?
private static void transition(RecyclerView.ViewHolder holder) {
ObjectAnimator animator = ObjectAnimator.ofFloat(holder.itemView, "translationX", -150, 0);
animator.setDuration(500);
animator.start();
}
#Override
public void onBindViewHolder(MovieView holder, int position) {
.........
.........
transition(holder);
}
Related
I am trying to animate a bar (just an ImageView) in the onBindViewHolder method.
If i don't try to animate it, it is working perfectly with this line:
holder.progressBar.getLayoutParams().width = 100;
But as soon as i add a function to animate this bar/imageView, it doesn't work.
I can see the bar only on the first item in the recyclerView and the bar is not animated.
this is the code that i use. what is the problem?
Thanks to all.
#Override
public void onBindViewHolder(ViewHolder holder, int position)
{
//holder.progressBarWeatherFactor.getLayoutParams().width = 100;
animateWidth(0, 100, holder.progressBar.getLayoutParams());
}
public void animateWidth(int start, int end, final ViewGroup.LayoutParams myBar)
{
ValueAnimator valueAnimator = ValueAnimator.ofInt(start, end);
valueAnimator.setDuration(1800);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
#Override
public void onAnimationUpdate( ValueAnimator valueAnimator)
{
myBar.width = ((int) valueAnimator.getAnimatedValue());
}
});
valueAnimator.start();
}
So, in order to help, i found a solution, maybe not the best but it is working and i hope it will help!
(the /10*3/64 is in relation with my image size, so don't matter of this)
#Override
public void onBindViewHolder(ViewHolder holder, int position)
{
animateWidth(0, 100, holder.progressBar);
}
public void animateWidth(int initialValue, int finalValue, ImageView image)
{
image.setPivotX(0f);
PropertyValuesHolder barWidth;
barWidth = PropertyValuesHolder.ofFloat("scaleX", 0, ((float)(((image.getResources().getDisplayMetrics().density)/10)*3)/64)*finalValue);
ObjectAnimator.ofPropertyValuesHolder(image, barWidth).setDuration(800).start();
}
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%
First of all please excuse me if this question is already asked.
I am new to android animations.
I want a view lets say an Image View (with animation i.e,smooth movement) to permanently move one position to some other position of the screen lets say if current X co-ordinate to X+50 and similarly Y co-ordinate to Y+50. I was able to move using XML translate animation file but not able to get click event after that.I am able to get click event at the original position in the layout not from the translated position.
Can anyone guide me to right track?
Thanks in advance.
The Animations you use are deprecated.. I show an example of ObjectAnimator class... And this sample is in a Fragment, so i write the whole onCreateView.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_screen, container, false);
ImageView image = (ImageView) rootView.findViewById(R.id.image);
ObjectAnimator translationY = ObjectAnimator.ofFloat(image, "translationY", 100);
translationY.setInterpolator(new AccelerateInterpolator());
ObjectAnimator translationX = ObjectAnimator.ofFloat(image, "translationX", 100);
translationX.setInterpolator(new AccelerateInterpolator());
AnimatorSet as = new AnimatorSet();
as.playTogether(translationX, translationY);
as.setDuration(2000);
as.start();
image.setOnClickListener(new View.OnClickListener() {
int sum = 0;
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), "Clicked: " + sum++, Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
Do animation programatically. Try this code. It may help
TranslateAnimation translateAnimation = new TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta);
translateAnimation.setDuration(500);
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
//before animation
}
#Override
public void onAnimationEnd(Animation animation) {
//after animation
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
imageView.startAnimation(translateAnimation);
You probably using view.startAnimation();. Key here is do your animation programatically.
do
Animation animation = AnimationUtils.loadAnimation (this.context, R.anim.your_translate_animation);
animation .setStartOffset (2000);
yourView.startAnimation (animation);
animation.setAnimationListener (new AnimationListener () {
#Override
public void onAnimationStart (Animation animation) {
}
#Override
public void onAnimationRepeat (Animation animation) {
}
#Override
public void onAnimationEnd (Animation animation) {
//do you click functionality here...
}
});
P.S. If you want to click view programtically
do
yourView.performClick();
I'm implementing a slot machine in Android. The reels are ScrollViews with LinearLayouts as children, and the individual tiles as ImageViews vertically oriented inside the LinearLayout. I'm using an ObjectAnimator to scroll to the end of the ScrollView, using ValueAnimator.RESTART and ValueAnimator.INFINITE. The reel scrolling is nice and smooth, however when it comes time to repeat, it pauses for a second, which ruins the effect. Here's the code I'm using:
public void spinReel(SlotReel reel) {
final int reelSize = this.context.getPixelsInDPs(64);
final SlotMachineView me = this;
final SlotReel myReel = reel;
ImageView[] tiles = reel.getTiles();
int delta = tiles.length - reel.currentTileNumber();
ObjectAnimator animator = ObjectAnimator.ofInt(reel, "scrollY", tiles.length * reelSize );
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(delta * 75);
animator.setStartDelay(0);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
myReel.scrollTo(0, reelSize * 3);
}
});
animator.start();
}
Note that the jerkiness occurs whether or not I put the scrollTo in the Repeat callback.
Example video here:
You should try:
setRepeatMode(ValueAnimator.INFINITE);
look here
Android ValueAnimator pauses during repeat
I have a Relative Layout containing some textviews which floats over a gridview. When I select an item in the grid, the layout moves down to nearly the end of the screen and only about 1/5th of it is visible. This is done using simple Translate Animation. Now when I click another button in the grid, I need to Relative Layout to move back to its original position on top of the gridview. I did this also with Translate Animation and this is happnening, but only the portion of the RelativeLayout which was visible when it was collapsed is translating (moving) and the other portion becomes visible after animation has ended. This looks really ugly.
I know that Android doesnt draw the portion of the view that is not visible on the screen. Is there a way to force draw the full portion ?
My Animation code is given below:
public void smoothExpanderAnimate(final int finalTarget,final RelativeLayout expander,final int animateToY,final boolean setExpanded,final boolean refreshGrid)
{
final RelativeLayout.LayoutParams head_params = (RelativeLayout.LayoutParams)expander.getLayoutParams();
TranslateAnimation anim = new TranslateAnimation(0f, 0f, 0f, animateToY);
anim.setDuration(400);
//timeListHeight = list.getHeight();
//anim.setFillAfter(true);
anim.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
//Should I try something here ?
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
head_params.topMargin = finalTarget;
expander.clearAnimation();
expander.setLayoutParams(head_params);
isExpanded = setExpanded;
isAnimating = false;
if(!setExpanded)
{
setChildHeight(timeListHeight, list);
}
}
});
isAnimating = true;
expander.startAnimation(anim);
}
I found a solution for this.
If you dont need to support lower API levels and are fine with API level 11 onwards, you can use ObjectAnimator for this. ObjectAnimator has a translatey method which works quite well.
If you need to support API 8 onwards, you need to make sure your view comes within the bounds of the screen and then animates. The following code modification did the trick.
I know it seems very weird, do let me know if there is a better way to do this.
public void smoothExpanderAnimate(boolean addSpecialFix,final int finalTarget,final RelativeLayout expander,final int animateToY,final boolean setExpanded,final boolean refreshGrid)
{
final RelativeLayout.LayoutParams head_params = (RelativeLayout.LayoutParams)expander.getLayoutParams();
TranslateAnimation anim = new TranslateAnimation(0f, 0f, 0f, animateToY);
anim.setDuration(400);
expander.setVisibility(View.INVISIBLE); //Make View invisible
if(isExpanded && addSpecialFix){
//THIS IS THE FIX
int old = head_params.topMargin;
head_params.topMargin = finalTarget;
expander.clearAnimation();
expander.setLayoutParams(head_params); //move invisible view to the final position
anim = new TranslateAnimation(0f, 0f, old-closedY, 0);
Log.d("asdasd", old+"");
anim.setDuration(400);
}
//timeListHeight = list.getHeight();
//anim.setFillAfter(true);
anim.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
head_params.topMargin = finalTarget;
expander.clearAnimation();
expander.setLayoutParams(head_params);
isExpanded = setExpanded;
isAnimating = false;
expander.setVisibility(View.VISIBLE);
if(refreshGrid)
{
mCalAdapter.notifyDataSetChanged();
}
if(!setExpanded)
{
setListHeight(timeListHeight, list);
}
}
});
isAnimating = true;
expander.startAnimation(anim);
}