Search code examples
javaandroidandroid-listviewandroid-viewandroid-transitions

ListView Shared Element Transition Issue


I am attempting to create shared element transition between two Activities. This appears to work find between two layouts, each containing a single ImageView. However, I am having issues getting this transition to work with a ListView.

The issue is when the user taps on the first row, the transition will work as expected. However, when the second row is tapped, the origin of the transition appears to be the image of the first row as well!

I have created a simple list view with a custom row layout:

row_detailed.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="1">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Daft Punk"
        android:id="@+id/primary_textview"
        android:layout_gravity="center_horizontal"
        android:layout_weight="0.07"
        android:layout_alignTop="@+id/primary_imageview"
        android:layout_toRightOf="@+id/primary_imageview" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Random Access Memories"
        android:id="@+id/textView4"
        android:layout_gravity="center_horizontal"
        android:layout_weight="0.07"
        android:layout_alignBottom="@+id/primary_imageview"
        android:layout_toRightOf="@+id/primary_imageview" />


    <ImageView
        android:layout_width="84dp"
        android:layout_height="84dp"
        android:id="@+id/primary_imageview"
        android:src="@drawable/ram"
        android:layout_weight="0.07" />

</RelativeLayout>

The layout for the secondary Activity, activity_transition_secondary.xml:

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="legiocode.com.tapstrprototype.activity.TransitionSecondaryActivity">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/secondary_imageview"
        android:src="@drawable/ram"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentEnd="true" />

</RelativeLayout>

The Primary Activity, TransitionPrimaryActivity.java:

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

        ListView listView = (ListView)findViewById(R.id.listView2);
        ArrayAdapter<String> adapter = new ArrayAdapter(this,
                R.layout.row_detailed,
                R.id.primary_textview,
                items);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                String transitionName = getString(R.string.transition_image) + String.format("_%d", i);

                ImageView imageView = (ImageView)findViewById(R.id.primary_imageview);
                imageView.setTransitionName(transitionName);

                Intent intent = new Intent(TransitionPrimaryActivity.this, TransitionSecondaryActivity.class);
                intent.putExtra(TransitionSecondaryActivity.TRANSITION_NAME, transitionName);

                ActivityOptionsCompat options =
                        ActivityOptionsCompat.makeSceneTransitionAnimation(TransitionPrimaryActivity.this,
                                imageView,   // The view which starts the transition
                                transitionName    // The transitionName of the view we’re transitioning to
                        );
                ActivityCompat.startActivity(TransitionPrimaryActivity.this, intent, options.toBundle());
            }
        });
    }

The Secondary Activity, TransitionSecondaryActivity.java:

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

        String transitionName = getIntent().getStringExtra(TRANSITION_NAME);

        ImageView imageView = (ImageView)findViewById(R.id.secondary_imageview);
        imageView.setTransitionName(transitionName);
    }

I have tried to implement the transition names dynamically, but that doesn't seem to make much of a difference. Am I setting up the transition correctly?


Solution

  • You have to access your actually clicked View (in this case parameter view) in

    onItemClick(AdapterView<?> adapterView, View view, int i, long l)
    

    With

    ImageView imageView = (ImageView)findViewById(R.id.primary_imageview);
    

    you always access the first element in the list.

    PS: Put the transition names inside the xml. Makes it much more easy to read.