transparente quitar para navegacion inferior equipos como barras barra animacion activar android material-design android-toolbar

android - quitar - Desactivar la animación de la hamburguesa hacia atrás en la barra de herramientas



barras de animacion para equipos (7)

Es muy fácil implementar la Toolbar con hamburguesa para la animación de la flecha hacia atrás. En mi opinión, esta animación no tiene sentido porque según el diseño del material, el cajón de navegación cubre la Toolbar cuando se abre. Mi pregunta es cómo deshabilitar correctamente esta animación y mostrar una hamburguesa o una flecha hacia atrás usando getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Así es como lo hice, pero parece un truco sucio:

mDrawerToggle.setDrawerIndicatorEnabled(false); if (showHomeAsUp) { mDrawerToggle.setHomeAsUpIndicator(R.drawable.lib_ic_arrow_back_light); mDrawerToggle.setToolbarNavigationClickListener(view -> finish()); } else { mDrawerToggle.setHomeAsUpIndicator(R.drawable.lib_ic_menu_light); mDrawerToggle.setToolbarNavigationClickListener(view -> toggleDrawer()); }

¿Alguna pista de cómo debería implementarse esto correctamente para usar solo setDisplayHomeAsUpEnabled para cambiar entre los iconos de hamburguesa y flecha atrás?


En mi opinión esta animación no tiene sentido.

Bueno, ActionBarDrawerToggle está destinado a ser animado.

De la documentación:

Puede personalizar el conmutador animado definiendo drawerArrowStyle en su tema ActionBar.

¿Alguna pista de cómo debería implementarse esto correctamente para usar solo setDisplayHomeAsUpEnabled para cambiar entre los iconos de hamburguesa y flecha atrás?

El ActionBarDrawerToggle es solo una forma elegante de llamar a ActionBar.setHomeAsUpIndicator . Entonces, de cualquier forma, tendrás que llamar a ActionBar.setDisplayHomeAsUpEnabled a true para poder mostrarlo.

Si está convencido de que tiene que usarlo, le sugiero que llame a ActionBarDrawerToggle.onDrawerOpened(View drawerView) y ActionBarDrawerToggle.onDrawerClosed(View drawerView) respectivamente.

Esto establecerá la posición del DrawerIndicator en 1 o 0 , cambiando entre la flecha y los estados de hamburguesa de DrawerArrowDrawable .

Y en su caso, no es necesario adjuntar un ActionBarDrawerToggle como DrawerLayout.DrawerListener . Como en:

mYourDrawer.setDrawerListener(mYourDrawerToggle);

Pero un enfoque mucho más avanzado sería llamar a ActionBar.setHomeAsUpIndicator una vez y aplicar su propio icono de hamburguesa, también podría hacerlo a través de un estilo. Luego, cuando desee mostrar la flecha hacia atrás, solo llame a ActionBar.setDisplayHomeAsUpEnabled y deje que AppCompat o el marco se encarguen del resto. Por los comentarios que has hecho, estoy bastante seguro de que esto es lo que estás buscando.

Si no estás seguro de qué icono utilizar, el tamaño predeterminado de DrawerArrowDrawable es 24dp , lo que significa que querrías obtener ic_menu_white_24dp o ic_menu_black_24dp del icono de navegación establecido en el paquete de iconos de diseño de materiales oficial de Google.

También puede copiar DrawerArrowDrawable en su proyecto y dejar que luego cambie la flecha o los estados de hamburguesa según lo necesite. Es autónomo, menos unos pocos recursos.


Ahora hay un método dedicado para deshabilitar la animación: toggle.setDrawerSlideAnimationEnabled(false)

Aquí hay un fragmento que uso:

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); [...] ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); toggle.setDrawerSlideAnimationEnabled(false); drawer.addDrawerListener(toggle); toggle.syncState(); }


Deshabilitar la llamada de la cena en el método onDrawerSlide() detendrá la animación entre Arrow y Burger. Solo verá el cambio (sin animación) cuando el cajón esté completamente abierto o completamente cerrado.

mActionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.open, R.string.closed) { @Override public void onDrawerSlide(View drawerView, float slideOffset) { //super.onDrawerSlide(drawerView, slideOffset); } }; mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);


Esta es mi función para controlar el ActionBarDrawableToggle ubicado en NavigationDrawerFragment, al que llamo en la devolución de llamada onActivityCreated de cada fragmento. Las funciones de correos son necesarias. El icono de la hamburguesa cambia a la flecha de retroceso y se puede hacer clic en la flecha de retroceso. Los manipuladores manejan adecuadamente los cambios de orientación.

... import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarDrawerToggle; ... public class NavigationDrawerFragment extends Fragment { private ActionBarDrawerToggle mDrawerToggle; ... public void syncDrawerState() { new Handler().post(new Runnable() { @Override public void run() { final ActionBar actionBar = activity.getSupportActionBar(); if (activity.getSupportFragmentManager().getBackStackEntryCount() > 1 && (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != ActionBar.DISPLAY_HOME_AS_UP) { new Handler().post(new Runnable() { @Override public void run() { mDrawerToggle.setDrawerIndicatorEnabled(false); actionBar.setDisplayHomeAsUpEnabled(true); mDrawerToggle.setToolbarNavigationClickListener(onToolbarNavigationClickListener()); } }); } else if (activity.getSupportFragmentManager().getBackStackEntryCount() <= 1 && (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) == ActionBar.DISPLAY_HOME_AS_UP) { actionBar.setHomeButtonEnabled(false); actionBar.setDisplayHomeAsUpEnabled(false); mDrawerToggle.setDrawerIndicatorEnabled(true); mDrawerToggle.syncState(); } } }); } }

Este es solo mi método onActivityCreated en mi fragmento base.

@Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); navigationDrawerFragment.syncDrawerState(); }


Esto deshabilitará la animación, al crear el drawerToggle, anulará onDrawerSlide ():

drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, getToolbar(), R.string.open, R.string.close) { @Override public void onDrawerClosed(View view) { super.onDrawerClosed(view); } @Override public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); } @Override public void onDrawerSlide(View drawerView, float slideOffset) { super.onDrawerSlide(drawerView, 0); // this disables the animation } };

Si desea eliminar la flecha completamente, puede agregar

super.onDrawerSlide(drawerView, 0); // this disables the arrow @ completed state

al final de la función onDrawerOpened.


Si no quieres la animación, no uses ActionBarDrawerToggle . Utilice el código de abajo en su lugar.

toolbar.setNavigationIcon(R.drawable.ic_menu); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { drawer.openDrawer(GravityCompat.START); } });


Tenía un requisito similar y pasé un tiempo ActionBarDrawerToggle código ActionBarDrawerToggle . Lo que tienes actualmente es el mejor camino a seguir.

Más por venir:

La animación de hamburguesa a flecha es proporcionada por una implementación DrawerArrowDrawableToggle - DrawerArrowDrawableToggle . Actualmente, no tenemos mucho control sobre cómo reacciona este dibujo a los estados del cajón. actionVarDrawerToggle dice el constructor de acceso al paquete para actionVarDrawerToggle :

/** * In the future, we can make this constructor public if we want to let developers customize * the * animation. */ <T extends Drawable & DrawerToggle> ActionBarDrawerToggle(Activity activity, Toolbar toolbar, DrawerLayout drawerLayout, T slider, @StringRes int openDrawerContentDescRes, @StringRes int closeDrawerContentDescRes)

Al proporcionar su propia implementación del slider , puede controlar cómo reacciona a los estados del cajón. La interfaz que el slider debe implementar:

/** * Interface for toggle drawables. Can be public in the future */ static interface DrawerToggle { public void setPosition(float position); public float getPosition(); }

setPosition(float) es lo más destacado aquí: todos los cambios de estado del cajón lo llaman para actualizar el indicador del cajón.

Para el comportamiento que desea, la implementación de su slider setPosition(float position) no haría nada.

Aún necesitarás:

if (showHomeAsUp) { mDrawerToggle.setDrawerIndicatorEnabled(false); // Can be set in theme mDrawerToggle.setHomeAsUpIndicator(R.drawable.lib_ic_arrow_back_light); mDrawerToggle.setToolbarNavigationClickListener(view -> finish()); }

Si no setDrawerIndicatorEnabled(false) , OnClickListener lo configuró con setToolbarNavigationClickListener(view -> finish()); no disparará

¿Qué podemos hacer ahora ?

En una inspección más cercana, encuentro que hay una disposición para su requerimiento en ActionBarDrawerToggle . Considero que esta disposición es aún más un hack que lo que tienes actualmente. Pero, te dejaré decidir.

ActionBarDrawerToggle permite tener cierto control sobre el indicador del cajón a través de la interfaz Delegate . Puede hacer que su actividad implemente esta interfaz de la siguiente manera:

public class TheActivity extends ActionBarActivity implements ActionBarDrawerToggle.Delegate { .... @Override public void setActionBarUpIndicator(Drawable drawableNotUsed, int i) { // First, we''re not using the passed drawable, the one that animates // Second, we check if `displayHomeAsUp` is enabled final boolean displayHomeAsUpEnabled = (getSupportActionBar().getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) == ActionBar.DISPLAY_HOME_AS_UP; // We''ll control what happens on navigation-icon click mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (displayHomeAsUpEnabled) { finish(); } else { // `ActionBarDrawerToggle#toggle()` is private. // Extend `ActionBarDrawerToggle` and make provision // for toggling. mDrawerToggle.toggleDrawer(); } } }); // I will talk about `mToolbarnavigationIcon` later on. if (displayHomeAsUpEnabled) { mToolbarNavigationIcon.setIndicator( CustomDrawerArrowDrawable.HOME_AS_UP_INDICATOR); } else { mToolbarNavigationIcon.setIndicator( CustomDrawerArrowDrawable.DRAWER_INDICATOR); } mToolbar.setNavigationIcon(mToolbarNavigationIcon); mToolbar.setNavigationContentDescription(i); } @Override public void setActionBarDescription(int i) { mToolbar.setNavigationContentDescription(i); } @Override public Drawable getThemeUpIndicator() { final TypedArray a = mToolbar.getContext() .obtainStyledAttributes(new int[]{android.R.attr.homeAsUpIndicator}); final Drawable result = a.getDrawable(0); a.recycle(); return result; } @Override public Context getActionBarThemedContext() { return mToolbar.getContext(); } .... }

ActionBarDrawerToggle usará setActionBarUpIndicator(Drawable, int) proporcionado aquí. Ya que ignoramos que se puede pasar el Drawable , tenemos control total sobre lo que se mostrará.

Captura: ActionBarDrawerToggle permitirá que nuestra Activity actúe como un delegado si pasamos el parámetro Toolbar como nulo aquí:

public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar, @StringRes int openDrawerContentDescRes, @StringRes int closeDrawerContentDescRes) { .... }

Y, tendrá que anular getV7DrawerToggleDelegate() en su actividad:

@Nullable @Override public ActionBarDrawerToggle.Delegate getV7DrawerToggleDelegate() { return this; }

Como puede ver, ir por el camino correcto es mucho trabajo adicional. Y no hemos terminado todavía.

La animación DrawerArrowDrawableToggle puede DrawerArrowDrawableToggle usando estos atributos . Si desea sus estados dibujables (homeAsUp y hamburguesa) exactamente como los valores predeterminados, deberá implementarlo como tal:

/** * A drawable that can draw a "Drawer hamburger" menu or an Arrow */ public class CustomDrawerArrowDrawable extends Drawable { public static final float DRAWER_INDICATOR = 0f; public static final float HOME_AS_UP_INDICATOR = 1f; private final Activity mActivity; private final Paint mPaint = new Paint(); // The angle in degress that the arrow head is inclined at. private static final float ARROW_HEAD_ANGLE = (float) Math.toRadians(45); private final float mBarThickness; // The length of top and bottom bars when they merge into an arrow private final float mTopBottomArrowSize; // The length of middle bar private final float mBarSize; // The length of the middle bar when arrow is shaped private final float mMiddleArrowSize; // The space between bars when they are parallel private final float mBarGap; // Use Path instead of canvas operations so that if color has transparency, overlapping sections // wont look different private final Path mPath = new Path(); // The reported intrinsic size of the drawable. private final int mSize; private float mIndicator; /** * @param context used to get the configuration for the drawable from */ public CustomDrawerArrowDrawable(Activity activity, Context context) { final TypedArray typedArray = context.getTheme() .obtainStyledAttributes(null, R.styleable.DrawerArrowToggle, R.attr.drawerArrowStyle, R.style.Base_Widget_AppCompat_DrawerArrowToggle); mPaint.setAntiAlias(true); mPaint.setColor(typedArray.getColor(R.styleable.DrawerArrowToggle_color, 0)); mSize = typedArray.getDimensionPixelSize(R.styleable.DrawerArrowToggle_drawableSize, 0); mBarSize = typedArray.getDimension(R.styleable.DrawerArrowToggle_barSize, 0); mTopBottomArrowSize = typedArray .getDimension(R.styleable.DrawerArrowToggle_topBottomBarArrowSize, 0); mBarThickness = typedArray.getDimension(R.styleable.DrawerArrowToggle_thickness, 0); mBarGap = typedArray.getDimension(R.styleable.DrawerArrowToggle_gapBetweenBars, 0); mMiddleArrowSize = typedArray .getDimension(R.styleable.DrawerArrowToggle_middleBarArrowSize, 0); typedArray.recycle(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.SQUARE); mPaint.setStrokeWidth(mBarThickness); mActivity = activity; } public boolean isLayoutRtl() { return ViewCompat.getLayoutDirection(mActivity.getWindow().getDecorView()) == ViewCompat.LAYOUT_DIRECTION_RTL; } @Override public void draw(Canvas canvas) { Rect bounds = getBounds(); final boolean isRtl = isLayoutRtl(); // Interpolated widths of arrow bars final float arrowSize = lerp(mBarSize, mTopBottomArrowSize, mIndicator); final float middleBarSize = lerp(mBarSize, mMiddleArrowSize, mIndicator); // Interpolated size of middle bar final float middleBarCut = lerp(0, mBarThickness / 2, mIndicator); // The rotation of the top and bottom bars (that make the arrow head) final float rotation = lerp(0, ARROW_HEAD_ANGLE, mIndicator); final float topBottomBarOffset = lerp(mBarGap + mBarThickness, 0, mIndicator); mPath.rewind(); final float arrowEdge = -middleBarSize / 2; // draw middle bar mPath.moveTo(arrowEdge + middleBarCut, 0); mPath.rLineTo(middleBarSize - middleBarCut, 0); final float arrowWidth = Math.round(arrowSize * Math.cos(rotation)); final float arrowHeight = Math.round(arrowSize * Math.sin(rotation)); // top bar mPath.moveTo(arrowEdge, topBottomBarOffset); mPath.rLineTo(arrowWidth, arrowHeight); // bottom bar mPath.moveTo(arrowEdge, -topBottomBarOffset); mPath.rLineTo(arrowWidth, -arrowHeight); mPath.moveTo(0, 0); mPath.close(); canvas.save(); if (isRtl) { canvas.rotate(180, bounds.centerX(), bounds.centerY()); } canvas.translate(bounds.centerX(), bounds.centerY()); canvas.drawPath(mPath, mPaint); canvas.restore(); } @Override public void setAlpha(int i) { mPaint.setAlpha(i); } // override public boolean isAutoMirrored() { // Draws rotated 180 degrees in RTL mode. return true; } @Override public void setColorFilter(ColorFilter colorFilter) { mPaint.setColorFilter(colorFilter); } @Override public int getIntrinsicHeight() { return mSize; } @Override public int getIntrinsicWidth() { return mSize; } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } public void setIndicator(float indicator) { mIndicator = indicator; invalidateSelf(); } /** * Linear interpolate between a and b with parameter t. */ private static float lerp(float a, float b, float indicator) { if (indicator == HOME_AS_UP_INDICATOR) { return b; } else { return a; } } }

CustomDrawerArrowDrawable''s implementación CustomDrawerArrowDrawable''s se ha tomado de AOSP y se ha CustomDrawerArrowDrawable''s para permitir el dibujo de solo dos estados: homeAsUp y hamburger. Puede alternar entre estos estados llamando a setIndicator(float) . Usamos esto en el Delegate que implementamos. Además, el uso de CustomDrawerArrowDrawable le permitirá CustomDrawerArrowDrawable en xml: barSize , color , etc. Aunque no lo necesite, la implementación anterior le permite proporcionar animaciones personalizadas para abrir y cerrar cajones .

Sinceramente, no sé si debería recomendar esto.

Si llama a ActionBarDrawerToggle#setHomeAsUpIndicator(...) con un argumento null , debería elegir el dibujable definido en su tema:

<item name="android:homeAsUpIndicator">@drawable/some_back_drawable</item>

Actualmente, esto no sucede debido a un posible error en ToolbarCompatDelegate#getThemeUpIndicator() :

@Override public Drawable getThemeUpIndicator() { final TypedArray a = mToolbar.getContext() // Should be new int[]{android.R.attr.homeAsUpIndicator} .obtainStyledAttributes(new int[]{android.R.id.home}); final Drawable result = a.getDrawable(0); a.recycle(); return result; }

Informe de error que discute de manera holgada (lea el Caso 4): Link

Si decide seguir con la solución que ya tiene, considere usar CustomDrawerArrowDrawable en lugar de pngs (R.drawable.lib_ic_arrow_back_light & R.drawable.lib_ic_menu_light). No necesitarás múltiples elementos dibujables para los cubos de densidad / tamaño y el estilo se realizará en xml. Además, el producto final será el mismo que el del marco.

mDrawerToggle.setDrawerIndicatorEnabled(false); CustomDrawerArrowDrawable toolbarNavigationIcon = new CustomDrawerArrowDrawable(this, mToolbar.getContext()); if (showHomeAsUp) { toolbarNavigationIcon.setIndicator( CustomDrawerArrowDrawable.HOME_AS_UP_INDICATOR); mDrawerToggle.setToolbarNavigationClickListener(view -> finish()); } else { mToolbarNavigationIcon.setIndicator( CustomDrawerArrowDrawable.DRAWER_INDICATOR); mDrawerToggle.setToolbarNavigationClickListener(view -> toggleDrawer()); } mDrawerToggle.setHomeAsUpIndicator(toolbarNavigationIcon);