I want animate view on click of it. I am animating that view using AnimatorSet
But when user scroll at that time state of animation is not maintain or not clearAnimation properly. It will animate other item's icon.
anyone has idea on it?
animation method:
public static void likeAnimation(Object object) {
if (object == null) {
return;
}
AnimatorSet set = new AnimatorSet();
Object myView = object;
set.setInterpolator(new LinearInterpolator());
set.playTogether(
ObjectAnimator.ofFloat(myView, "rotation", 0, 360)
);
set.setDuration(500).start();
}
RecyclerView code:
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
holder.imageView_like.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
likeAnimation(v);
}
}
You're just in time with this question, and I hope I'm not too late. An idea here is very simple. You have to keep in mind that your RecyclerView reuses every single ViewHolder which has ever been created. Usually, it creates about 7~8 items, but it depends on screen size.
So, in your particular case if you want to animate an item upon click, you have to track the state of every item in your RecyclerView. Basically, you can have three states:
Enter state or your very animation. When the user clicks on some item from the list, you start animating that item, and in the end of animation switch the state of the item to Animated state.
Animated state. This is the state of an item that has been animated, and doesn't need this animation again, so when the user scrolls up/down you just need to set a view into the animated state. In your case, you can try the following code:
private void animatedState(View view){
//perform the same action but without animation
view.setRotation(360);
}
Default state or normal state. That is View without rotation, just a normal state. For instance,
private void defaultState(View view){
view.setRotation(0);
}
Also you may want to animate the items back upon click, if yes, you have to add one more state which is an Exit state, and then switch from that state to the Default state.
You can find the entire implementation of this idea by this link.
Related
I have RecyclerView and I want to animate one View inside RecyclerView item only for items which meet certain condition.
I'm using ObjectAnimator for this. Sometimes it is working fine, but sometimes animation is applied to all views. I assume there is some recycling problem with Views, but I'm not certain what can cause that.
Example:
val halfHeightCropped = halfHeight - (stopIndicatorHeight/2) //half item height minus half timeline circle height
val halfDistCurrToNext = timeDistCurrToNext/2
if (alreadyTraveled > halfDistCurrToNext){
animator = ObjectAnimator.ofFloat(indicator, "translationY", halfHeightCropped.toFloat()).apply {
duration = 0
start()
}
}
I'm an animating circle that is moving vertically through a timeline based on real-time. This circle is part of each RecyclerView item and in some items, this item is stationarily centered in item View, and some (1 at the time) is animating this circle vertically.
The example above is part of the function which is called from onBindViewHolder if the item meets the condition, otherwise, the view is reset to a default position. (layout param center vertical in an item).
when item select from recyclerView select that into adapter like
yourAdapter = new yourAdapter(new ArrayLis(),new ItemOnClick(){
#Override
public void onClick(int position){
yourAdapter.selectItem(position)
}
});
perform animate in bind() method of holder class.
if(selectedItem = getAdapterPosition){
//perform your animation for the selected item
}
your adapter should have the selectedItem variable and setter method for that.
I want to animate appearance of only last item of a recyclerview. Every time scroll is done to end, view should be shown with animation.
Applying Item Animator animates when item is removed, added, deleted. But i did not get option to animate in on scroll.
I applied animation in onBindView, but onBindView is not always called and animation is not started. Moreover, in cases onBindView is called and user is performing slow scroll operation, animation had already started when view is actually visible to user.
What can be suitable way to apply this animation?
Thanks
Vibhor
I have tested this solution and It's working like a charm.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
LinearLayoutManager layoutManager = LinearLayoutManager.class.cast(recyclerView.getLayoutManager());
int lastItem=adapter.getItemCount()-1;
tryAnimation(layoutManager.findViewByPosition(lastItem));
}
});
public void tryAnimation(View view) {
Animation animation = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
if (view != null)
view.startAnimation(animation);
}
this solution can be optimized by taking advantage of dy
I have an activity that (when started) shows some coachmark views (All ImageButtons) on screen that indicate how the app should be used (function of certain buttons, swipe behaviour, etc). A fade out animation is associated with each of these views that triggers after some predefined interval. This works as expected. However, I would like those marks to disappear earlier if the user interacts with the activity in a certain way. When these actions are triggered I cancel the animations and callsetVisibility(View.INVISIBLE); on the coachmark views. However, the visibility of the view does not change. I have experimented with other techniques - removing the view from the parent and setting alpha to 0 and these work fine but altering view visibility does nothing.
The code that sets up the coachmark looks as follows:
private void animateCoachmark(int id) {
AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);
final View view = findViewById(id);
animation.setStartOffset(10000);
animation.setDuration(500);
animation.setAnimationListener(new AnimationListenerBase(null) {
#Override
public void onAnimationEnd(Animation animation) {
view.setVisibility(View.INVISIBLE);
}
});
view.startAnimation(animation);
coachmarkViews.add(view);
}
The problematic code to change visiblity:
for (final View coachmarkView : coachmarkViews) {
Animation animation = coachmarkView.getAnimation();
if (animation != null) {
animation.cancel();
}
coachmarkView.setVisibility(View.INVISIBLE);
}
This issue seems to be that changes to visibility are not honoured as long as an animation is associated with a view even if the animation has been cancelled. Altering my cleanup code to first set the animation on the view to null allows the view to disappear as expected.
for (final View coachmarkView : coachmarkViews) {
Animation animation = coachmarkView.getAnimation();
if (animation != null) {
animation.cancel();
coachmarkView.setAnimation(null);
}
coachmarkView.setVisibility(View.INVISIBLE);
}
I have a listview in a fragment container.
Each view within the list has a gesture detector which on gesture up invalidates the list for redraw.
After an item selection I animate the fragment container to another part of the screen
ObjectAnimator x = ObjectAnimator.ofInt(ListLayout, "left", ListLayout.getLeft(), ListLayout.getLeft() - 336);
x.setDuration(500);
x.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
View ListLayout = findViewById(R.id.fragment_list_container);
Log.d(TAG, "ListLayout x after move completed = " + ListLayout.getLeft());
}
});
x.start();
All good to this point.
However if I select another item from the list (list should not move this time so animation not called) when the gesture up is detected and the list invalidated it reverts to it's original position?
If I getLeft before and after the initial animated move it returns the correct positions.
Any help or insight gratefully received,
Slip
For those that run into this problem it was simply because I was using "left" rather than translating the value.
I ended up compacting everything and using the new feature
mLayout.animate().setDuration(ANIMATE_TIME_MILLIS).translationXBy(ANIMATE_MOVE_DISTANCE);
found many question on same issue.
How to set OnClickListener on the ImageView after rotation animation
How to write the onclick listener for a view after animation?
i also have same issue, any suggestion ?
You ought to write a fresh, concise question about your specific issue rather than just pointing to other questions. The two questions linked to aren't entirely clear.
I assume your issue is that after applying an animation (such as a TranslateAnimation, for example) to a View, the View no longer responds to touch events in its new position. The reason for this is because the View hasn't been moved to the new position in terms of layout parameters, but rather it has had a transformation applied.
The solution is quite simple: immediately after the animation has completed, actually move the View to the new position. You could set myAnimation.setFillAfter() = false, and set a listener to physically move the View to the target location when the animation has finished:
myAmazingAnimation.setFillAfter() = false;
myAmazingAnimation.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationEnd(Animation animation) {
// Now actually move the View using LayoutParams
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationStart(Animation animation) {
}
});
Another variation is to physically move the View at the beginning before animation is applied, and then apply an animation that makes the View start where it used to be and end at 0,0.