Laut Android-Dokumentation bestimmen Shared Elements Transitions, wie Ansichten, die von zwei Activities geteilt werden, zwischen diesen Activities übergehen. Wenn zum Beispiel zwei Activities das gleiche Bild in verschiedenen Positionen und Größen haben, übersetzt und skaliert der changeImageTransform shared element transition das Bild reibungslos zwischen diesen Activities.

Dieser Thread befasst sich mit Beispielen und Bibliotheken im Zusammenhang mit Shared Transitions in android. Du kannst gerne weitere Beispiele, Links und Bibliotheken beisteuern.

SharedTransition für Bilder einfach implementieren

Mit dieser Bibliothek, die als Transitional ImageView bekannt ist, können Sie ganz einfach gemeinsame Elementübergänge für Bilder implementieren.

Lassen Sie uns zeigen, wie das geht.

Schritt 1 - Installieren Sie die Bibliothek

Registrieren Sie zunächst jitpack als Repository in Ihrer App-Ebene build.gradle:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Dann installieren Sie die Bibliothek:

implementation 'com.github.mostafaaryan:transitional-imageview:v0.2.2'

Schritt 2

Erstellen Sie Transitional ImageView in Ihrem Layout, indem Sie den folgenden Code einfügen:

<com.mostafaaryan.transitionalimageview.TransitionalImageView
        android:id="@+id/transitional_image"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"
        android:adjustViewBounds="true"
        app:res_id="@drawable/sample_image" />

Schritt 3

Erstellen Sie nun ein TransitionImageObject und setzen Sie es auf den TransitionalImageView:

TransitionalImageView transitionalImageView = (TransitionalImageView) findViewById(R.id.transitional_image);
TransitionalImage transitionalImage = new TransitionalImage.Builder()
                                    .duration(500)
                                    .backgroundColor(ContextCompat.getColor(MainActivity.this, R.color.color))
                                    .image(R.drawable.sample_image)
                                    /* or */
                                    .image(bitmap)
                                    .create();
transitionalImageView.setTransitionalImage(transitionalImage);

Full Example

Hier ist ein schönes Beispiel für die Verwendung dieser Bibliothek.

(a). Shoe.java

Die Modellklasse zur Definition eines einzelnen Schuhs.

public class Shoe {

    private String Title;
    private String imageUrl;

    public Shoe(String title, String imageUrl) {
        Title = title;
        this.imageUrl = imageUrl;
    }

    public String getTitle() {
        return Title;
    }

    public String getImageUrl() {
        return imageUrl;
    }

}

(b). ShoeAdapter.java

Dann der Adapter für die Recycling-Ansicht.

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.ariannejad.mostafa.transitional_imageview_implementation.R;
import com.ariannejad.mostafa.transitional_imageview_implementation.controller.MainActivity;
import com.ariannejad.mostafa.transitional_imageview_implementation.model.Shoe;
import com.mostafaaryan.transitionalimageview.TransitionalImageView;
import com.mostafaaryan.transitionalimageview.model.TransitionalImage;
import com.squareup.picasso.Picasso;

import java.io.IOException;
import java.util.ArrayList;

/**
 * Created by Mostafa Aryan Nejad on 8/11/17.
 */

public class ShoeAdapter extends RecyclerView.Adapter<ShoeAdapter.ViewHolder> {

    Context mContext;
    ArrayList<Shoe> shoes = new ArrayList<>();

    public ShoeAdapter(Context context, ArrayList<Shoe> shoes) {
        mContext = context;
        this.shoes = shoes;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_shoe, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {

        final Shoe shoe = shoes.get(position);

        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                try{

                    final Bitmap bitmap = Picasso.with(mContext).load(shoe.getImageUrl()).get();
                    ((Activity) mContext).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            TransitionalImage transitionalImage = new TransitionalImage.Builder()
                                    .duration(500)
                            /*.backgroundColor(ContextCompat.getColor(, R.color.colorAccent))*/
                                    /*.image(R.drawable.sample_image)*/
                                    .image(bitmap)
                                    .create();
                            holder.image.setTransitionalImage(transitionalImage);
                            bitmap.recycle();
                        }
                    });
                } catch (IOException e){e.printStackTrace();}
            }
        });

        holder.title.setText(shoe.getTitle());
        holder.sizes.setText("37,38,39,40");

    }

    @Override
    public int getItemCount() {
        return shoes.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView title;
        public TextView sizes;
        public TransitionalImageView image;

        public ViewHolder(View itemView) {
            super(itemView);

            title = (TextView) itemView.findViewById(R.id.shoe_title);
            sizes = (TextView) itemView.findViewById(R.id.shoe_sizes);
            image = (TransitionalImageView) itemView.findViewById(R.id.shoe_image);

        }

    }

}

(c). ShoeListActivity.java

Die Aktivität der Schuhliste:

import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.TabLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;

import com.ariannejad.mostafa.transitional_imageview_implementation.R;
import com.ariannejad.mostafa.transitional_imageview_implementation.adapter.ShoeAdapter;
import com.ariannejad.mostafa.transitional_imageview_implementation.model.Shoe;

import java.util.ArrayList;

public class ShoeListActivity extends AppCompatActivity {

    private RecyclerView shoeRecyclerView;
    private ArrayList<Shoe> shoes = new ArrayList<>();
    private ActionBar actionBar;
    private AppBarLayout appBarLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shoe_list);

        shoeRecyclerView = (RecyclerView) findViewById(R.id.shoe_recycler_view);
        CollapsingToolbarLayout collapsingToolbar =
                (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        appBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
        setOnOffsetChangedListener();
        collapsingToolbar.setTitleEnabled(false);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        actionBar = getSupportActionBar();
        if(actionBar != null) actionBar.setTitle("");

        populateList();

    }

    private void populateList() {
        shoes.add(new Shoe("Skechers Relaxed Fit Empire Game On Walking Shoe",
                "https://www.shoes.com/pm/skech/skech800828_42965_hd2.jpg"));

        shoes.add(new Shoe("Skechers After Burn Memory Fit Geardo High Top Trainer",
                "https://www.shoes.com//pm/skech/skech798492_42965_hd2.jpg"));

        shoes.add(new Shoe("New Balance Fresh Foam Zante v3 Running Shoe",
                "https://www.shoes.com/pi/newba/hd/newba805216_436896_hd.jpg"));

        for(int i = 0 ; i <= 5 ; i++ ) {
            shoes.addAll(shoes);
        }

        displayList();
    }

    private void displayList() {
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        RecyclerView.Adapter adapter = new ShoeAdapter(this, shoes);
        shoeRecyclerView.setLayoutManager(layoutManager);
        shoeRecyclerView.setAdapter(adapter);
    }

    private void setOnOffsetChangedListener() {

        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {

            boolean isDisplayed = false;

            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                int totalScroll = appBarLayout.getTotalScrollRange();

                if (totalScroll + verticalOffset == 0) {
                    if (actionBar != null) {
                        actionBar.setTitle("Sneakers");
                    }
                    isDisplayed = true;
                } else if (isDisplayed) {
                    if (actionBar != null)
                        actionBar.setTitle("");
                    isDisplayed = false;
                }
            }

        });

    }

}

(d). MainActivity.java

Und schließlich die Haupt-"Aktivität".

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.ariannejad.mostafa.transitional_imageview_implementation.R;
import com.mostafaaryan.transitionalimageview.TransitionalImageView;
import com.mostafaaryan.transitionalimageview.model.TransitionalImage;
import com.squareup.picasso.Picasso;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    private String imageUrl = "https://image.freepik.com/free-icon/android-logo_318-54237.jpg";
    TransitionalImageView tiv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tiv = (TransitionalImageView) findViewById(R.id.sample_image);

        loadImage();

    }

    private void loadImage() {

        /*
        ImageLoader imageLoader;
        imageLoader = ImageLoader.getInstance();
        imageLoader.init(ImageLoaderConfiguration.createDefault(this));
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                DisplayImageOptions dio = new DisplayImageOptions.Builder()
                        .cacheInMemory(false).build();
                final Bitmap bmp = imageLoader.loadImageSync(imageUrl, dio);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tiv.setImage(bmp);
                    }
                });
            }
        });*/

        /* Glide.with(this).asBitmap().load(imageUrl).into(new SimpleTarget<Bitmap>() {
            @Override
            public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                tiv.setImage(resource);
            }
        }); */

        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    final Bitmap b = Picasso.with(MainActivity.this).load(imageUrl).get();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
//                            tiv.setImage(b);
                            TransitionalImage transitionalImage = new TransitionalImage.Builder()
                                    .duration(500)
                                    .backgroundColor(ContextCompat.getColor(MainActivity.this, R.color.colorAccent))
                                    //.image(R.drawable.sample_image)
                                    .image(b)
                                    .create();
                            tiv.setTransitionalImage(transitionalImage);
                        }
                    });

                } catch (IOException e) {e.printStackTrace();}
            }
        });

    }

    public void onClickShoes(View view) {
        startActivity(new Intent(this, ShoeListActivity.class));
    }

}

Demo

Hier ist die Demo dessen, was Sie erhalten, wenn Sie das Projekt ausführen.

Android Shared Element Image Transition Example

Download

Hier sind die Download-Links.

  1. Direkter Download hier.
  2. Folgen Sie dem Autor hier.

Kotlin Shared Transition RecyclerView und Fragmente

Dies ist ebenfalls ein einfaches Beispiel für Shared Transitions, geschrieben in Kotlin. Diesmal ist jedoch eine RecyclerView das gemeinsame Element von zwei Fragmenten.

Tools

Hier sind die Dinge, die man beachten sollte:

  • Programmiersprache - Kotlin
  • Minimum SDK - 21

1. Übergänge erstellen

Fügen Sie in einem Ordner namens "transitions" unter "resources" das Folgende hinzu:

(a). change_bounds.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet>
    <changeBounds />
</transitionSet>

(b). change_image_transform.xml

Dann:

<?xml version="1.0" encoding="utf-8"?>
<transitionSet>
    <changeImageTransform />
</transitionSet>

2. Layouts entwerfen

Die Layouts finden Sie im Code.

3. Code schreiben

In diesem Fall wird der Code in Kotlin geschrieben.

(a). Fragment1.kt

Hier ist der Code für das erste Fragment.

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
import android.transition.ChangeBounds
import android.transition.ChangeImageTransform

class Fragment1: Fragment() {

    private lateinit var lm: LinearLayoutManager

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.activity_main, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        lm = LinearLayoutManager(context, LinearLayoutManager.VERTICAL,
            false)
        rv.layoutManager = lm
        val adapter = MainActivity.Adapter()
        rv.adapter = adapter
        btn.setOnClickListener {

//            val changeImageTransform =
//                TransitionInflater.from(context).inflateTransition(R.transition.change_image_transform)
//            val changeBoundsTransform =
//                TransitionInflater.from(context).inflateTransition(R.transition.change_bounds)

            sharedElementReturnTransition = ChangeBounds()
            sharedElementEnterTransition = ChangeImageTransform()
            exitTransition = ChangeBounds()

            val fragment2 = Fragment2()
            // Setup transition on second fragment
            fragment2.sharedElementEnterTransition = ChangeBounds()
            fragment2.enterTransition = ChangeBounds();

            val firstVisiblePosition = lm.findFirstVisibleItemPosition()
            val lastVisiblePosition = lm.findLastVisibleItemPosition()
            val transaction = fragmentManager!!.beginTransaction()
                .replace(R.id.container, fragment2, fragment2::class.java.simpleName)
                .addToBackStack("name")
            for (i in firstVisiblePosition..lastVisiblePosition) {
                val holderForAdapterPosition =
                    rv.findViewHolderForAdapterPosition(i) as MainActivity.Adapter.Holder
                val itemView = holderForAdapterPosition.itemView
                transaction.addSharedElement(itemView, "unique_key_$i")
            }
            transaction.commit()
        }
    }
}

(b). Fragment2.kt

Fügen Sie den folgenden Code in das zweite Fragment ein.

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*

class Fragment2: Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.activity_main, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val lm = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL,
            false)
        rv.layoutManager = lm
        val adapter = MainActivity.Adapter()
        rv.adapter = adapter
        btn.setOnClickListener {
        }
        postponeEnterTransition()
    }

    override fun onStart() {
        super.onStart()
        rv.post {
            startPostponedEnterTransition()
        }
    }
}

(c). ScndActivity.kt

Dann die zweite Activity.

import android.os.Bundle
import android.os.PersistableBundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*

class ScndActivity: AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val lm = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,
            false)
        rv.layoutManager = lm
        val adapter = MainActivity.Adapter()
        rv.adapter = adapter
        btn.setOnClickListener {

            //            val currentOrientation = lm.orientation
//            if (currentOrientation == LinearLayoutManager.VERTICAL) {
//                lm.orientation = LinearLayoutManager.HORIZONTAL
//            } else {
//                lm.orientation = LinearLayoutManager.VERTICAL
//            }
//            adapter.notifyItemRangeChanged(1, adapter?.itemCount ?: 0)
        }
        supportPostponeEnterTransition()
        rv.post {
            supportStartPostponedEnterTransition()
        }
    }
}

(d). MainActivity.kt

Und zum Schluss die Hauptaktivität,

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {

    private lateinit var lm: LinearLayoutManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.cont)
        val fragment1 = Fragment1()
        supportFragmentManager.beginTransaction()
            .add(R.id.container, fragment1, Fragment1::class.java.simpleName)
            .commit()
//        lm = LinearLayoutManager(this, LinearLayoutManager.VERTICAL,
//            false)
//        rv.layoutManager = lm
//        val adapter = Adapter()
//        rv.adapter = adapter
//        btn.setOnClickListener {
//            val firstVisiblePosition = lm.findFirstVisibleItemPosition()
//            val lastVisiblePosition = lm.findLastVisibleItemPosition()
//            val pairs = ArrayList<Pair<View, String>>()
//            for (i in firstVisiblePosition..lastVisiblePosition) {
//                val holderForAdapterPosition =
//                    rv.findViewHolderForAdapterPosition(i) as Adapter.Holder
//                val itemView = holderForAdapterPosition.itemView
//                pairs.add(Pair(itemView, "unique_key_$i"))
//            }
//            val bundle = ActivityOptions.makeSceneTransitionAnimation(
//                this,
//                *pairs.toTypedArray()
//            ).toBundle()
//            val fragment1 = Fragment1()
//            supportFragmentManager.beginTransaction()
//                .add(fragment1, Fragment1::class.java.simpleName)
//                .commit()
//            startActivity(Intent(this, ScndActivity::class.java), bundle)
//        }
    }

    override fun onResume() {
        super.onResume()
    }

    class Adapter : RecyclerView.Adapter<Adapter.Holder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder =
            Holder(
                LayoutInflater.from(parent.context).inflate(
                    R.layout.item_item,
                    parent,
                    false
                )
            )

        override fun getItemCount(): Int = 10

        override fun onBindViewHolder(holder: Holder, position: Int) {
            holder.bind(position)
        }

        class Holder(view: View) : RecyclerView.ViewHolder(view) {

            fun bind(position: Int) {
                itemView.transitionName = "unique_key_$position"
            }
        }
    }
}

Demo

Hier ist, was Sie erhalten, wenn Sie das Projekt ausführen.

Android Kotlin <code>Shared Transition</code> Example RecyclerView

Download.

  1. Direkter Download hier.
  2. Dem Autor folgen hier.

Java Shared Transition mit Fragmenten und FloatingActionButton

Dies ist ein einfaches Ein-Klassen-Beispiel, um einen gemeinsamen Element-Übergang innerhalb von Fragmenten in einer androiden Aktivität zu verwenden. Die Programmiersprache ist Java. Obwohl es nicht in androidx geschrieben ist, kann man es leicht auf androidx fragments aktualisieren und es verwendet keine Bibliothek von Drittanbietern.

Übergänge

Diese sind in XML geschrieben.  Normalerweise erstellt man ein Transition-Ressourcenverzeichnis und platziert die XML.

(a). shared_enter_transition.xml

Hier ist der Code:

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

    <changeTransform/>
    <arcMotion
        android:minimumHorizontalAngle="0"
        android:minimumVerticalAngle="15"
        android:maximumAngle="90" />
    <changeBounds />

</transitionSet>

Activities

Hier sind die Aktivitäten

(a). MainActivity.java

Hier ist die wichtigste Aktivität:

import android.animation.Animator;
import android.app.Fragment;
import android.os.Bundle;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.ActionBarActivity;
import android.transition.Fade;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;

public class FabActivity extends ActionBarActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fab);

        getFragmentManager()
                .beginTransaction()
                .add(R.id.frag_content, TitleFragment.newInstance())
                .commit();
    }

    public static class TitleFragment extends Fragment {
        public static TitleFragment newInstance() {
            return new TitleFragment();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            final View view = inflater.inflate(R.layout.fragment_fab_title, container, false);
            final View fabbutton = view.findViewById(R.id.fab);
            fabbutton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    final ControlsFragment controlsFragment = ControlsFragment.newInstance();

                    setupSharedElementTransition(controlsFragment);
                    Fade f = new Fade();
                    f.setStartDelay(250);
                    setExitTransition(f);

                    getFragmentManager()
                            .beginTransaction()
                            .replace(R.id.frag_content, controlsFragment)
                            .addToBackStack("controls")
                            .addSharedElement(fabbutton, "pause_button")
                            .commit();
                }
            });
            return view;
        }

        private void setupSharedElementTransition(final ControlsFragment controlsFragment) {
            Transition sharedTransition = TransitionInflater.from(getActivity()).inflateTransition(R.transition.shared_enter_transition);
            controlsFragment.setSharedElementEnterTransition(sharedTransition);
            controlsFragment.setSharedElementReturnTransition(sharedTransition);
            sharedTransition.addListener(new Transition.TransitionListener() {
                @Override
                public void onTransitionEnd(Transition transition) {
                    controlsFragment.revealContent();
                }

                @Override
                public void onTransitionStart(Transition transition) {
                }

                @Override
                public void onTransitionCancel(Transition transition) {
                }

                @Override
                public void onTransitionPause(Transition transition) {
                }

                @Override
                public void onTransitionResume(Transition transition) {
                }
            });

        }

    }

    public static class ControlsFragment extends Fragment {

        public static ControlsFragment newInstance() {
            return new ControlsFragment();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_fab_controls, container, false);
        }

        public void revealContent() {
            View layout = getView().findViewById(R.id.controls_layout);
            animateRevealColor(layout);
        }

        private void animateRevealColor(View targetView) {
            int cx = (targetView.getLeft() + targetView.getRight()) / 2;
            int cy = (targetView.getTop() + targetView.getBottom()) / 2;

            cx += targetView.getTranslationX();
            cy += targetView.getTranslationY();
            int finalRadius = Math.max(targetView.getWidth(), targetView.getHeight());

            Animator anim = ViewAnimationUtils.createCircularReveal(targetView, cx, cy, 0, finalRadius);
            targetView.setBackgroundColor(getResources().getColor(R.color.accent_material_light));
            anim.setDuration(getResources().getInteger(R.integer.default_anim_duration));
            anim.setInterpolator(new AccelerateInterpolator());
            anim.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationEnd(Animator animator) {
                    animateScaleButton(getView().findViewById(R.id.ff_button));
                    animateScaleButton(getView().findViewById(R.id.rew_button));
                }

                @Override
                public void onAnimationStart(Animator animator) {
                }

                @Override
                public void onAnimationCancel(Animator animator) {
                }

                @Override
                public void onAnimationRepeat(Animator animator) {
                }
            });
            anim.start();
        }

        private void animateScaleButton(View view) {
            ViewCompat.animate(view)
                    .scaleX(1)
                    .scaleY(1)
                    .setDuration(250)
                    .start();
        }
    }

}

Demo

Hier ist die Demo dessen, was Sie erhalten, wenn Sie das Projekt ausführen.

Fragments Shared Element Transition

Download Links

  1. Direktes Herunterladen des Codes hier. (Bitte aktualisieren Sie ihn auf androidx und teilen Sie Ihren Code erneut)
  2. Folgen Sie dem Autor hier.

Categorized in:

Tagged in: