Cómo iniciar compartido elemento de transición utilizando Fragmentos?

Estoy tratando de implementar transiciones entre los fragmentos que han «elementos comunes», como se describe en el nuevo material de especificaciones de diseño.
El único método que puede encontrar es la ActivityOptionsCompat.makeSceneTransitionAnimation, que creo que trabaja en la Actividad.
He estado buscando esta misma funcionalidad pero con/para los fragmentos.

  • Has comprobado FragmentTransaction.addSharedElement -método ; developer.android.com/reference/android/support/v4/app/… ?
  • Traté de usar que, en la realidad, pero no parece funcionar, al menos desde un imageview en un elemento listview. Probablemente hay un montón de indocumentados limitaciones. La desactivación de las transiciones y animaciones en la transacción no parecía ayudar, aunque.
  • Yo no era capaz de llegar a trabajar con ImageViews dentro de la lista de elementos. Yo era capaz de reunir a una Actividad muy sencilla con 2 de pantalla completa de los fragmentos. Cada fragmento tiene 2 puntos de vista con el fondo negro en diferentes tamaños y posiciones, y cuando me toque la pantalla se cambia el fragmento. Los elementos compartidos hizo animar como era de esperar en este caso. Sí funciona, sólo tal vez, no cuando su vista en un elemento de la lista. Me pregunto si es porque los elementos de la lista no son conocidos hasta el tiempo de ejecución?
  • Ahora puedo confirmar que la transición de un punto de vista que es dentro de una lista de elementos de diseño de una vista en un nuevo fragmento no funciona. Si pongo una vista en mi primer fragmentos de diseño, fuera de la vista de lista, que hace el trabajo.
  • He encontrado la solución para listview\recyclerview. Usted necesita transición únicos nombre para cada elemento. Leer más: androidauthority.com/…
  • Aquí está una serie de posts, que puede ayudar a entender los Fragmentos de la transición.

InformationsquelleAutor unchosen | 2014-10-25

7 Kommentare

  1. 45

    Tuve el mismo problema, pero tenía que trabajar por la adición de un nuevo fragmento de otro fragmento.
    El siguiente enlace es muy útil en la introducción en el presente: https://developer.android.com/training/material/animations.html#Transitions

    Siguiente es mi código que funciona. Me voy a animar un ImageView de un fragmento a otro.
    Asegúrese de que el View desea animar tiene el mismo android:transitionName en ambos fragmentos.
    El contenido de otros en realidad no importa.

    Como una prueba, usted puede copiar este tanto en su formato de archivos xml. Asegúrese de que la imagen existe.

    <ImageView
    android:transitionName="MyTransition"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    android:src="@drawable/test_image" />

    Entonces tengo 1 archivo en mi res/transition carpeta, nombre change_image_transform.xml.

    <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
        <changeImageTransform />
    </transitionSet>

    Ahora usted puede empezar. Digamos que usted tiene Fragmento de Una que contiene la imagen y quiere añadir un Fragmento B.

    Ejecutar en este Fragmento de Un:

    @Override
    public void onClick(View v) {
        switch(v.getId()) {
            case R.id.product_detail_image_click_area:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_transform));
                    setExitTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.explode));
    
                    //Create new fragment to add (Fragment B)
                    Fragment fragment = new ImageFragment();
                    fragment.setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_transform));
                    fragment.setEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.explode));
    
                    //Our shared element (in Fragment A)
                    mProductImage   = (ImageView) mLayout.findViewById(R.id.product_detail_image);
    
                    //Add Fragment B
                    FragmentTransaction ft = getFragmentManager().beginTransaction()
                            .replace(R.id.container, fragment)
                            .addToBackStack("transaction")
                            .addSharedElement(mProductImage, "MyTransition");
                    ft.commit();
                }
                else {
                    //Code to run on older devices
                }
                break;
        }
    }
    • Esto funciona para mí, excepto que siempre se inicia la animación en la parte superior de la pantalla en el segundo fragmento. Así que si tengo una vista en cada elemento de mi listview (o en mi caso RecyclerView) y pulsa sobre uno cerca de la parte inferior de la lista y la nueva colocación para que la vista en el segundo fragmento se encuentra en la parte inferior de la pantalla, que en realidad anima desde la parte superior a la parte inferior en lugar de animar desde el lugar de la pantalla en el primer fragmento, donde la vista comenzó. Alguien sabe por qué es esto?
    • Creo que esto es debido a que la vista de lista repetidamente contiene los mismos elementos. Si se iba a realizar una findViewById, el primer punto de retorno. Creo que se debe identificar la animación de la vista mediante la asignación de la transitionName dinámicamente cuando se hace clic en el elemento.
    • Yo soy la asignación del identificador único para cada instancia en la que mi Adaptador. Estoy anexando los elementos de la posición. Dicho esto, he resuelto mi problema. Resulta que deberá incluir la ChangeTransform a su TransitionSet. Esto le dice al sistema para guardar la posición de inicio de la vista que se acaba de seleccionar y usar eso como la posición de inicio de la animación en el nuevo fragmento.
    • usted puede elaborar sobre » Como resulta que es necesario incluir la ChangeTransform a su TransitionSet.» ? ¿Cómo hacer eso?
    • es sólo res/transición, gradle no construir de otra manera. developer.android.com/reference/android/transition/…
    • Esto no funciona cuando me add el fragmento en lugar de replace'. Any ideas on how to achieve the transition animation with agregar`? — stackoverflow.com/questions/29145031/…
    • echa un vistazo a este enlace androidauthority.com/…
    • bonito tutorial. Aunque tenga en cuenta que addSharedElement de la FragmentTransaction se llama fuera de la Piruleta si-declaración, por lo que no funciona en dispositivos más antiguos, como se trata de una API lev. 21 método. Debería ser corregido. Consulte developer.android.com/reference/android/app/…, java.lang.Cadena)

  2. 21

    Estoy publicando esto como una respuesta, ya que soy nuevo aquí y no puede comentar.

    Compartido elemento fragmento de transiciones hacer trabajo con ListViews, siempre y cuando el origen y el destino de las opiniones de la misma (y única) transitionName.

    Si se hacen de la vista de lista adaptador para establecer único transitionNames a las vistas que desee (por ejemplo, en algunas constante + específicos de id de elemento) y también cambiar su detalle de un fragmento de conjunto de la misma transitionNames a la meta vistas en tiempo de ejecución (onCreateView), las transiciones en realidad el trabajo!

    • Este fijo que es para mí. Soy capaz de animar mi compartida ImageViews de un fragmento a otro dentro de la misma Actividad. Ahora mi problema es que mi ImageViews no están traduciendo en sus nuevas posiciones, que acaba de aparecer en su nueva ubicación, sino que se ejecute una escala de animación. Estoy usando setSharedElementEnterTransition(nueva ChangeBounds()); cuando me cree mi fragmento de la instancia. Similar comportamiento con ChangeImageTransform()
    • Es posible conseguir un trozo de código de trabajo para probar esto? He estado tratando durante algún tiempo ahora, y nada funciona.
    • para mí, incluso si cada una de las vistas de imágenes comparten el mismo transitionName, es un poco de obras. funciona bien si la imagen todavía está en la memoria y sólo después de la primera vez que la animación se produce. el problema es, como yo lo estoy usando descargado las imágenes, se puede ver la imagen vista de intercambio para la reserva de uno de los primeros antes de cargar el adecuado. aún así, tengo la fuerza de carga de la misma imagen en el fragmento B, pasar la url de la imagen como un argumento a partir de un fragmento A.
  3. 11

    De elementos compartidos hacer un trabajo con los Fragmentos, pero hay algunas cosas a tener en cuenta:

    1. No intenta establecer la sharedElementsTransition en el onCreateView de su Fragmento. Usted tiene que definen al crear una instancia de su Fragmento o en onCreate.

    2. Tomar nota de la documentación oficial sobre la posible animaciones para entrar/salir de las transiciones & sharedElementTransition. Ellos no son el mismo.

    3. De ensayo y error 🙂

  4. 3

    Este debe ser un comentario a la aceptación de la respuesta, pues yo soy incapaz de hacer un comentario sobre él.

    La aceptación de la respuesta (por WindsurferOak y ar34z) obras, salvo para un «pequeño» problema que causó una excepción de puntero nulo cuando se navega con el backStack. Parece que setSharedElementReturnTransition() debe ser llamado en el destino fragmento en lugar del fragmento original.

    Así que en lugar de:

    setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_transform));

    debe ser

    fragment.setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_transform));

    https://github.com/tevjef/Rutgers-Course-Tracker/issues/8

  5. 0

    La clave es usar un custom transacción con

    transaction.addSharedElement(sharedElement, "sharedImage");

    Compartido Elemento De Transición Entre Dos Fragmentos De

    En este ejemplo, uno de los dos diferentes ImageViews debe ser traducido de la ChooserFragment a la DetailFragment.

    En el ChooserFragment diseño necesitamos el único transitionName atributos:

    <ImageView
        android:id="@+id/image_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_first"
        android:transitionName="fistImage" />
    
    <ImageView
        android:id="@+id/image_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_second"
        android:transitionName="secondImage" />

    En el ChooserFragments clase, tenemos que pasar la View que se ha hecho clic y una IDENTIFICACIÓN con el padre Activity que es el manejo de la sustitución de los fragmentos (necesitamos el ID para saber qué recursos de imagen para mostrar en el DetailFragment). Cómo pasar información a un padre de la actividad en detalle es, sin duda cubierto en otra documentación.

    view.findViewById(R.id.image_first).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mCallback != null) {
                mCallback.showDetailFragment(view, 1);
            }
        }
    });
    
    view.findViewById(R.id.image_second).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mCallback != null) {
                mCallback.showDetailFragment(view, 2);
            }
         }
    });

    En el DetailFragment, el ImageView de la compartida elemento también necesita la única transitionName atributo.

    <ImageView
        android:id="@+id/image_shared"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:transitionName="sharedImage" />

    En el onCreateView() método de la DetailFragment, tenemos que decidir qué imagen recurso debe ser demostrado (si no hacemos eso, el compartido elemento desaparecerá después de la transición).

    public static DetailFragment newInstance(Bundle args) {
        DetailFragment fragment = new DetailFragment();
        fragment.setArguments(args);
        return fragment;
    }
    
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_detail, container, false);
    
        ImageView sharedImage = (ImageView) view.findViewById(R.id.image_shared);
    
        //Check which resource should be shown.
        int type = getArguments().getInt("type");
    
        //Show image based on the type.
        switch (type) {
            case 1:
                sharedImage.setBackgroundResource(R.drawable.ic_first);
                break;
    
            case 2:
                sharedImage.setBackgroundResource(R.drawable.ic_second);
                break;
        }
    
        return view;
    }

    El padre Activity es recibir las devoluciones de llamada y se encarga de la reposición de los fragmentos.

    @Override
    public void showDetailFragment(View sharedElement, int type) {
        //Get the chooser fragment, which is shown in the moment.
        Fragment chooserFragment = getFragmentManager().findFragmentById(R.id.fragment_container);
    
        //Set up the DetailFragment and put the type as argument.
        Bundle args = new Bundle();
        args.putInt("type", type);
        Fragment fragment = DetailFragment.newInstance(args);
    
        //Set up the transaction.
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
    
        //Define the shared element transition.
        fragment.setSharedElementEnterTransition(new DetailsTransition());
        fragment.setSharedElementReturnTransition(new DetailsTransition());
    
        //The rest of the views are just fading in/out.
        fragment.setEnterTransition(new Fade());
        chooserFragment.setExitTransition(new Fade());
    
        //Now use the image's view and the target transitionName to define the shared element.
        transaction.addSharedElement(sharedElement, "sharedImage");
    
        //Replace the fragment.
        transaction.replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName());
    
        //Enable back navigation with shared element transitions.
        transaction.addToBackStack(fragment.getClass().getSimpleName());
    
        //Finally press play.
        transaction.commit();
    }

    No hay que olvidar la Transition sí mismo. Este ejemplo se mueve y ajusta el elemento compartido.

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public class DetailsTransition extends TransitionSet {
    
        public DetailsTransition() {
            setOrdering(ORDERING_TOGETHER);
            addTransition(new ChangeBounds()).
                addTransition(new ChangeTransform()).
                addTransition(new ChangeImageTransform());
        }
    
    }
  6. 0

    He buscado por SharedElement en fragmentos y me parece muy útil el código fuente en GitHub.

    1.primero, se debe definir la transitionName para sus Objetos(ImageView) en ambos Fragmentos de diseño(Podemos añadir un botón en el fragmento de Un para el manejo de evento click):

    fragmento de Un:

      <ImageView
        android:id="@+id/fragment_a_imageView"
        android:layout_width="128dp"
        android:layout_height="96dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="80dp"
        android:scaleType="centerCrop"
        android:src="@drawable/gorilla"
        android:transitionName="@string/simple_fragment_transition />
    
    <Button
        android:id="@+id/fragment_a_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="24dp"
        android:text="@string/gorilla" />

    fragmento B:

        <ImageView
        android:id="@+id/fragment_b_image"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:scaleType="centerCrop"
        android:src="@drawable/gorilla"
        android:transitionName="@string/simple_fragment_transition" />
    1. Entonces usted debe escribir este código en su transición de archivo en la transición de Directorio(si no este Directorio para crear Uno: res > nuevo > Android Directorio de Recursos > Tipo de Recurso = transición > nombre = change_image_transform ):

    change_image_transform.xml:

     <?xml version="1.0" encoding="utf-8"?>
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
      <changeBounds/>
      <changeTransform/>
      <changeClipBounds/>
      <changeImageTransform/>
    </transitionSet>
    1. En el último paso se debe completar los códigos en java:

    fragmento de Un:

    public class FragmentA extends Fragment {
    
        public static final String TAG = FragmentA.class.getSimpleName();
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            //Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_a, container, false);
        }
    
        @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            final ImageView imageView = (ImageView) view.findViewById(R.id.fragment_a_imageView);
            Button button = (Button) view.findViewById(R.id.fragment_a_btn);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    getFragmentManager()
                            .beginTransaction()
                            .addSharedElement(imageView, ViewCompat.getTransitionName(imageView))
                            .addToBackStack(TAG)
                            .replace(R.id.content, new FragmentB())
                            .commit();
                }
            });
        }
    }

    fragmento B:

    public class FragmentB extends Fragment {
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
                setSharedElementEnterTransition(TransitionInflater.from(getContext()).inflateTransition(android.R.transition.move));
    
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_b, container, false);
        }
    }

    no olvides mostrar tu «Un» fragmento de su actividad:

     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.content, new SimpleFragmentA())
                    .commit();
        }

    fuente : https://github.com/mikescamell/shared-element-transitions

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea