Search code examples
androidanimationandroid-recyclerviewshared-element-transitionandroid-5.1.1-lollipop

Fix SharedElementTransition animation not showing well


I'm trying to create a shared elements transition animation between 2 activities with a shared ImageView.

The first one has a RecyclerView with an item click listener, and after click, it should start the other activity with the transition.

The animation works fine when closing the started activity, but it doesn't when starting it.

After tapping the item of the RecyclerView, it expands a bit, freezes for a bit, and then shows a blank black "window" and then the other ImageView, but it doesn't animates fluently.

This is the code to open the other activity:

private void openActivity(WallpapersAdapter.WallsHolder wallsHolder, int index, final HashMap<String, String> data) {

    Toast.makeText(this,data.get(WallpapersActivity.WALL),Toast.LENGTH_SHORT).show();

    final Intent intent = new Intent(wallsActivity, ViewerActivity.class);
    intent.putExtra("wallUrl", data.get(WallpapersActivity.WALL));
    intent.putExtra("wallName", data.get(WallpapersActivity.NAME));

    String indextext = Integer.toString(index);
    intent.putExtra("indexText", indextext);

    String transName = "view_" + indextext;
    ViewCompat.setTransitionName(wallsHolder.view, transName);
    ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
            wallsActivity, wallsHolder.view, transName);

    startActivity(intent, options.toBundle());

}

Edit: This is the code of the layout for the initial view:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="?selectableItemBackground">

    <ProgressBar
        android:id="@+id/progress"
        style="?progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginBottom="24dp" />

    <jahirfiquitiva.project.views.SquareImageView
        android:id="@+id/wall"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        tools:ignore="ContentDescription,UnusedAttribute" />

    <LinearLayout
        android:id="@+id/titlebg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        style="@style/AboutContent"
        android:alpha="0.3"
        android:background="#000000"
        tools:ignore="UnusedAttribute">

        <TextView
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:gravity="center"
            android:textColor="#ffffffff"
            android:textSize="@dimen/abc_text_size_medium_material"
            tools:text="Title" />

    </LinearLayout>

</FrameLayout>

Thanks in advance.

Edit 2: This is a video showing how it looks like: https://drive.google.com/file/d/0Bw52d3_ZiSb9YWc2Z1Z4MnkwNm8/view?usp=sharing


Solution

  • Ok I wrote this short program to experiment with this... I'm animating textViews as sharedElements... And it's working... Here's what I did :

    Inside my RecyclerView adapter

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
        ViewCompat.setTransitionName(((RecyclerViewHolder) holder).mTextView,"myTransition"+position);
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                mEventListener.clicked((RecyclerViewHolder) holder);
            }
        });
    }
    

    MainActivity's click event from where I'm starting the other Activity

    @Override
    public void clicked(final MyAdapter.RecyclerViewHolder holder) {
        final Intent intent = new Intent(this, AnotherActivity.class);
    
        intent.putExtra("TRANSITION_KEY", ViewCompat.getTransitionName(holder.mTextView));
    
        ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
                this, holder.mTextView, ViewCompat.getTransitionName(holder.mTextView));
    
        startActivity(intent, options.toBundle());
    }
    

    Other Activity's onCreate

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_another);
        TextView textView = (TextView) findViewById(R.id.textView2);
        Intent intent = getIntent();
        ViewCompat.setTransitionName(textView, intent.getStringExtra("TRANSITION_KEY"));
    }
    

    Solution to your specific problem

    Aside from following the previous instructions, remove the Toast inside onClick.

    Add transitionSet xml in : res/transition/image_transition.xml

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

    Remove these from your styles.xml (if they're added)

    <item name="android:windowAnimationStyle">@style/WindowTransitionAnimation</item>
    <item name="android:windowContentTransitions">true</item>
    <item name="android:windowAllowEnterTransitionOverlap">true</item>
    <item name="android:windowAllowReturnTransitionOverlap">true</item>
    <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
    <item name="android:windowSharedElementExitTransition">@android:transition/move</item>
    <item name="android:windowEnterTransition">@android:transition/move</item>
    <item name="android:windowExitTransition">@android:transition/move</item>