Recycler View add Item Animator not animating - android

I am trying to use a custom Item Animator for animating an itemview after clicking a button. After clicking the add button, the new item appear, but the desired animation does not happen. It just appears suddenly. I have tried everything, please help.
viewholder_add_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration = "500"
android:fromXScale="0%"
android:fromYScale="0%"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="100%"
android:toYScale="100%"/>
</set>
CustomItemAnimator
import android.view.animation.AnimationUtils;
import com.example.bookui.R;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
public class CustomItemAnimator extends DefaultItemAnimator {
#Override
public boolean animateRemove(RecyclerView.ViewHolder holder) {
return super.animateRemove(holder);
}
#Override
public boolean animateAdd(RecyclerView.ViewHolder holder) {
holder.itemView.setAnimation(AnimationUtils.loadAnimation(holder.itemView.getContext(),
R.anim.viewholder_add_anim));
return super.animateAdd(holder);
}
}
Main Activity
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerViewBooks;
private BookAdapter bookAdapter;
private List<Book> mdata;
private Button addButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initmdataBooks();
setUpBookAdapter();
}
private void initViews() {
addButton = findViewById(R.id.add_btn);
recyclerViewBooks = findViewById(R.id.recyclerView);
recyclerViewBooks.setHasFixedSize(true);
recyclerViewBooks.setItemAnimator(new CustomItemAnimator());
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addBook();
}
});
}
private void initmdataBooks() {
mdata = new ArrayList<>();
mdata.add(new Book(R.drawable.book1));
mdata.add(new Book(R.drawable.book2));
mdata.add(new Book(R.drawable.book3));
mdata.add(new Book(R.drawable.book2));
mdata.add(new Book(R.drawable.book4));
mdata.add(new Book(R.drawable.book5));
mdata.add(new Book(R.drawable.book1));
mdata.add(new Book(R.drawable.book1));
mdata.add(new Book(R.drawable.book5));
}
private void setUpBookAdapter() {
bookAdapter = new BookAdapter(mdata);
recyclerViewBooks.setAdapter(bookAdapter);
}
private void addBook() {
Book book = new Book(R.drawable.book4);
mdata.add(1, book);
bookAdapter.notifyDataSetChanged();
}
}

You have to properly fullfill ItemAnimator contract instead of blindly overriding animateAdd:
Don't call through to super.animateAdd(holder) - you're just going to run into conflict with default fade in animation.
You have to keep track of this animation and call dispatchAddStarting(holder) / dispatchAddFinished(holder) to inform super implementation of current animation state.
You have to override few more methods (in code below) that must be aware of whether your animations are running and provide cancellation option
Sample DefaultItemAnimator overriden to run a scale up animation on newly added items:
public class AddRecAnimator extends DefaultItemAnimator {
private final static String TAG = "AddRecAnimator";
// must keep track of all pending/ongoing animations.
private final ArrayList<AddHolder> pending = new ArrayList<>();
private final HashMap<RecyclerView.ViewHolder, AddHolder> additions = new HashMap<>();
#Override
public boolean animateAdd(RecyclerView.ViewHolder holder) {
pending.add(new AddHolder(holder));
return true; // return true to receive call to runPendingAnimations
}
#Override
public void runPendingAnimations() {
for (AddHolder ah : pending) {
ah.start();
}
pending.clear();
super.runPendingAnimations();
}
#Override
public void endAnimation(RecyclerView.ViewHolder item) {
AddHolder ah = additions.get(item);
if (ah != null) {
ah.endAnimation();
}
super.endAnimation(item);
}
#Override
public void endAnimations() {
for (AddHolder ah : pending) {
ah.resetViewHolderState();
dispatchAddFinished(ah.holder);
}
for (AddHolder ah : additions.values()) {
ah.resetViewHolderState();
dispatchAddFinished(ah.holder);
}
pending.clear();
additions.clear();
super.endAnimations();
}
#Override
public boolean isRunning() {
return super.isRunning() &&
!pending.isEmpty() &&
!additions.isEmpty();
}
/**
* This is container for addition animation. It's also end listener for it.
*/
private final class AddHolder implements Animation.AnimationListener {
private final RecyclerView.ViewHolder holder;
private AddHolder(RecyclerView.ViewHolder holder) {
this.holder = holder;
Animation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(500);
anim.setAnimationListener(this);
holder.itemView.setAnimation(anim);
dispatchAddStarting(holder);
}
void start() {
View itemView = holder.itemView;
Animation a = itemView.getAnimation();
if (a != null) {
a.start();
additions.put(holder, this);
} else {
endAnimation(); // invalid state, animation missing
}
}
private void resetViewHolderState() {
// reset state as if no animation was ran
Animation a = holder.itemView.getAnimation();
if (a != null) {
a.setAnimationListener(null);
a.cancel();
holder.itemView.clearAnimation();
}
holder.itemView.setScaleX(1f);
holder.itemView.setScaleY(1f);
}
// called when animation ends or is manually cancelled
protected void endAnimation(){
additions.remove(holder);
resetViewHolderState();
dispatchAddFinished(holder);
// if all animations in animator are done dispatch they're finished
if (!isRunning()) dispatchAnimationsFinished();
}
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
endAnimation();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
}

Related

Toggle play pause ImageView inside listview

I have a list view of songs with play and pause button in every row.
Obviously, I can't have two pause Icon(two playing song)at the same time in my list view So I need to first reset all of them to play Icon then set the selected view to pause Icon.
How can I achieve this?
This is what I have done so far:
In the model class ( Product ):
public boolean paused = true;
private int PlayPauseId;
public int getPlayPauseId(){
return PlayPauseId;
}
public void setPlayPauseId(int playPauseId) {
PlayPauseId = playPauseId;
}
in Adapter:
public interface PlayPauseClick {
void playPauseOnClick(int position);
}
private PlayPauseClick callback;
public void setPlayPauseClickListener(PlayPauseClick listener) {
this.callback = listener;
}
.
.
.
holder.playPauseHive.setImageResource(product.getPlayPauseId());
holder.playPauseHive.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (callback != null) {
callback.playPauseOnClick(position);
}
}
});
my Callback inside my Activity:
#Override
public void playPauseOnClick(int position) {
final Product product = movieList.get(position);
if (product.paused) {
product.setPlayPauseId(R.drawable.ic_pause);
product.paused=false;
}else {
product.setPlayPauseId(R.drawable.ic_play);
product.paused = true;
}
this.adapter.notifyDataSetChanged();
}
You have to check condition in your getView() method of adapter like this:
if (product.paused) {
holder.playPauseHive.setImageResource(R.drawable.ic_play);
}else {
holder.playPauseHive.setImageResource(R.drawable.ic_pause);
}

Making a perfect Chromeless Youtube Player in Android

What i created while making CHROMELESS youtube player view is here. It is loading and playing perfectly but the buffering circle plays continuously even when video gets completed. Can anyone help me to remove buffering progress when it is not required and make a perfect youtube player?
MainActivity.java
package com.rocky.youtubedemo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import com.google.android.youtube.player.YouTubeBaseActivity;
import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayerView;
public class MainActivity extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener {
private static final int RECOVERY_REQUEST = 1;
private static String YOUTUBE_API_KEY = "";
private YouTubePlayerView youTubeView;
private Context context;
private MyPlayerStateChangeListener playerStateChangeListener;
private MyPlaybackEventListener playbackEventListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
playerStateChangeListener = new MyPlayerStateChangeListener();
playbackEventListener = new MyPlaybackEventListener();
YOUTUBE_API_KEY = "PLACE_YOUR_API_KEY_HERE";
youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view);
youTubeView.initialize(YOUTUBE_API_KEY, this);
}
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, final YouTubePlayer player, boolean wasRestored) {
player.setPlayerStateChangeListener(playerStateChangeListener);
player.setPlaybackEventListener(playbackEventListener);
if (!wasRestored) {
player.loadVideo("fhWaJi1Hsfo"); // Plays https://www.youtube.com/watch?v=fhWaJi1Hsfo
player.setPlayerStyle(YouTubePlayer.PlayerStyle.CHROMELESS);
}
}
#Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult errorReason) {
if (errorReason.isUserRecoverableError()) {
Toast.makeText(context, errorReason.toString(), Toast.LENGTH_LONG).show();
// errorReason.getErrorDialog(this, RECOVERY_REQUEST).show();
} else {
String error = errorReason.toString();
Toast.makeText(context, error, Toast.LENGTH_LONG).show();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECOVERY_REQUEST) {
// Retry initialization if user performed a recovery action
getYouTubePlayerProvider().initialize(YOUTUBE_API_KEY, this);
}
}
private void showMessage(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
protected YouTubePlayer.Provider getYouTubePlayerProvider() {
return youTubeView;
}
private final class MyPlaybackEventListener implements YouTubePlayer.PlaybackEventListener {
#Override
public void onPlaying() {
// Called when playback starts, either due to user action or call to play().
showMessage("Playing");
}
#Override
public void onPaused() {
// Called when playback is paused, either due to user action or call to pause().
showMessage("Paused");
}
#Override
public void onStopped() {
// Called when playback stops for a reason other than being paused.
showMessage("Stopped");
}
#Override
public void onBuffering(boolean b) {
showMessage("buffer");
}
#Override
public void onSeekTo(int i) {
// Called when a jump in playback position occurs, either
// due to user scrubbing or call to seekRelativeMillis() or seekToMillis()
}
}
private final class MyPlayerStateChangeListener implements YouTubePlayer.PlayerStateChangeListener {
#Override
public void onLoading() {
showMessage("loading");
}
#Override
public void onLoaded(String s) {
showMessage("loaded");
}
#Override
public void onAdStarted() {
// Called when playback of an advertisement starts.
}
#Override
public void onVideoStarted() {
// Called when playback of the video starts.
showMessage("started");
}
#Override
public void onVideoEnded() {
// Called when the video reaches its end.
}
#Override
public void onError(YouTubePlayer.ErrorReason errorReason) {
// Called when an error occurs.
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.youtube.player.YouTubePlayerView
android:id="#+id/youtube_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
In your onInitializationSuccess(), set a PlaybackEventListener on the player. Override the onBuffering() and do something like this:
ViewGroup ytView = youTubeView; // if you are using YouTubePlayerView
ViewGroup ytView = (ViewGroup)ytPlayerFragment.getView(); // if you are using YouTubePlayerFragment
ProgressBar progressBar;
try {
// As of 2016-02-16, the ProgressBar is at position 0 -> 3 -> 2 in the view tree of the Youtube Player Fragment/View
ViewGroup child1 = (ViewGroup)ytView.getChildAt(0);
ViewGroup child2 = (ViewGroup)child1.getChildAt(3);
progressBar = (ProgressBar)child2.getChildAt(2);
} catch (Throwable t) {
// As its position may change, we fallback to looking for it
progressBar = findProgressBar(ytView);
// I recommend reporting this problem so that you can update the code in the try branch: direct access is more efficient than searching for it
}
int visibility = isBuffering ? View.VISIBLE : View.INVISIBLE;
if (progressBar != null) {
progressBar.setVisibility(visibility);
// Note that you could store the ProgressBar instance somewhere from here, and use that later instead of accessing it again.
}
Make method like this one:
private ProgressBar findProgressBar(View view) {
if (view instanceof ProgressBar) {
return (ProgressBar)view;
} else if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup)view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
ProgressBar res = findProgressBar(viewGroup.getChildAt(i));
if (res != null) return res;
}
}
return null
}
By this way you can enable progress when it is buffering and disable it when it is not.

How to find memory leaks using LeakCanary in the Android app?

Help please find memory leaks in my app.
LeakCanary:
-static android.app.ActivityThread.sCurrentActivityThread
-references android.utill.ArrayMap.mArray
-reference array java.lang.Object[].1
-references android.app.ActivityThread$ActivityClientRecord.activity
-references MainActivity.tf (tf - my fragment)
-leaks TheaterFragment instance
Example code fragment:
public class TheaterFragment extends Fragment {
Typeface face;
private View view;
private RelativeLayout rl;
private LinearLayout linearLayout;
private int wordLheigh, screenWidht, wordLength, margin, btnHeight;
private String word;
private float scale;
private Animation anim;
private int tangelSound, whooshSound;
private SoundPool mSoundPool2;
private int soundMusic;
private boolean startAnim = false;
private LayoutAnimationController controller;
#Override
public void onStart(){
super.onStart();
if (!word.equals("suoh") && startAnim) {
anim = AnimationUtils.loadAnimation(getActivity(), R.anim.theater);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mSoundPool2.play(whooshSound, soundMusic, soundMusic, 0, 0, 1);
rl.setClickable(false);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// linearLayout.startLayoutAnimation();
startAnim = false;
Animation anim1 = AnimationUtils.loadAnimation(getActivity(), R.anim.blueword);
anim1.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mSoundPool2.play(tangelSound, soundMusic, soundMusic, 0, wordLength, 0.5f);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// rl.setClickable(true);
}
});
controller = new LayoutAnimationController(anim1, 0.5f);
linearLayout.setLayoutAnimation(controller);
linearLayout.setLayoutAnimationListener(new Animation.AnimationListener() {
public void onAnimationEnd(Animation _animation) {
rl.setClickable(true);
}
public void onAnimationRepeat(Animation _animation) {
}
public void onAnimationStart(Animation _animation) {
}
});
linearLayout.setVisibility(View.VISIBLE);
linearLayout.startLayoutAnimation();
}
});
rl.setVisibility(View.VISIBLE);
rl.startAnimation(anim);
}
}
public void falseClickable(){
rl.setClickable(false);
rl.setEnabled(false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
face = Typefaces.get(getContext(), getContext().getText(R.string.font_droidsans).toString());
if (Build.VERSION.SDK_INT >= 21)
{
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
mSoundPool2 = new SoundPool.Builder()
.setAudioAttributes(attributes)
.build();
} else {
mSoundPool2 = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
}
tangelSound = mSoundPool2.load(getActivity(), R.raw.tangel, 1);
whooshSound = mSoundPool2.load(getActivity(), R.raw.whoosh3, 1);
scale = getArguments().getInt("scale");
wordLheigh = getArguments().getInt("wordLheigh");
screenWidht = getArguments().getInt("screenWidht");
word = getArguments().getString("word");
wordLength = word.length();
soundMusic = getArguments().getInt("soundMusic");
startAnim = getArguments().getBoolean("startAnim");
//Log.e("TylyTaay", Integer.toString(FINAL));
margin = (int) (getResources().getDimension(R.dimen.word_btn_margin)+0.5f);
btnHeight = (int) (screenWidht / 10 - 4 * margin +0.5f);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_theater, container, false);
rl = (RelativeLayout) view.findViewById(R.id.theaterLayout);
TextView tv1 = (TextView) view.findViewById(R.id.textView1);
TextView tv2 = (TextView) view.findViewById(R.id.textView1);
tv1.setTypeface(face);
tv2.setTypeface(face);
if (!word.equals("suoh")){
linearLayout = (LinearLayout) view.findViewById(R.id.clonWordLayout);
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, wordLheigh);
lparams.setMargins(0, screenWidht, 0, 0);
linearLayout.setLayoutParams(lparams);
setClon();
} else {
rl.setVisibility(View.VISIBLE);
}
return view;
}
#Override
public void onDestroy() {
super.onDestroy();
linearLayout.removeAllViews();
linearLayout = null;
RefWatcher refWatcher = MyApp.getRefWatcher(getActivity());
refWatcher.watch(this);
}
private void setClon()
{
Button btn;
for(int i = 0; i < wordLength; i++)
{
btn = new Button(getActivity());
char[] ch = {word.charAt(i)};
String st = new String(ch);
btn.setText(st);
btn.setGravity(Gravity.CENTER);
btn.setPadding(0, 0, 0, 0);
btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.word_btn_text_size));
btn.setBackgroundResource(R.drawable.btn_word_win);
btn.setTextColor(getResources().getColorStateList(R.color.dark_gray));
btn.setClickable(false);
btn.setTypeface(face);
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(btnHeight, btnHeight);
lparams.setMargins(margin, 0,margin, 0);
linearLayout.addView(btn, lparams); //Добавляем в LinearLayout
}
btn = null;
}
public void playSound(int nameSound ) {
if (soundMusic == 1)
mSoundPool2.play(nameSound,1,1,0,0,1);}
The sample code in MainActivity, which call the fragment:
private void rightAnswer()
{
if (imgZoom != null) {
imgZoomBack(wordL);
}
wordL.blockWord(false);
buttonL.blockBtn(false);
gridView.setOnItemClickListener(null);
//tf = new TheaterFragment(scale, wordLheigh, screenWidht, word, bar.tvDiamond, bar.tvLevel, bar.imageView, wordId);
if (tf == null) {
tf = new TheaterFragment();
}
if (args == null) {
args = new Bundle();
}
args.putFloat("scale", scale);
args.putInt("wordLheigh", wordLheight);
args.putInt("screenWidht", screenWidht);
args.putInt("soundMusic", soundOnOff);
args.putBoolean("startAnim", true);
args.putString("word", word);
//Log.e("TylyTaay", Integer.toString(wordId));
args.putInt("wordId", wordId);
tf.setArguments(args);
args = null;
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frameLayout, tf)
.commit();
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tgDiamond);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tgVolume);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tvDiamond);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tvLevel);
bar.imageView.setVisibility(View.VISIBLE);
YoYo.with(Techniques.SlideInDown)
.playOn(bar.imageView);}
I'm late for the response, this might be helpful for others.
As mentioned by #tsiro LeakCanary has its own bugs, you can go here for more details.
For your code,
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frameLayout, tf)
.commit();
Here you are adding the fragment in FragmentManager but you are not removing it when the activity goes to background or when the fragment is changed/reinitialised.
Try removing the fragment from the fragment manager, if you are using .add().
You can use .replace() which calls .remove() and .add() implicitly.
I hope it helps.
i have just noticed that i take the same output in my application.Even though i double checked my app for possible memory leaks and after i resolve the actual point in my code where memory leak occured, i am still getting this message...you do not have to worry about it, probably it is a bug created by LeakCanary library...just ignore it as i did..

A custom function structure for my customView.onclick

I have searched but could not find answer of my question.
This is what I have:
private class BoxView extends View {
private String caption;
private OnClickListener bvClickListener = null
public BoxView(Context context) {
super(context);
this.bvClickListener = new this.OnClickListener(){
public void onClick (View v){
/*v.setCaption("X"); view don't have this method */
}}
}
public void setCaption(String s){
this.caption=s;
invalidate();
}
}
This is what I want to have:
private class BoxView extends View {
private String caption;
private OnClickListener bvClickListener = null
public BoxView(Context context) {
super(context);
this.bvClickListener = new this.OnClickListener(){
public void onClick (BoxView bv){
bv.setCaption("X");
}}
}
public void setCaption(String s){
this.caption=s;
invalidate();
}
}
I may need custom methods for my custom views. And I want to be able to pass my custom view instead of view version of it when onclick is triggered so I can access to it directly.
Updated
And I want to have access to real object not a converted one. So I want to avoid this:
public void onClick (View v){
((BoxView)v).setCaption("X");
}
Call setCaption method as in onClick :
public void onClick (View v){
((BoxView)v).setCaption("X");
}
Try this
class Main extents Activity
{
BoxView boxView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// if view is used using layout then
boxView = (BoxView)findViewByID(id);
//else if directly used
boxView = new BoxView(this);
box.setOnClickListener(new onClickListener()
{
#Override
public void onClick(View view) {
boxView.setCaption("X");
boxView.invalidate();
}
});
}
}

Cannot repeat animation on Floating Action Button

Now that I can animate my FloatingActionButton, I have another issue.
When I click on the FAB, the rotation of the FAB starts and keeps going until an AsyncTask finishes its job.
Here are the parts of the code related:
#OnClick(R.id.floating_action_button) //Butterknife feature
public void refreshAccountInfo(){
APIHandler api = new APIHandler(databaseHelper, c, getActivity());
AccountSync accountSync = new AccountSync(api);
accountSync.execute();
}
public class AccountSync extends AsyncTask<Void,Void,Account> {
APIHandler apiHandler;
ObjectAnimator animation;
public AccountSync(APIHandler api){
apiHandler = api;
}
#Override
protected void onPreExecute(){
FloatingActionButton button = ButterKnife.findById(getActivity(), R.id.floating_action_button);
PropertyValuesHolder pvhR = PropertyValuesHolder.ofFloat(View.ROTATION, -360);
animation = ObjectAnimator.ofPropertyValuesHolder(button, pvhR);
animation.setRepeatCount(Animation.INFINITE);
animation.setDuration(1500);
animation.start();
}
#Override
protected Account doInBackground(Void... params) {
Account a;
try {
a = apiHandler.getAccountInfo();
return a;
} catch (final ResponseException e) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(apiHandler.getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
});
return null;
}
}
#Override
protected void onPostExecute(Account result) {
animation.setRepeatCount(0);
if(result!=null){
a = result;
showInfo();
Toast.makeText(getActivity(),"Account synchronization done",Toast.LENGTH_SHORT).show();
}
}
}
My problem is, when I trigger the button the first time, the animation plays fine, but when I try to click more times, the AsyncTask will do its job, but the rotation animation will never play until I reload the fragment completely.
How can I fix that ?
You can for example end the animation in onPostExecute like this :
#Override
protected void onPostExecute(Account result) {
if(animation.isRunning())
animation.end();
...
}
}
That should be more efficient than setting repeatCount to 0.

Categories

Resources