TL;DR: estoy buscando un completa de trabajo de la muestra de lo que voy a referir como «el Gmail de tres fragmento de animación del escenario. Específicamente, queremos empezar con dos fragmentos, como este:

Ejemplo de Trabajo completo de la de Gmail Tres Fragmento de Animación Escenario?

Sobre algunos eventos de IU (por ejemplo, tocar algo en el Fragmento B), queremos:

  • Fragmento de Una deslizar la pantalla hacia la izquierda
  • Fragmento B a deslizarse hacia el borde izquierdo de la pantalla y reducir a tomar el lugar dejado libre por Fragmento de Un
  • El fragmento C deslice desde el lado derecho de la pantalla y para ocupar el lugar vacante por el Fragmento B

Y, en un botón de prensa, queremos que el conjunto de operaciones a revertirse.

Ahora que la he visto un montón de implementaciones parciales; voy a revisar cuatro de ellos a continuación. Más allá de ser incompleta, todos ellos tienen sus problemas.


@Reto Meier contribuido esta respuesta popular a la misma pregunta básica, lo que indica que podría utilizar setCustomAnimations() con un FragmentTransaction. Para un dos-fragmento (por ejemplo, sólo se ve Un Fragmento de inicialmente, y quiero reemplazarlo con un nuevo Fragmento B con efectos animados), estoy en completo acuerdo. Sin embargo:

  • Dado que sólo se puede especificar un «dentro» y un «fuera» de la animación, no veo cómo se podría manejar todas las diferentes animaciones necesario para los tres-fragmento escenario
  • La <objectAnimator> en su código de ejemplo utiliza cableado de las posiciones de los píxeles, y que parece ser poco práctico dado diferentes tamaños de pantalla, sin embargo, setCustomAnimations() requiere de animación de los recursos, lo que impide la posibilidad de definir estas cosas en Java
  • Estoy en una pérdida en cuanto a cómo el objeto de animadores para la escala empate con cosas como android:layout_weight en un LinearLayout para la asignación de espacio en base a un porcentaje
  • Estoy en una pérdida en cuanto a cómo el Fragmento C se maneja en el principio (GONE? android:layout_weight de 0? pre-animado a una escala de 0? algo más?)

@Roman Nurik señala que usted puede animar a cualquier propiedad, incluso aquellas de las que define a sí mismo. Que puede ayudar a resolver el problema de los cableados de posiciones, en el costo de inventar su propio diseño personalizado del administrador de la subclase. Que ayuda a algunos, pero todavía estoy desconcertado por el resto de Reto de la solución.


El autor de este pastebin entrada muestra algunos tentadora pseudocódigo, básicamente diciendo que todos los tres fragmentos que residen en el contenedor inicialmente, con el Fragmento C ocultas en un principio a través de un hide() operación de transacción. Luego nos show() C y hide() Un cuando la interfaz de usuario se produce el evento. Sin embargo, no veo la manera de que se encarga el hecho de que B cambia de tamaño. También se basa en el hecho de que, aparentemente, puede agregar varios fragmentos para el mismo contenedor, y no estoy seguro de si eso es o no confiable de comportamiento en el largo plazo (por no hablar de que debe romper findFragmentById(), a pesar de que puedo vivir con eso).


El autor de este blog indica que Gmail no es el uso de setCustomAnimations() en todos, pero en su lugar utiliza directamente objeto de animadores («usted acaba de cambiar el margen izquierdo de la raíz vista + cambiar el ancho de la vista derecha»). Sin embargo, esto todavía es un dos-fragmento de solución AFAICT, y la implementación que se muestra una vez más dura de los alambres dimensiones en píxeles.


Voy a seguir perseverando en este, así que pueden acabar respondiendo a este mismo algún día, pero estoy realmente esperando que alguien ha salido de los tres fragmento de solución para esta animación escenario y puede publicar el código (o un enlace al mismo). Animaciones en Android me dan ganas de tirar de mi cabello, y aquellos de ustedes que me han visto saben que esto está en gran medida de un infructuoso esfuerzo.

  • No es algo como esto publicado por Romain Guy? curious-creature.org/2011/02/22/…
  • Él no es el uso de fragmentos de AFAICT. Visualmente, es el derecho básico de efecto, y que puede ser capaz de utilizar esto como otro punto de datos para intentar crear un fragmento basado en la respuesta. Gracias!
  • Sólo un pensamiento: el estándar de la aplicación de Correo electrónico tiene una similar (aunque no idéntica) comportamiento en mi Nexus 7 — que debe ser de código abierto.
  • La aplicación de Correo electrónico utiliza una costumbre «ThreePaneLayout» que anima a la posición de la Vista de la izquierda, y los anchos/la visibilidad de los otros dos puntos de vista — cada uno de los cuales contienen el Fragmento relevante.
  • Eso es muy interesante. No he usado el AOSP aplicación de Correo electrónico, así que no se dio cuenta de que se utiliza la misma interfaz de usuario básica de la estructura de allí con Gmail. Tenga en cuenta que no tengo manera de otorgar una recompensa a un comentario, así que usted podría considerar la posibilidad de escribir una respuesta con sus ideas sobre la ThreePaneLayout aplicación. Gracias!
  • me pueden decir los Fragmentos a y B se miden? es en linearLayout con el peso de atributo? Relación con el estándar de DPs , Fragmento de Un es wrap_content y B se llena el resto de la pantalla? También Dibujable el almacenamiento en caché está permitido ? ( lo que significa que los diseños no se puede actualizar durante la animación)
  • me puedes decir los Fragmentos a y B se miden?» — cualquiera de sus enfoques estaría bien, aunque tengo una leve preferencia por el LinearLayout/peso de enfoque. «También Dibujable el almacenamiento en caché está permitido ? ( lo que significa que los diseños no se puede actualizar durante la animación)» — :: shrug :: fuera de, quizás, el uso de hardware de las capas en las versiones posteriores de Android, no me ha dado ese aspecto mucho pensamiento.
  • tiene una leve preferencia por el LinearLayout/peso enfoque» así, un personalizado (bootstrap estilo) ViewGroup que separa el ancho de la pantalla con el N de igualdad de unidades y cada fragmento se lleva a x*N espacio de ancho, está permitido.(Casi lo que peso, pero un poco más controlable)
  • El Control es la clave, en particular el control que puede estar basado en el espacio disponible en la general contenedor (vs calcular un montón de valores de dimensión, como la AOSP aplicación de Correo electrónico no). Sin embargo, «N la igualdad de unidades» definitivamente no es lo que estoy buscando, como llegar Fragmento B para cambiar el tamaño a lo que Fragmento de Un tamaño había sido una clave difícil de las piezas de este rompecabezas.
  • hey @CommonsWare no te molestes ppl con toda mi respuesta aquí, pero hay una pregunta similar a la tuya en la que me dio una respuesta satisfactoria. Así, sólo una sugerencia que a la salida (también ver los comentarios): stackoverflow.com/a/14155204/906362

InformationsquelleAutor CommonsWare | 2012-09-03

6 Comentarios

  1. 66

    De subir mi propuesta en github
    (Es trabajar con todas las versiones de android a pesar de que la vista de la aceleración de hardware es muy recomendable para este tipo de animaciones. Para los que no acelerada por hardware de los dispositivos de una caché de mapa de bits aplicación debe encajar mejor)

    Vídeo de demostración con la animación es Aquí (Lenta velocidad de fotogramas causa de la pantalla de cast. El rendimiento real es muy rápido)


    Uso:

    layout = new ThreeLayout(this, 3);
    layout.setAnimationDuration(1000);
    setContentView(layout);
    layout.getLeftView();   //<---inflate FragmentA here
    layout.getMiddleView(); //<---inflate FragmentB here
    layout.getRightView();  //<---inflate FragmentC here
    
    //Left Animation set
    layout.startLeftAnimation();
    
    //Right Animation set
    layout.startRightAnimation();
    
    //You can even set interpolators

    Explicación:

    Creado una nueva costumbre RelativeLayout(ThreeLayout) y 2 Animaciones personalizadas(MyScalAnimation, MyTranslateAnimation)

    ThreeLayout obtiene el peso del panel de la izquierda como param ,suponiendo que el otro visible de la vista ha weight=1.

    Así new ThreeLayout(context,3) crea una vista nueva con 3 niños y el panel de la izquierda con tener 1/3 del total de la pantalla. El otro punto de vista ocupa todo el espacio disponible.

    Se calcula el ancho en tiempo de ejecución,más seguro de la aplicación es que las dimensiones se calcularán primera vez en draw(). en lugar de en el post()

    De escala y traducción de animaciones realmente cambiar el tamaño y mover la vista y no pseudo-[escala,mover]. Observe que fillAfter(true) no se utiliza en cualquier lugar.

    View2 es right_of Vista1

    y

    View3 es right_of View2

    De haber establecido estas reglas RelativeLayout encarga de todo lo demás. Animaciones alterar el margins (en movimiento) y [width,height] en la escala de

    Para acceder a cada niño (de modo que usted puede inflar con su Fragmento puede llamar

    public FrameLayout getLeftLayout() {}
    
    public FrameLayout getMiddleLayout() {}
    
    public FrameLayout getRightLayout() {}

    A continuación se demuestra el 2 animaciones


    Stage1

    —EN la Pantalla———-!—–FUERA—-

    [Vista1][_____View2_____][_____View3_____]

    Stage2

    –OUT-!——–EN Pantalla——

    [Vista1][View2][_____View3_____]

    • Mientras que yo no he implementado una escala animador sin embargo, me preocupa que va a funcionar bien para sólidos de los campos de color y menos bien en, digamos, «real» de su contenido. Los resultados del Fragmento B se cambia el tamaño para que se ajuste Fragmento de Un espacio no debe ser diferente que si el Fragmento B, que había sido puesto allí originalmente. Por ejemplo, AFAIK, una escala animador se escala el tamaño de la fuente (por el dibujo de todo lo que en la película de animación View más pequeños), pero en Gmail/Correo electrónico, no nos fuentes más pequeñas, menos palabras.
    • scaleAnimation es sólo un nombre abstracto. De hecho, no hay escala se lleva a cabo. Lo que realmente cambia el tamaño de la vista del ancho. Compruebe la fuente. LayoutResizer podría ser un mejor nombre para él.
    • Que no es mi interpretación de la fuente de todo el scaleX valor en View, a pesar de que me puede estar malinterpretando las cosas.
    • marque esta github.com/weakwire/3PaneLayout/blob/master/src/com/example/… fuera. La única razón por la que extender la Animación es conseguir acceso a a la interpolatedTime . p.ancho = (int) de ancho; el que hace toda la magia y no scaleX. Es real ver las dimensiones que alteran durante el tiempo especificado.
    • Ah, lo siento, mi error. Estaba leyendo tu comentario y no contrastar con su fuente en ese momento. Gracias! Se me ocurrió otra solución, en paralelo a su propio desarrollo, a pesar de que en el momento en que son «el líder en la casa club» para obtener la recompensa: stackoverflow.com/a/12318422/115145
    • Un video muestra un buen framerate, pero el punto de vista utilizado en el ejemplo es muy simple. Haciendo un requestLayout() durante una animación es muy costoso. Sobre todo si los niños son complejos (un ListView, por ejemplo). Esto probablemente resultará en un partido de la animación. La app de GMail no llame requestLayout. En su lugar, otro punto de vista más pequeño se coloca en el panel del medio, justo antes de la animación se inicia.
    • está ahí por casualidad una forma de crear un diseño que va a aparecer a partir de la parte superior?
    • sí, yo no veo ninguna limitación en la materia. Acaba de configurar su diseño con RelativeLayout params y más tarde de los márgenes.

  2. 31

    OK, aquí está mi propia solución, derivado del Email AOSP aplicación, por @Christopher sugerencia en la pregunta del comentario.

    https://github.com/commonsguy/cw-omnibus/tree/master/Animation/ThreePane

    @weakwire la solución es una reminiscencia de la mina, a pesar de que utiliza clásico Animation en lugar de animadores, y él utiliza RelativeLayout reglas para hacer cumplir el posicionamiento. Desde el punto de vista de la recompensa, probablemente va a recibir la recompensa, a menos que alguien con una suave solución puestos de una respuesta.


    En pocas palabras, la ThreePaneLayout en que es un proyecto de LinearLayout subclase, diseñado para trabajar en paisaje con tres hijos. Los niños anchos se pueden establecer en el diseño de XML, a través de cualquier medio — me muestran el uso de pesas, pero que podría tener un ancho específico establecido por la dimensión de los recursos o lo que sea. El tercer hijo, el Fragmento C de la pregunta — debe tener un ancho de cero.

    package com.commonsware.android.anim.threepane;
    import android.animation.Animator;
    import android.animation.AnimatorListenerAdapter;
    import android.animation.ObjectAnimator;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.View;
    import android.widget.LinearLayout;
    public class ThreePaneLayout extends LinearLayout {
    private static final int ANIM_DURATION=500;
    private View left=null;
    private View middle=null;
    private View right=null;
    private int leftWidth=-1;
    private int middleWidthNormal=-1;
    public ThreePaneLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    initSelf();
    }
    void initSelf() {
    setOrientation(HORIZONTAL);
    }
    @Override
    public void onFinishInflate() {
    super.onFinishInflate();
    left=getChildAt(0);
    middle=getChildAt(1);
    right=getChildAt(2);
    }
    public View getLeftView() {
    return(left);
    }
    public View getMiddleView() {
    return(middle);
    }
    public View getRightView() {
    return(right);
    }
    public void hideLeft() {
    if (leftWidth == -1) {
    leftWidth=left.getWidth();
    middleWidthNormal=middle.getWidth();
    resetWidget(left, leftWidth);
    resetWidget(middle, middleWidthNormal);
    resetWidget(right, middleWidthNormal);
    requestLayout();
    }
    translateWidgets(-1 * leftWidth, left, middle, right);
    ObjectAnimator.ofInt(this, "middleWidth", middleWidthNormal,
    leftWidth).setDuration(ANIM_DURATION).start();
    }
    public void showLeft() {
    translateWidgets(leftWidth, left, middle, right);
    ObjectAnimator.ofInt(this, "middleWidth", leftWidth,
    middleWidthNormal).setDuration(ANIM_DURATION)
    .start();
    }
    public void setMiddleWidth(int value) {
    middle.getLayoutParams().width=value;
    requestLayout();
    }
    private void translateWidgets(int deltaX, View... views) {
    for (final View v : views) {
    v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    v.animate().translationXBy(deltaX).setDuration(ANIM_DURATION)
    .setListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
    v.setLayerType(View.LAYER_TYPE_NONE, null);
    }
    });
    }
    }
    private void resetWidget(View v, int width) {
    LinearLayout.LayoutParams p=
    (LinearLayout.LayoutParams)v.getLayoutParams();
    p.width=width;
    p.weight=0;
    }
    }

    Sin embargo, en tiempo de ejecución, no importa cómo se configuró originalmente el ancho, la anchura de gestión es asumida por ThreePaneLayout la primera vez que uso hideLeft() para cambiar de mostrar lo que la pregunta se refiere a como los Fragmentos a y B a los Fragmentos B y C. En la terminología de ThreePaneLayout — que no tiene ninguna específica vínculos con fragmentos — las tres piezas son left, middle, y right. En el momento de llamar a hideLeft(), tenemos constancia de que los tamaños de left y middle y de cero pesos que fueron utilizados en cualquiera de los tres, por lo que podemos controlar por completo los tamaños. En el momento de hideLeft(), podemos configurar el tamaño de right a ser el tamaño original de middle.

    Las animaciones son de dos tipos:

    • Utilizar un ViewPropertyAnimator para realizar una traducción de los tres widgets a la izquierda por el ancho de left, el uso de una capa de hardware
    • Utilizar un ObjectAnimator en una costumbre pseudo-propiedad de middleWidth para cambiar el middle ancho de lo que comenzó con la anchura original de left

    (es posible que se de una mejor idea utilizar una AnimatorSet y ObjectAnimators para todos estos, a pesar de que esto funciona por ahora)

    (también es posible que el middleWidth ObjectAnimator niega el valor de la capa de hardware, ya que requiere cierta continuidad de la invalidación)

    (es definitivamente posible que todavía tengo huecos en mi animación comprensión, y que me gusta declaraciones entre paréntesis)

    El efecto neto es que left se desliza fuera de la pantalla, middle se desliza a la posición original y el tamaño de left, y right se traduce en el derecho detrás de middle.

    showLeft() simplemente invierte el proceso, con la misma mezcla de animadores, sólo con las instrucciones invertido.

    La actividad utiliza una ThreePaneLayout a cabo un par de ListFragment widgets y un Button. Seleccionar algo en la izquierda fragmento añade o actualiza el contenido de) de la media fragmento. La selección de algo en el medio fragmento se establece el título de la Button, además ejecuta hideLeft() en el ThreePaneLayout. Pulsando de nuevo, si nos escondió el lado izquierdo, se ejecutará showLeft(); de lo contrario, de VUELTA sale de la actividad. Ya que este no utiliza FragmentTransactions de afectar a las animaciones, estamos atrapados gestión que «atrás de la pila» a nosotros mismos.

    El proyecto vinculado a la anterior utiliza nativo de fragmentos y los nativos de animador marco. Yo tengo otra versión de este mismo proyecto, que utiliza el Soporte para Android fragmentos de migración y NineOldAndroids para la animación:

    https://github.com/commonsguy/cw-omnibus/tree/master/Animation/ThreePaneBC

    El backport funciona bien en una 1ª generación de Kindle Fire, aunque la animación es un poco desigual, dada la menor de especificaciones de hardware y la falta de aceleración de hardware de apoyo. Ambas implementaciones parezca suave en un Nexus 7 y otros la actual generación de tabletas.

    Ciertamente estoy abierto a ideas de cómo mejorar esta solución, u otras soluciones que ofrecen ventajas claras sobre lo que yo he hecho (o lo @weakwire utilizado).

    Gracias de nuevo a todos los que han contribuido!

    • Hola! Gracias por la solución, pero creo que, la adición de v. setLayerType() a veces hace las cosas un poco más despacio. Acaba de quitar estas líneas (y Escucha demasiado) Esto es al menos cierto para Android 3+ dispositivos que he probado en Galaxy Nexus y sin estas líneas es mucho mejor
    • «Ambas implementaciones parezca suave en un Nexus 7 y otros la actual generación de tabletas.» Yo creo que usted; pero yo soy la prueba de su aplicación nativa de ObjectAnimator en un Nexus 7 y se queda un poco. ¿Cuál sería la más probable causa ? Ya tengo hardwareAccelerated:true en el AndroidMAnifest. La verdad, no sé cuál puede ser el problema. También he intentado DanielGrech de la variante y se queda la misma. Puedo ver las diferencias en la animación (con su animación se basa en pesos), pero no puedo ver por qué se iba a la zaga en ambos casos.
    • queda un poco» — estoy seguro de cómo se está utilizando el verbo «lag» aquí. Para mí, «lag» implica una meta concreta para la comparación. Así, por ejemplo, una animación atado a una deslizar el movimiento podría zaga del movimiento de los dedos. En este caso, todo es provocado por los grifos, y por eso estoy claro de lo que la animación puede ser a la zaga. Creo que tal vez «queda un poco» significa simplemente «es lento», no he visto eso, pero yo no pretendo tener un fuerte sentido de la estética, y así lo que podría ser una aceptable de animación para mí podría ser inaceptable para usted.
    • En términos de tratar de descifrar si algo está mal, puede probar las técnicas que se explican por Romain Guy en esta entrada del blog: curious-creature.org/2012/12/01/android-performance-case-study
    • Sí, tu intuición está en la pista. Gal = es lento; queda un poco = es lento, pero no mucho, sólo un par de fotogramas. De hecho, mediante el uso de dumpsys gfxinfo llegué a la conclusión de que el avg total de tiempo de cálculo por fotograma es de 18ms, que está por encima de 16ms línea. De todos modos, tal vez voy a abrir una pregunta aparte para no secuestrar el hilo.
    • Sólo para confirmar, está encontrando la pérdida de fotogramas en mi proyecto original, o simplemente en su proyecto, desde la su seguimiento ASÍ, pregunta?
    • Yo no he probado su proyecto en solitario. Es sólo mi aplicación. Así que no te preocupes, es muy probable que no se el código de la culpa, si eso es lo que usted quiere oír.
    • Es más, que hay una diferencia entre mi sabiendo que hay un problema en mi código y mi sospecha de que hay un problema en mi código. Solo te ligeramente cambiar mi forma de enfocar el problema, cuando yo lo veo la próxima semana.
    • Chet Haase eché un vistazo al código y escrito una respuesta en la pregunta referente a la animación tartamudeo. Ya he quitado el ObjectAnimator y la requestLayout() la llamada, pero todavía no he encontrado una forma de simular el Gmail de animación, sin hacer un diseño de paso en cada frame de la animación. Si te encuentras con una idea, hacer compartir.
    • mi mejor conjetura es que el panel central es que no se cambia el tamaño de la mosca, sino más bien el panel de la izquierda se desliza sobre la parte superior de la misma como parte de la animación y el cambio de tamaño que está sucediendo en la final. Eso es sólo una conjetura. La aplicación que requeriría una relación bastante completa de la reescritura de mi ThreePaneLayout, como LinearLayout no admite que se superpone en el eje Z.
    • He compilado el código con 4.2, gran trabajo. Cuando me tocó en un medio ListView y pulsa de nuevo el botón de forma rápida y repetida, a continuación, todo el Diseño se desvió a la derecha. Se empezó a mostrar más espacio columna de la izquierda. Este comportamiento se presentó porque no quería que la primera animación (iniciado por el toque en medio ListView) completar y pulsa el botón atrás. Me fijo por la sustitución de translationXBy con translationX en translateWidgets método y translateWidgets(leftWidth, left, middle, right); con translateWidgets(0, left, middle, right); en showLeft() método.
    • Yo también reemplazó a requestLayout(); con middle.requestLayout(); en setMiddleWidth(int value); método. Es posible que no influye en el rendimiento como supongo GPU todavía va a hacer un esquema completo de paso, algún comentario?
    • En algún momento, voy a tratar de replicar sus resultados, pero puede ser un par de días antes de que yo pueda hacerlo.
    • Mark, me encontré con el mismo problema que @M-WaJeEh mediante el Android Mono (aleatorio rápido de hacer clic) en él. La solución propuesta (absoluta de traducción en lugar de relativa) parece solucionarlo por completo para mí. Propongo copiar.

  3. 13

    Hemos construido una biblioteca llamada PanesLibrary que resuelve este problema. Es incluso más flexible de lo que ha sido previamente ofrecida porque:

    • Cada panel puede ser dinámicamente el tamaño
    • Se permite cualquier número de paneles (no solo 2 o 3)
    • Fragmentos en el interior de los paneles están correctamente conservado en los cambios de orientación.

    Usted puede ver aquí: https://github.com/Mapsaurus/Android-PanesLibrary

    Aquí una demo: http://www.youtube.com/watch?v=UA-lAGVXoLU&feature=norton ghost.ser

    Que básicamente le permite agregar fácilmente cualquier número de dinámicamente el tamaño de los paneles y adjuntar los fragmentos a los paneles. Espero que les sea útil! 🙂

  4. 6

    La construcción de uno de los ejemplos que enlaza a (http://android.amberfog.com/?p=758), acerca de cómo la animación de la layout_weight propiedad? De esta manera, se puede animar a los cambios en el peso de los 3 fragmentos juntos, Y usted consigue la ventaja de que todos ellos se deslice bien juntas:

    Inicio con un diseño sencillo. Puesto que vamos a ser la animación de layout_weight, necesitamos un LinearLayout como la raíz de la vista de los 3 paneles.:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
    android:id="@+id/panel1"
    android:layout_width="0dip"
    android:layout_weight="1"
    android:layout_height="match_parent"/>
    <LinearLayout
    android:id="@+id/panel2"
    android:layout_width="0dip"
    android:layout_weight="2"
    android:layout_height="match_parent"/>
    <LinearLayout
    android:id="@+id/panel3"
    android:layout_width="0dip"
    android:layout_weight="0"
    android:layout_height="match_parent"/>
    </LinearLayout>

    A continuación, la clase demo:

    public class DemoActivity extends Activity implements View.OnClickListener {
    public static final int ANIM_DURATION = 500;
    private static final Interpolator interpolator = new DecelerateInterpolator();
    boolean isCollapsed = false;
    private Fragment frag1, frag2, frag3;
    private ViewGroup panel1, panel2, panel3;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    panel1 = (ViewGroup) findViewById(R.id.panel1);
    panel2 = (ViewGroup) findViewById(R.id.panel2);
    panel3 = (ViewGroup) findViewById(R.id.panel3);
    frag1 = new ColorFrag(Color.BLUE);
    frag2 = new InfoFrag();
    frag3 = new ColorFrag(Color.RED);
    final FragmentManager fm = getFragmentManager();
    final FragmentTransaction trans = fm.beginTransaction();
    trans.replace(R.id.panel1, frag1);
    trans.replace(R.id.panel2, frag2);
    trans.replace(R.id.panel3, frag3);
    trans.commit();
    }
    @Override
    public void onClick(View view) {
    toggleCollapseState();
    }
    private void toggleCollapseState() {
    //Most of the magic here can be attributed to: http://android.amberfog.com/?p=758
    if (isCollapsed) {
    PropertyValuesHolder[] arrayOfPropertyValuesHolder = new PropertyValuesHolder[3];
    arrayOfPropertyValuesHolder[0] = PropertyValuesHolder.ofFloat("Panel1Weight", 0.0f, 1.0f);
    arrayOfPropertyValuesHolder[1] = PropertyValuesHolder.ofFloat("Panel2Weight", 1.0f, 2.0f);
    arrayOfPropertyValuesHolder[2] = PropertyValuesHolder.ofFloat("Panel3Weight", 2.0f, 0.0f);
    ObjectAnimator localObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(this, arrayOfPropertyValuesHolder).setDuration(ANIM_DURATION);
    localObjectAnimator.setInterpolator(interpolator);
    localObjectAnimator.start();
    } else {
    PropertyValuesHolder[] arrayOfPropertyValuesHolder = new PropertyValuesHolder[3];
    arrayOfPropertyValuesHolder[0] = PropertyValuesHolder.ofFloat("Panel1Weight", 1.0f, 0.0f);
    arrayOfPropertyValuesHolder[1] = PropertyValuesHolder.ofFloat("Panel2Weight", 2.0f, 1.0f);
    arrayOfPropertyValuesHolder[2] = PropertyValuesHolder.ofFloat("Panel3Weight", 0.0f, 2.0f);
    ObjectAnimator localObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(this, arrayOfPropertyValuesHolder).setDuration(ANIM_DURATION);
    localObjectAnimator.setInterpolator(interpolator);
    localObjectAnimator.start();
    }
    isCollapsed = !isCollapsed;
    }
    @Override
    public void onBackPressed() {
    //TODO: Very basic stack handling. Would probably want to do something relating to fragments here..
    if(isCollapsed) {
    toggleCollapseState();
    } else {
    super.onBackPressed();
    }
    }
    /*
    * Our magic getters/setters below!
    */
    public float getPanel1Weight() {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)     panel1.getLayoutParams();
    return params.weight;
    }
    public void setPanel1Weight(float newWeight) {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel1.getLayoutParams();
    params.weight = newWeight;
    panel1.setLayoutParams(params);
    }
    public float getPanel2Weight() {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel2.getLayoutParams();
    return params.weight;
    }
    public void setPanel2Weight(float newWeight) {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel2.getLayoutParams();
    params.weight = newWeight;
    panel2.setLayoutParams(params);
    }
    public float getPanel3Weight() {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel3.getLayoutParams();
    return params.weight;
    }
    public void setPanel3Weight(float newWeight) {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel3.getLayoutParams();
    params.weight = newWeight;
    panel3.setLayoutParams(params);
    }
    /**
    * Crappy fragment which displays a toggle button
    */
    public static class InfoFrag extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle     savedInstanceState) {
    LinearLayout layout = new LinearLayout(getActivity());
    layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    layout.setBackgroundColor(Color.DKGRAY);
    Button b = new Button(getActivity());
    b.setOnClickListener((DemoActivity) getActivity());
    b.setText("Toggle Me!");
    layout.addView(b);
    return layout;
    }
    }
    /**
    * Crappy fragment which just fills the screen with a color
    */
    public static class ColorFrag extends Fragment {
    private int mColor;
    public ColorFrag() {
    mColor = Color.BLUE; //Default
    }
    public ColorFrag(int color) {
    mColor = color;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    FrameLayout layout = new FrameLayout(getActivity());
    layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    layout.setBackgroundColor(mColor);
    return layout;
    }
    }
    }

    También este ejemplo no utiliza FragmentTransactions para lograr las animaciones (más bien, se anima a las opiniones de los fragmentos se adjunta), por lo que tendría que hacer todo el backstack/fragmento de operaciones de ti mismo, pero en comparación con el esfuerzo de conseguir las animaciones trabajando muy bien, esto no parece un mal trade-off 🙂

    Horrible de baja resolución de vídeo de la acción: http://youtu.be/Zm517j3bFCo

    • Bueno, Gmail, definitivamente, hace una traducción de lo que yo describo como Fragmento de A. me preocuparía que la reducción de su peso a 0 podría introducir artefactos visuales (por ejemplo, TextView con wrap_content se ejercita de manera vertical como la animación continúa). Sin embargo, puede ser que la animación del peso es cómo cambiar el tamaño de lo que yo me refería como Fragmento B. Gracias!
    • No se preocupe! Eso es un buen punto, aunque, es probable que esto causaría artefactos visuales en función de lo que el niño vistas en «Fragmento de Un’. Esperemos que alguien encuentra una más sólida manera de hacerlo
  5. 5

    Este no es el uso de fragmentos…. Es un diseño personalizado y con 3 hijos. Cuando usted haga clic en un mensaje, usted desplazamiento de los 3 niños el uso de offsetLeftAndRight() y un animador.

    En JellyBean puede activar «Mostrar el diseño de los límites» en el «Desarrollador» Opciones de configuración. Cuando la diapositiva de animación se completa, usted todavía puede ver que el menú de la izquierda está todavía allí, pero por debajo de la media del panel.

    Es similar a Cirilo Mottier con Mosca en el menú de la aplicación, pero con 3 elementos, en vez de 2.

    Además, el ViewPager de la tercera niños es otro indicio de este comportamiento: ViewPager generalmente se utiliza Fragmentos (sé que ellos no tienen, pero nunca he visto una aplicación de otras que Fragment), y ya que no utiliza Fragments dentro de otro Fragment los 3 niños probablemente no son los fragmentos….

    • Yo nunca he usado «Mostrar el diseño de los límites» antes de que … de que es muy útil para la fuente cerrada aplicaciones como esta (¡gracias!). Parece que lo que he descrito como Fragmento de Una es la traducción de la pantalla (se puede ver su borde derecho deslice de derecha a izquierda), antes de hacer estallar de nuevo en debajo de lo que he descrito como Fragmento B. Que se siente como un TranslateAnimation, aunque estoy seguro de que hay formas de usar los animadores para lograr el mismo fin. Voy a tener que ejecutar algunos experimentos sobre esto. Gracias!
  6. 2

    Actualmente estoy tratando de hacer algo como eso, excepto que el Fragmento B escala para tener el espacio disponible y que el 3 de panel se pueden abrir al mismo tiempo si no hay espacio suficiente. Aquí está mi solución hasta el momento, pero no estoy seguro de si me voy a quedar con ella. Espero que alguien va a dar una respuesta que muestra La Manera Correcta.

    Lugar de utilizar un LinearLayout y animar el peso, yo uso un RelativeLayout y animar a los márgenes. No estoy seguro de que es la mejor manera debido a que se requiere una llamada a requestLayout() en cada actualización. Es suave en todos mis dispositivos, aunque.

    Así que me anime el diseño, no estoy utilizando fragmentos de la transacción. Yo manejo el botón atrás manualmente para cerrar el fragmento C si está abierto.

    FragmentB uso layout_toLeftOf/ToRightOf para mantenerlo alineado a fragmento a y C.

    Cuando mi app desencadenar un evento para mostrar el fragmento C, me deslice en el fragmento C, y me desliza fragmento de Una al mismo tiempo. (2 aparte de la animación). Inversamente, cuando Un Fragmento de abrir, cerrar C al mismo tiempo.

    En modo retrato o en la pequeña pantalla, yo uso un diseño ligeramente diferente y deslice el Fragmento C por encima de la pantalla.

    A porcentaje de uso del ancho de Fragmento a y C, creo que se tendría que calcular en tiempo de ejecución… (?)

    Aquí es la actividad del diseño:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootpane"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <!-- FRAGMENT A -->
    <fragment
    android:id="@+id/fragment_A"
    android:layout_width="300dp"
    android:layout_height="fill_parent"
    class="com.xyz.fragA" />
    <!-- FRAGMENT C -->
    <fragment
    android:id="@+id/fragment_C"
    android:layout_width="600dp"
    android:layout_height="match_parent"
    android:layout_alignParentRight="true"
    class="com.xyz.fragC"/>
    <!-- FRAGMENT B -->
    <fragment
    android:id="@+id/fragment_B"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:layout_marginLeft="0dip"
    android:layout_marginRight="0dip"
    android:layout_toLeftOf="@id/fragment_C"
    android:layout_toRightOf="@id/fragment_A"
    class="com.xyz.fragB" />
    </RelativeLayout>

    La animación de la diapositiva FragmentC dentro o fuera:

    private ValueAnimator createFragmentCAnimation(final View fragmentCRootView, boolean slideIn) {
    ValueAnimator anim = null;
    final RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) fragmentCRootView.getLayoutParams();
    if (slideIn) {
    //set the rightMargin so the view is just outside the right edge of the screen.
    lp.rightMargin = -(lp.width);
    //the view's visibility was GONE, make it VISIBLE
    fragmentCRootView.setVisibility(View.VISIBLE);
    anim = ValueAnimator.ofInt(lp.rightMargin, 0);
    } else
    //slide out: animate rightMargin until the view is outside the screen
    anim = ValueAnimator.ofInt(0, -(lp.width));
    anim.setInterpolator(new DecelerateInterpolator(5));
    anim.setDuration(300);
    anim.addUpdateListener(new AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    Integer rightMargin = (Integer) animation.getAnimatedValue();
    lp.rightMargin = rightMargin;
    fragmentCRootView.requestLayout();
    }
    });
    if (!slideIn) {
    //if the view was sliding out, set visibility to GONE once the animation is done
    anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
    fragmentCRootView.setVisibility(View.GONE);
    }
    });
    }
    return anim;
    }

Dejar respuesta

Please enter your comment!
Please enter your name here