Changes fragments with sequential animation - android

I can't found how make animation between two fragments sequential. Is it possible?
For example. I have fragmentA and fragmentB. I can make animation
getSupportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.fragment_fade_in, R.anim.fragment_fade_out)
.replace(fragmentB)
.commit();
But animations shows together. I need scenario:
remove fragmentA with animation
waiting some ms
add fragmentB with animation
I found solution, but I think it's not good.
Handler mSequentiallyFrgAnimHandler = new Handler(Looper.getMainLooper());
//first remove preview fragment
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(0, R.anim.fragment_fade_out)
.remove(fragmentA)
.commit();
//we need animations sequentially, wait 400ms between animations
mSequentiallyFrgAnimHandler.postDelayed(new Runnable() {
#Override
public void run() {
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.fragment_fade_in, 0)
.add(fragmentB)
.commit();
}
}, 400);
Can someone give an example? How does it make correctly?

Related

Async Task running from Fragment

i saw a lot of posts saying that you should put your async task inside a Fragment(i dont remember other ways), so you can rotate screen and keep it...
but its not working for me
Activity shows the Fragment;
MyGetJsonFragment frag= ....
frag.setRetainInstance(true);
fm = getSupportFragmentManager();
ft = fm.beginTransaction();
ft.replace(R.id.fragment_main, frag);
ft.commit();
than, inside this Fragment i have a RecyclerView, and when the user click in any item on list, it call the Adapter and inside the adapter onBindViewHolder i implemented the onClick to call the AsyncTask
holder.button_get.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new AsyncGet(activity, AdapterList.this).execute();
}
});
if i use the configChanges ( android:configChanges="orientation|keyboardHidden|screenSize)
at manifest it works normal, but i heard and read that this is not a good workaround!
after removed the configChanges, if i rotate the screen, the progress dialog dismiss and than on the post execute i get the error at progressdialog.dissmiss or anyother thing that dependes the activity
i understood the activity life cycle that when i rotate the original that started the async is destroyed and new one is created...
but how can i handle it and still show the progressdialog?
i need the Context/Activity at the async to start the progress and i have some db methods inside the postExecute that use Activity/Context
and why setRetainInstance(true) is not holding the Instance?

Fragment - Wait until transaction animation is complete

I am using a simple slide left, slide right custom animation when I perform FragmentTransaction. My problem is, the fragment I'm loading with the transaction animation contains code in the onResume() to make a HTTP call which causes my "Please Wait" progress dialog to show. It works, but I would like the move my code from onResume to another method in the Fragment that would not fire until the fragment is completely loaded. In other words, when the animation is complete and it is completely slid into place.
I use this to start the new fragment
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.setCustomAnimation(R.anim.slide_in_right, R.anim.slide_out_left);
ft.replace(R.id.realtabcontent, new MyFragment());
ft.commit();
and I want the method in MyNewFragment() to initialize after the animation is 100% complete
Is that possible?
There are two approaches possible here,
Implement an AnimationListener on the slide-in animation.
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
In onAnimationEnd() of the listener, call a method in the fragment to make the HTTP call.
The above approach wastes time just for the sake of the animation. So, instead of having a progress dialog, implement a circular progress bar within your fragment. That way your animation and http call can happen simultaneously. Once you get the response, remove the progress spinner and show your actual fragment views.

FragmentManager.popBackStack() adds fragment below the current one

I'm learning how to use fragments properly.
I have 4 fragments:
A
B
Loading
Complete
It should replace each other in this sequence:
A ==> Loading ==> B ==> Loading ==> Complete
Method that change my Fragment A into Loading:
LoadingFragment loadingFragment = new LoadingFragment();
Bundle bundle = new Bundle();
bundle.putBoolean("fragmentA", true);
loadingFragment.setArguments(bundle);
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, loadingFragment)
.addToBackStack(null)
.commit();
Changing Fragment B into Loading looks similarly (only arguments are changed obviously)
Method that change Loading fragment into Fragment B:
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new FragmentB())
.commit();
}
}).start();
Thread.sleep(...) is just a long operation...
Obviously I'm not adding .addToBackStack(null) this time.
Ok. Now the problem:
When I use getFragmentManager().popBackStack() method, the previous fragment (A) is added below (my fragment container is LinearLayout) my actual fragment instead of replaceing it. According to this: https://stackoverflow.com/a/17793959/3279023 it should work, but it's not.
The behavior you are experiencing looks OK to me. popBackStack() reverses the last saved operation, which in your case is: replace A with Loading.
So it replaces Loading with A, but that has no effect on B obviously, which you added without recording the transaction.
A solution could be using addToBackStack() in both cases, so that both transaction are registered, and then call popBackStack() twice.
Several fragments can make one activity/screen. Backstack is like back arrow or go back to the last activity/screen.

Android scroll to bottom after new fragment added

I've got an App with a LinearLayout to which rectangular fragments are added below each other over time from top to bottom.
At some point the screen is full and the new fragments are "hidden" outside the view of the screen. What I'd like to do then is to make the App scroll to bottom every time a new fragment is added.
A fragment is added everytime a button in the activity is pushed or a checkbox in the above fragment is checked.
So I've tried the following in the onClickListeners and in the onCreateView of the fragments:
fm.beginTransaction().add(R.id.activity_uhf_layout, fragment).commit(); //Adding fragment
runOnUiThread(new Runnable() {
#Override
public void run() {
scrollView.scrollTo(0, scrollView.getBottom());
}});
This works sometimes, the fragment is added and the screen scrolls down, but its like 1/8 times.
I've tried other things such as:
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.scrollTo(0, scrollView.getBottom());
}
});
Which basically gives the same result and I've tried without the Runnable post, which doesn't work at all.
The result I'm getting is that the layout is only scrolled down to the bottom of the fragment which is already present and not all the way down to the end of the new fragment which has just been added by the fragmentmanager.
To me it seems that even though the fragment is added, the LayoutManager hasn't really "detected it" or something similar, but how to get around it, I'm not really sure about.
You could also try doing this.
fm.executePendingTransactions();
runOnUiThread(new Runnable() {
#Override
public void run() {
//Linearlayout is the layout the fragments are being added to.
View view = linearLayout.getChildAt(linearLayout.getChildCount()-1);
scrollView.scrollTo(0, view.getY() + view.getHeight());
}});
I don't know that the executePendingTransactions() is necessary, but if the view has been added, then that should work.

android lollipop - setentertransition() for fragment not working properly on exiting

While replacing fragment, I am using Slide animation available for android lollipop version. It works as expected for this particular replacement, but on pressing back button it first pops back current fragment & then reverse of enter animation (slide out) is executed.
private void replaceContentFrameByFragment(Fragment replaceBy, String replaceByFragmentTag) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Slide slide = new Slide(Gravity.BOTTOM);
slide.setDuration(1000);
replaceBy.setEnterTransition(slide);
}
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, replaceBy, replaceByFragmentTag);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commitAllowingStateLoss();
}
So, how to force fragment to pop back only after reverse animation of slide is finished? I noticed that activity has method finishAfterTransition() provided. Is there something similar for frgament?
I had the same issue, onReturn from Fragment B -> A, Fragment B seem to be doing an extra slide transition. To get around it, I put in a fade transition for setReturnTransition() of a shorter time than the slide which looks quite good (as it dissolves into previous fragment). The code for this is:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Slide slideRight = new Slide(Gravity.RIGHT);
slideRight.setDuration(200);
fragment.setEnterTransition(slideRight);
Fade fade = new Fade();
fade.setDuration(100);
fragment.setReturnTransition(fade);
}
I was having the same issue with roughly the same pattern and was able to get around it by posting my fragments transition:
new Handler().post(new Runnable() {
#Override
public void run() {
page.setEnterTransition(new Slide());
getFragmentManager()
.beginTransaction()
.replace(R.id.root_layout, page, "current")
.commit();
}
});
Not sure why this resolves the issue (or if this is the absolute correct solution), but it worked for me.

Categories

Resources