I've put following code into onDrawerSlide method of navigation drawer in order to move content when drawer is opening.
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
container.setTranslationX(slideOffset * drawerView.getWidth());
mDrawerLayout.bringChildToFront(drawerView);
mDrawerLayout.requestLayout();
}
It works perfectly almost always, except of first app run - I open drawer programmatically to teach user using it.
So, when I'm calling
if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
mDrawerLayout.openDrawer(mFragmentContainerView);
}
drawer is opening, but onDrawerSlide is not called.
I suppose, reason is that something does not have enough time to load, but I don't know what exactly and how escape this.
It works when I'm calling openDrawer in a few seconds after run (via Handler), but it looks terrible on UI.
PS. Tried to call openDrawer in onCreate, onResume, in calling Activity - still no result.
PPS. Also I'm unable to call onDrawerSlide directly - because I don't know slideOffset value.
I think when you open drawer programmatically to teach user using it, you need to call DrawerLayout.DrawerListener.onDrawerSlide(View drawerView, float slideOffset) with a Handler or an AsyncTask which will change in time the value of slideOffset which is in [0, 1].
Just like:
private Handler mUIHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_SLIDING_INDEX:
double slideOffSet= (double)msg.obj;
if (slideOffSet> 0.0 && slideOffSet<= 1.0) {
drawerListener.onDrawerSlide(drawer, slideOffSet);
Message message = mUIHandler.obtainMessage();
message.what = UPDATE_SLIDING_INDEX;
message.obj = slideOffSet- 0.1;
mUIHandler.sendMessageDelayed(message, 100);
} else {
//To do something here.
}
break;
default:
break;
}
}
};
Then you call like this:
Message message = mUIHandler.obtainMessage();
message.what = UPDATE_SLIDING_INDEX;
message.obj = 0.8;
mUIHandler.sendMessage(message);
when mDrawerLayout.setDrawerListener(....); is called before or after of the below if condition.
if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
mDrawerLayout.openDrawer(mFragmentContainerView);
}
If it is after, obviously the onDrawerSlide won't be called.
If it is before then you should debug.
Related
The DrawerLayout take noticeable time to close
here is my code:
#Override
public void onDrawerOpened(View drawerView) {
if (items.size() == 0)
view.setVisibility(View.GONE);
else view.setVisibility(View.VISIBLE);}
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
}
is there a solution for that?
Your problem is that the onDrawerOpened() method doesn't fire until the drawer is completely open. The perceived delay is due to the View being visible during the opening.
One solution would be to disable dragging the drawer, and only allow the toggle to open and close it. You could then do your size check before opening it programmatically. This, though, would require locking the drawer to the appropriate state in each of the onDrawerOpened() and onDrawerClosed() methods, and, of course, you'd lose that standard mode of interaction.
The preferred option is probably to do the check and visibility setting as soon as possible as the drawer is starting to open. We can do this in the onDrawerSlide() method instead, keeping a boolean flag to determine if the drawer is sliding after having been closed. For example:
actionBarDrawerToggle = new ActionBarDrawerToggle(...) {
private boolean opened;
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
if (slideOffset == 0) {
opened = false;
}
else {
if (!opened) {
opened = true;
if (items.size() == 0) {
view.setVisibility(View.GONE);
}
else {
view.setVisibility(View.VISIBLE);
}
}
}
}
...
}
have you include
actionBarDrawerToggle.syncState()
What does syncState() exactly do?
Well, ActionBarDrawerToggle.syncState() will synchronize the changed icon's state, which deponds on actions of DrawerLayout. If you ever tried to remove the syncState(), you will realize that the icon of arrow won't rotate any more.
I am displaying a FrameLayout with some components inside a Fragment. In onCreateView(..) I am animating the content of the FrameLayout and everything works fine. Now I want to animate the content before closing the Fragment.
In my current solution I am overriding onBackPressed() in the parent Activity and then I'm calling the method onBackPressed() inside my Fragment and animating the content there. The problem with this solution is, that I want to inflate the Fragment from various activities and then this is not really a nice solution... Does anybody know a better approach?
Thanks for your help!
Note:
I also tried to override onCreateView() and onPause() but the animation is not shown if I start it in those methods
and the following method does not fulfill my requirements either as it animates the whole fragment and I want to animate the content
getActivity().getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.slide_in_up, R.anim.slide_out_up, R.anim.slide_out_down, R.anim.slide_in_down)
Maybe you can try to handle onBackPressed in your fragment like below:
yourRootLayout.setFocusableInTouchMode(true);
yourRootLayout.requestFocus();
yourRootLayout.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
animateMyViews();
return true;
}
return false;
}
});
I wanted to perform sliding exit animation before dismissing the view/fragment.
These are the steps I performed:
I created a runnable task which can dismiss the current screen.
Passed that runnable to animating view.
Used view.postOnAnimationDelayed(runnable, 400) so that it can animate and execute the runnable after 400 milliseconds.
Also I made sure that my animation duration is >= 400 so that the transition is smooth.
Below is a little bit altered version of code for idea.
I used view.postOnAnimationDelayed(runnable, 400) to
Dialog dialog = new Dialog(getActivity(), getTheme()) {
#Override
public void onBackPressed() {
ParentFragment.this.onBackPressed();
Runnable runnable = new Runnable() {
#Override
public void run() {
//Referencing this class in runnable
getInstance().dismiss();
}
};
//webView is the child view loaded on this fragment
if(webView != null && webView.webViewClient != null) {
webView.webViewClient.animateClose(webView, runnable);
} else {
super.dismiss();
}
};
function animateOnClose in webViewClient looked like this:
public void animateClose(final WebView view, Runnable runnable) {
Animation anim = AnimationUtils.loadAnimation(getMainActivityContext(),
animationResource);
view.startAnimation(anim);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.postOnAnimationDelayed(runnable, 400);
// you can also try view.postOnAnimation(runnable);
} else {
runnable.run();
}
}
I think what you need is to notify the Fragment that you are about to destroy it.
A crude pseudocode might look like
myFragment.aboutToClose();
While in your Fragment's aboutToClose() method.
public void aboutToClose()
{
// Perform all the animations you want.
// Don't forget to add onAnimationEnd() call back.
onAnimationEnd()
{
// Notify Activity that Animations have completed.
callback.animationsCompleted();
}
}
Finally in your calling Activity.
public void animationsCompleted()
{
// Destroy fragment.
getActivity().getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.slide_in_up, R.anim.slide_out_up, R.anim.slide_out_down, R.anim.slide_in_down);
}
No, its not a re asked question
I've searched so well. but nowhere found how to do this. I want to change the hamburger icon to back icon by calling a method from my activity. I can do it with Drawer.. but I wanna do it without opening drawer..
for example, when a fragment is shown.. the hamburger will turn into back arrow(with animation)
then clicking the back arrow will hide fragment and turn the arrow back into hamburger.
I want the animation while doing this.. is there any way to do that? or its only possible while opening/closing drawer
Thanks in advance
I did it by Calling
onDrawerSlide(View v, float f);
where float value from 0.0f to 1.0f defines the progress of transforming from hamburger to back arrow.
Then I used object animator to call this method 100 times each time float value 0.1 increased
and the magic happened.
Thank you #gauravsarma for showing me the way.
Do the following
ActionBarDrawerToggle toolbarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
toolbar, R.string.drawer_open, R.string.drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu();
}
public void onDrawerOpened(View view) {
super.onDrawerOpened(view);
invalidateOptionsMenu();
}
};
drawerLayout.setDrawerListener(toolbarDrawerToggle);
toolbarDrawerToggle.syncState();
Is there any way to disable sliding animation of the NavigationDrawer's icon? I mean the effect, when you click the icon or open the Drawer with slide gesture. (I still use the ActionBar at the moment)
Preview
You need to override the onDrawerSlide method of ActionBarDrawerToggle and set the slideOffset to 0 if the drawer is right drawer. So this would disable the animation of the navigation drawer image.
#Override
public void onDrawerSlide(View drawerView, float slideOffset)
{
if(drawerView!=null && drawerView == rightDrawerListView){
super.onDrawerSlide(drawerView, 0);
}else{
super.onDrawerSlide(drawerView, slideOffset);
}
}
Look at this answer. Since support v7 version 25.3.0, you can disable the animation, you can disable the animation using one line of code.
yourActionBarDrawerToggle.setDrawerSlideAnimationEnabled(false);
I just make my first steps in android programming and i need a help!
I created a navigation drawer and it opened/closed with animation of humberher icon automatically. Then i decided to make damping effect to toolbar. My toolbar became dark. I used code below. After that i had that effect but animation of humburger icon disappeared. I don`t understand what happened. Can anyone help me to solve this problem. I want to return animation of humberger icon.
public void onDrawerSlide(View drawerView, float slideOffset) {
if(slideOffset<0.6){
toolbar.setAlpha(1 - slideOffset);
}
}
The animation you're describing is handled in ActionBarDrawerToggle's onDrawerSlide() method. You've overridden the method without calling through to the super's method, so the animation code isn't running. Simply add the super call to your method.
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
if(slideOffset<0.6) {
toolbar.setAlpha(1 - slideOffset);
}
}