content: package com.alirezaafkar.toolbar;
  
  import android.app.ActionBar;
  import android.app.Activity;
  import android.content.Context;
  import android.content.res.Configuration;
  import android.content.res.TypedArray;
  import android.graphics.drawable.Drawable;
  import android.os.Build;
  import android.support.annotation.Nullable;
  import android.support.annotation.StringRes;
  import android.support.v4.view.GravityCompat;
  import android.support.v4.widget.DrawerLayout;
  import android.support.v7.graphics.drawable.DrawerArrowDrawable;
  import android.util.Log;
  import android.view.MenuItem;
  import android.view.View;
  
  /**
   * This class provides a handy way to tie together the functionality of
   * {@link android.support.v4.widget.DrawerLayout} and the framework <code>ActionBar</code> to
   * implement the recommended design for navigation drawers.
   * <p/>
   * <p>To use <code>RtlActionBarDrawerToggle</code>, create one in your Activity and call through
   * to the following methods corresponding to your Activity callbacks:</p>
   * <p/>
   * <ul>
   * <li>{@link android.app.Activity#onConfigurationChanged(android.content.res.Configuration)
   * onConfigurationChanged}
   * <li>{@link android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
   * onOptionsItemSelected}</li>
   * </ul>
   * <p/>
   * <p>Call {@link #syncState()} from your <code>Activity</code>'s
   * {@link android.app.Activity#onPostCreate(android.os.Bundle) onPostCreate} to synchronize the
   * indicator with the state of the linked DrawerLayout after <code>onRestoreInstanceState</code>
   * has occurred.</p>
   * <p/>
   * <p><code>RtlActionBarDrawerToggle</code> can be used directly as a
   * {@link android.support.v4.widget.DrawerLayout.DrawerListener}, or if you are already providing
   * your own listener, call through to each of the listener methods from your own.</p>
   * <p/>
   * <p/>
   * You can customize the the animated toggle by defining the
   * {@link android.support.v7.appcompat.R.styleable#DrawerArrowToggle drawerArrowStyle} in your
   * ActionBar theme.
   */
  public class RtlActionBarDrawerToggle implements DrawerLayout.DrawerListener {
  
      /**
       * Allows an implementing Activity to return an {@link RtlActionBarDrawerToggle.Delegate} to use
       * with RtlActionBarDrawerToggle.
       */
      public interface DelegateProvider {
  
          /**
           * @return Delegate to use for ActionBarDrawableToggles, or null if the Activity
           * does not wish to override the default behavior.
           */
          @Nullable
          Delegate getDrawerToggleDelegate();
      }
  
      public interface Delegate {
  
          /**
           * Set the Action Bar's up indicator drawable and content description.
           *
           * @param upDrawable     - Drawable to set as up indicator
           * @param contentDescRes - Content description to set
           */
          void setActionBarUpIndicator(Drawable upDrawable, @StringRes int contentDescRes);
  
          /**
           * Set the Action Bar's up indicator content description.
           *
           * @param contentDescRes - Content description to set
           */
          void setActionBarDescription(@StringRes int contentDescRes);
  
          /**
           * Returns the drawable to be set as up button when DrawerToggle is disabled
           */
          Drawable getThemeUpIndicator();
  
          /**
           * Returns the context of ActionBar
           */
          Context getActionBarThemedContext();
  
          /**
           * Returns whether navigation icon is visible or not.
           * Used to print warning messages in case developer forgets to set displayHomeAsUp to true
           */
          boolean isNavigationVisible();
      }
  
      private final Delegate mActivityImpl;
      private final DrawerLayout mDrawerLayout;
  
      private DrawerToggle mSlider;
      private Drawable mHomeAsUpIndicator;
      private boolean mDrawerIndicatorEnabled = true;
      private boolean mHasCustomUpIndicator;
      private final int mOpenDrawerContentDescRes;
      private final int mCloseDrawerContentDescRes;
      // used in toolbar mode when DrawerToggle is disabled
      private View.OnClickListener mToolbarNavigationClickListener;
      // If developer does not set displayHomeAsUp, DrawerToggle won't show up.
      // DrawerToggle logs a warning if this case is detected
      private boolean mWarnedForDisplayHomeAsUp = false;
  
      /**
       * Construct a new RtlActionBarDrawerToggle.
       * <p/>
       * <p>The given {@link Activity} will be linked to the specified {@link DrawerLayout} and
       * its Actionbar's Up button will be set to a custom drawable.
       * <p>This drawable shows a Hamburger icon when drawer is closed and an arrow when drawer
       * is open. It animates between these two states as the drawer opens.</p>
       * <p/>
       * <p>String resources must be provided to describe the open/close drawer actions for
       * accessibility services.</p>
       *
       * @param activity                  The Activity hosting the drawer. Should have an ActionBar.
       * @param drawerLayout              The DrawerLayout to link to the given Activity's ActionBar
       * @param openDrawerContentDescRes  A String resource to describe the "open drawer" action
       *                                  for accessibility
       * @param closeDrawerContentDescRes A String resource to describe the "close drawer" action
       *                                  for accessibility
       */
      public RtlActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout,
                                      @StringRes int openDrawerContentDescRes,
                                      @StringRes int closeDrawerContentDescRes) {
          this(activity, null, drawerLayout, null, openDrawerContentDescRes,
                  closeDrawerContentDescRes);
      }
  
      /**
       * Construct a new RtlActionBarDrawerToggle with a Toolbar.
       * <p/>
       * The given {@link Activity} will be linked to the specified {@link DrawerLayout} and
       * the Toolbar's navigation icon will be set to a custom drawable. Using this constructor
       * will set Toolbar's navigation click listener to toggle the drawer when it is clicked.
       * <p/>
       * This drawable shows a Hamburger icon when drawer is closed and an arrow when drawer
       * is open. It animates between these two states as the drawer opens.
       * <p/>
       * String resources must be provided to describe the open/close drawer actions for
       * accessibility services.
       * <p/>
       * Please use {@link #RtlActionBarDrawerToggle(Activity, DrawerLayout, int, int)} if you are
       * setting the Toolbar as the ActionBar of your activity.
       *
       * @param activity                  The Activity hosting the drawer.
       * @param toolbar                   The toolbar to use if you have an independent Toolbar.
       * @param drawerLayout              The DrawerLayout to link to the given Activity's ActionBar
       * @param openDrawerContentDescRes  A String resource to describe the "open drawer" action
       *                                  for accessibility
       * @param closeDrawerContentDescRes A String resource to describe the "close drawer" action
       *                                  for accessibility
       */
      public RtlActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout,
                                      RtlToolbar toolbar, @StringRes int openDrawerContentDescRes,
                                      @StringRes int closeDrawerContentDescRes) {
          this(activity, toolbar, drawerLayout, null, openDrawerContentDescRes,
                  closeDrawerContentDescRes);
      }
  
      /**
       * In the future, we can make this constructor public if we want to let developers customize
       * the
       * animation.
       */
      <T extends Drawable & DrawerToggle> RtlActionBarDrawerToggle(Activity activity, RtlToolbar toolbar,
                                                                   DrawerLayout drawerLayout, T slider,
                                                                   @StringRes int openDrawerContentDescRes,
                                                                   @StringRes int closeDrawerContentDescRes) {
          if (toolbar != null) {
              mActivityImpl = new ToolbarCompatDelegate(toolbar);
              toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      if (mDrawerIndicatorEnabled) {
                          toggle();
                      } else if (mToolbarNavigationClickListener != null) {
                          mToolbarNavigationClickListener.onClick(v);
                      }
                  }
              });
          } else if (activity instanceof DelegateProvider) { // Allow the Activity to provide an impl
              mActivityImpl = ((DelegateProvider) activity).getDrawerToggleDelegate();
          } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
              mActivityImpl = new JellybeanMr2Delegate(activity);
          } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
              mActivityImpl = new HoneycombDelegate(activity);
          } else {
              mActivityImpl = new DummyDelegate(activity);
          }
  
          mDrawerLayout = drawerLayout;
          mOpenDrawerContentDescRes = openDrawerContentDescRes;
          mCloseDrawerContentDescRes = closeDrawerContentDescRes;
          if (slider == null) {
              Context themedContext = mActivityImpl.getActionBarThemedContext();
              mSlider = new DrawerArrowDrawableToggle(activity, themedContext,toolbar.getDirection());
          } else {
              mSlider = slider;
          }
  
          mHomeAsUpIndicator = getThemeUpIndicator();
      }
  
      /**
       * Synchronize the state of the drawer indicator/affordance with the linked DrawerLayout.
       * <p/>
       * <p>This should be called from your <code>Activity</code>'s
       * {@link Activity#onPostCreate(android.os.Bundle) onPostCreate} method to synchronize after
       * the DrawerLayout's instance state has been restored, and any other time when the state
       * may have diverged in such a way that the RtlActionBarDrawerToggle was not notified.
       * (For example, if you stop forwarding appropriate drawer events for a period of time.)</p>
       */
      public void syncState() {
          if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
              mSlider.setPosition(1);
          } else {
              mSlider.setPosition(0);
          }
          if (mDrawerIndicatorEnabled) {
              setActionBarUpIndicator((Drawable) mSlider,
                      mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
                              mCloseDrawerContentDescRes : mOpenDrawerContentDescRes);
          }
      }
  
      /**
       * This method should always be called by your <code>Activity</code>'s
       * {@link Activity#onConfigurationChanged(android.content.res.Configuration)
       * onConfigurationChanged}
       * method.
       *
       * @param newConfig The new configuration
       */
      public void onConfigurationChanged(Configuration newConfig) {
          // Reload drawables that can change with configuration
          if (!mHasCustomUpIndicator) {
              mHomeAsUpIndicator = getThemeUpIndicator();
          }
          syncState();
      }
  
      /**
       * This method should be called by your <code>Activity</code>'s
       * {@link Activity#onOptionsItemSelected(android.view.MenuItem) onOptionsItemSelected} method.
       * If it returns true, your <code>onOptionsItemSelected</code> method should return true and
       * skip further processing.
       *
       * @param item the MenuItem instance representing the selected menu item
       * @return true if the event was handled and further processing should not occur
       */
      public boolean onOptionsItemSelected(MenuItem item) {
          if (item != null && item.getItemId() == android.R.id.home && mDrawerIndicatorEnabled) {
              toggle();
              return true;
          }
          return false;
      }
  
      private void toggle() {
          int drawerLockMode = mDrawerLayout.getDrawerLockMode(GravityCompat.START);
          if (mDrawerLayout.isDrawerVisible(GravityCompat.START)
                  && (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_OPEN)) {
              mDrawerLayout.closeDrawer(GravityCompat.START);
          } else if (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
              mDrawerLayout.openDrawer(GravityCompat.START);
          }
      }
  
      /**
       * Set the up indicator to display when the drawer indicator is not
       * enabled.
       * <p/>
       * If you pass <code>null</code> to this method, the default drawable from
       * the theme will be used.
       *
       * @param indicator A drawable to use for the up indicator, or null to use
       *                  the theme's default
       * @see #setDrawerIndicatorEnabled(boolean)
       */
      public void setHomeAsUpIndicator(Drawable indicator) {
          if (indicator == null) {
              mHomeAsUpIndicator = getThemeUpIndicator();
              mHasCustomUpIndicator = false;
          } else {
              mHomeAsUpIndicator = indicator;
              mHasCustomUpIndicator = true;
          }
  
          if (!mDrawerIndicatorEnabled) {
              setActionBarUpIndicator(mHomeAsUpIndicator, 0);
          }
      }
  
      /**
       * Set the up indicator to display when the drawer indicator is not
       * enabled.
       * <p/>
       * If you pass 0 to this method, the default drawable from the theme will
       * be used.
       *
       * @param resId Resource ID of a drawable to use for the up indicator, or 0
       *              to use the theme's default
       * @see #setDrawerIndicatorEnabled(boolean)
       */
      public void setHomeAsUpIndicator(int resId) {
          Drawable indicator = null;
          if (resId != 0) {
              indicator = mDrawerLayout.getResources().getDrawable(resId);
          }
          setHomeAsUpIndicator(indicator);
      }
  
      /**
       * @return true if the enhanced drawer indicator is enabled, false otherwise
       * @see #setDrawerIndicatorEnabled(boolean)
       */
      public boolean isDrawerIndicatorEnabled() {
          return mDrawerIndicatorEnabled;
      }
  
      /**
       * Enable or disable the drawer indicator. The indicator defaults to enabled.
       * <p/>
       * <p>When the indicator is disabled, the <code>ActionBar</code> will revert to displaying
       * the home-as-up indicator provided by the <code>Activity</code>'s theme in the
       * <code>android.R.attr.homeAsUpIndicator</code> attribute instead of the animated
       * drawer glyph.</p>
       *
       * @param enable true to enable, false to disable
       */
      public void setDrawerIndicatorEnabled(boolean enable) {
          if (enable != mDrawerIndicatorEnabled) {
              if (enable) {
                  setActionBarUpIndicator((Drawable) mSlider,
                          mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
                                  mCloseDrawerContentDescRes : mOpenDrawerContentDescRes);
              } else {
                  setActionBarUpIndicator(mHomeAsUpIndicator, 0);
              }
              mDrawerIndicatorEnabled = enable;
          }
      }
  
  
      /**
       * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
       * RtlActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
       * through to this method from your own listener object.
       *
       * @param drawerView  The child view that was moved
       * @param slideOffset The new offset of this drawer within its range, from 0-1
       */
      @Override
      public void onDrawerSlide(View drawerView, float slideOffset) {
          mSlider.setPosition(Math.min(1f, Math.max(0, slideOffset)));
      }
  
      /**
       * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
       * RtlActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
       * through to this method from your own listener object.
       *
       * @param drawerView Drawer view that is now open
       */
      @Override
      public void onDrawerOpened(View drawerView) {
          mSlider.setPosition(1);
          if (mDrawerIndicatorEnabled) {
              setActionBarDescription(mCloseDrawerContentDescRes);
          }
      }
  
      /**
       * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
       * RtlActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
       * through to this method from your own listener object.
       *
       * @param drawerView Drawer view that is now closed
       */
      @Override
      public void onDrawerClosed(View drawerView) {
          mSlider.setPosition(0);
          if (mDrawerIndicatorEnabled) {
              setActionBarDescription(mOpenDrawerContentDescRes);
          }
      }
  
      /**
       * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
       * RtlActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
       * through to this method from your own listener object.
       *
       * @param newState The new drawer motion state
       */
      @Override
      public void onDrawerStateChanged(int newState) {
      }
  
      /**
       * Returns the fallback listener for Navigation icon click events.
       *
       * @return The click listener which receives Navigation click events from Toolbar when
       * drawer indicator is disabled.
       * @see #setToolbarNavigationClickListener(android.view.View.OnClickListener)
       * @see #setDrawerIndicatorEnabled(boolean)
       * @see #isDrawerIndicatorEnabled()
       */
      public View.OnClickListener getToolbarNavigationClickListener() {
          return mToolbarNavigationClickListener;
      }
  
      /**
       * When DrawerToggle is constructed with a Toolbar, it sets the click listener on
       * the Navigation icon. If you want to listen for clicks on the Navigation icon when
       * DrawerToggle is disabled ({@link #setDrawerIndicatorEnabled(boolean)}, you should call this
       * method with your listener and DrawerToggle will forward click events to that listener
       * when drawer indicator is disabled.
       *
       * @see #setDrawerIndicatorEnabled(boolean)
       */
      public void setToolbarNavigationClickListener(
              View.OnClickListener onToolbarNavigationClickListener) {
          mToolbarNavigationClickListener = onToolbarNavigationClickListener;
      }
  
      void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes) {
          if (!mWarnedForDisplayHomeAsUp && !mActivityImpl.isNavigationVisible()) {
              Log.w("RtlActionBarDrawerToggle", "DrawerToggle may not show up because NavigationIcon"
                      + " is not visible. You may need to call "
                      + "actionbar.setDisplayHomeAsUpEnabled(true);");
              mWarnedForDisplayHomeAsUp = true;
          }
          mActivityImpl.setActionBarUpIndicator(upDrawable, contentDescRes);
      }
  
      void setActionBarDescription(int contentDescRes) {
          mActivityImpl.setActionBarDescription(contentDescRes);
      }
  
      Drawable getThemeUpIndicator() {
          return mActivityImpl.getThemeUpIndicator();
      }
  
      static class DrawerArrowDrawableToggle extends DrawerArrowDrawable implements DrawerToggle {
          private final Activity mActivity;
  
          public DrawerArrowDrawableToggle(Activity activity, Context themedContext, int direction) {
              super(themedContext);
              mActivity = activity;
              setArrowDirection(direction);
          }
  
          private void setArrowDirection(int direction) {
              switch (direction) {
                  case RtlToolbar.LTR:
                      setDirection(ARROW_DIRECTION_LEFT);
                      break;
                  case RtlToolbar.RTL:
                      setDirection(ARROW_DIRECTION_RIGHT);
                      break;
              }
          }
  
          public void setPosition(float position) {
              if (position == 1f) {
                  setVerticalMirror(true);
              } else if (position == 0f) {
                  setVerticalMirror(false);
              }
              setProgress(position);
          }
  
          public float getPosition() {
              return getProgress();
          }
      }
  
      /**
       * Interface for toggle drawables. Can be public in the future
       */
      static interface DrawerToggle {
  
          public void setPosition(float position);
  
          public float getPosition();
      }
  
      /**
       * Delegate if SDK version is between honeycomb and JBMR2
       */
      private static class HoneycombDelegate implements Delegate {
  
          final Activity mActivity;
          ActionBarDrawerToggleHoneycomb.SetIndicatorInfo mSetIndicatorInfo;
  
          private HoneycombDelegate(Activity activity) {
              mActivity = activity;
          }
  
          @Override
          public Drawable getThemeUpIndicator() {
              return ActionBarDrawerToggleHoneycomb.getThemeUpIndicator(mActivity);
          }
  
          @Override
          public Context getActionBarThemedContext() {
              final ActionBar actionBar = mActivity.getActionBar();
              final Context context;
              if (actionBar != null) {
                  context = actionBar.getThemedContext();
              } else {
                  context = mActivity;
              }
              return context;
          }
  
          @Override
          public boolean isNavigationVisible() {
              final ActionBar actionBar = mActivity.getActionBar();
              return actionBar != null
                      && (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0;
          }
  
          @Override
          public void setActionBarUpIndicator(Drawable themeImage, int contentDescRes) {
              mActivity.getActionBar().setDisplayShowHomeEnabled(true);
              mSetIndicatorInfo = ActionBarDrawerToggleHoneycomb.setActionBarUpIndicator(
                      mSetIndicatorInfo, mActivity, themeImage, contentDescRes);
              mActivity.getActionBar().setDisplayShowHomeEnabled(false);
          }
  
          @Override
          public void setActionBarDescription(int contentDescRes) {
              mSetIndicatorInfo = ActionBarDrawerToggleHoneycomb.setActionBarDescription(
                      mSetIndicatorInfo, mActivity, contentDescRes);
          }
      }
  
      /**
       * Delegate if SDK version is JB MR2 or newer
       */
      private static class JellybeanMr2Delegate implements Delegate {
  
          final Activity mActivity;
  
          private JellybeanMr2Delegate(Activity activity) {
              mActivity = activity;
          }
  
          @Override
          public Drawable getThemeUpIndicator() {
              final TypedArray a = getActionBarThemedContext().obtainStyledAttributes(null,
                      new int[]{android.R.attr.homeAsUpIndicator}, android.R.attr.actionBarStyle, 0);
              final Drawable result = a.getDrawable(0);
              a.recycle();
              return result;
          }
  
          @Override
          public Context getActionBarThemedContext() {
              final ActionBar actionBar = mActivity.getActionBar();
              final Context context;
              if (actionBar != null) {
                  context = actionBar.getThemedContext();
              } else {
                  context = mActivity;
              }
              return context;
          }
  
          @Override
          public boolean isNavigationVisible() {
              final ActionBar actionBar = mActivity.getActionBar();
              return actionBar != null &&
                      (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0;
          }
  
          @Override
          public void setActionBarUpIndicator(Drawable drawable, int contentDescRes) {
              final ActionBar actionBar = mActivity.getActionBar();
              if (actionBar != null) {
                  actionBar.setHomeAsUpIndicator(drawable);
                  actionBar.setHomeActionContentDescription(contentDescRes);
              }
          }
  
          @Override
          public void setActionBarDescription(int contentDescRes) {
              final ActionBar actionBar = mActivity.getActionBar();
              if (actionBar != null) {
                  actionBar.setHomeActionContentDescription(contentDescRes);
              }
          }
      }
  
      /**
       * Used when DrawerToggle is initialized with a Toolbar
       */
      static class ToolbarCompatDelegate implements Delegate {
  
          final RtlToolbar mToolbar;
          final Drawable mDefaultUpIndicator;
          final CharSequence mDefaultContentDescription;
  
          ToolbarCompatDelegate(RtlToolbar toolbar) {
              mToolbar = toolbar;
              mDefaultUpIndicator = toolbar.getNavigationIcon();
              mDefaultContentDescription = toolbar.getNavigationContentDescription();
          }
  
          @Override
          public void setActionBarUpIndicator(Drawable upDrawable, @StringRes int contentDescRes) {
              mToolbar.setNavigationIcon(upDrawable);
              setActionBarDescription(contentDescRes);
          }
  
          @Override
          public void setActionBarDescription(@StringRes int contentDescRes) {
              if (contentDescRes == 0) {
                  mToolbar.setNavigationContentDescription(mDefaultContentDescription);
              } else {
                  mToolbar.setNavigationContentDescription(contentDescRes);
              }
          }
  
          @Override
          public Drawable getThemeUpIndicator() {
              return mDefaultUpIndicator;
          }
  
          @Override
          public Context getActionBarThemedContext() {
              return mToolbar.getContext();
          }
  
          @Override
          public boolean isNavigationVisible() {
              return true;
          }
      }
  
      /**
       * Fallback delegate
       */
      static class DummyDelegate implements Delegate {
          final Activity mActivity;
  
          DummyDelegate(Activity activity) {
              mActivity = activity;
          }
  
          @Override
          public void setActionBarUpIndicator(Drawable upDrawable, @StringRes int contentDescRes) {
  
          }
  
          @Override
          public void setActionBarDescription(@StringRes int contentDescRes) {
  
          }
  
          @Override
          public Drawable getThemeUpIndicator() {
              return null;
          }
  
          @Override
          public Context getActionBarThemedContext() {
              return mActivity;
          }
  
          @Override
          public boolean isNavigationVisible() {
              return true;
          }
      }
  }