Transition of nested shared elements does not starts from the expected place

拥有回忆 提交于 2019-12-09 06:43:08

问题


TL;DR Why this transition does not start from the expected place?

That is, the place where is the CardView.

Platform/Deps: Android Studio 1.0-RC2, TargetSdk 21, MinSdk 21, AppCompat-21.0.2, CardView-21.0.2, RecyclerView-21.0.2.

Tested On: Genymotion Nexus 5 Lollipop Preview

The Code (Simplified)

I have three shared elements:

Source:

<CardView
    android:transitionName="cardView">
    <ImageView
      android:transitionName="imageView">
    <TextView
      android:transitionName="textView">

Target:

<RelativeLayout
    android:transitionName="cardView">
    <ImageView
      android:transitionName="imageView">
    <TextView
      android:transitionName="textView">

Note below that the transition names are added programmatically. This is because CardView are holded on a RecyclerView and there are many copies of it. I've tried using the same name (as in the XML instance) but doesn't work neither.

The ReciclerView.Adapter does this:

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    //...
    ViewCompat.setTransitionName(viewHolder.mCardView, "cardViewTransition" + position);
    ViewCompat.setTransitionName(viewHolder.mImageView, "imageTransition" + position);
    ViewCompat.setTransitionName(viewHolder.mTextView, "textTransition" + position);
    //...
}

The HomeActivity does this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    getWindow().requestFeature(android.view.Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().requestFeature(android.view.Window.FEATURE_ACTIVITY_TRANSITIONS);
    // ..
    mRecyclerView.addOnItemTouchListener(
        new RecyclerItemClickListener(this, new RecyclerItemClickListener.OnItemClickListener() {
            @Override public void onItemClick(View view, int position) {
                Intent intent = new Intent(selfContext, DetailActivity.class);

                View imageView = view.findViewById(R.id.imageView);
                TextView textView = (TextView)view.findViewById(R.id.textView);

                Bundle extras = new Bundle();
                extras.putInt("position", position);
                extras.putString("text", textView.getText().toString());
                intent.putExtras(extras);
                String name = ViewCompat.getTransitionName(view);
                ActivityOptionsCompat options =
                    ActivityOptionsCompat.makeSceneTransitionAnimation(selfContext
                            ,Pair.create(view, ViewCompat.getTransitionName(view))
                            ,Pair.create(imageView, ViewCompat.getTransitionName(imageView))
                            ,Pair.create((View)textView, ViewCompat.getTransitionName(textView))
                    );
                ActivityCompat.startActivity(selfContext, intent, options.toBundle());
            }
        })
    );
    ///...
}

The DetailActivity does this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    getWindow().requestFeature(android.view.Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().requestFeature(android.view.Window.FEATURE_ACTIVITY_TRANSITIONS);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_detail);

    // ...

    Bundle extras = getIntent().getExtras();
    int mPositionRef = extras.getInt("position");
    View base = findViewById(R.id.detail_layout);
    View image = findViewById(R.id.imageView);
    TextView text = (TextView) findViewById(R.id.txtLabel);
    text.setText(extras.getString("text"));

    ViewCompat.setTransitionName(base, "cardViewTransition" + mPositionRef);
    ViewCompat.setTransitionName(image, "imageTransition" + mPositionRef);
    ViewCompat.setTransitionName(text, "textTransition" + mPositionRef);

}

I've debugged and shared elements have the same names in the source and destination.

The Question (Again)

Why this transition does not start from the expected place? That is, the place where is the CardView.

Complete sample in GitHub


回答1:


There is a known bug in Lollipop related to nested shared elements (i.e. adding both a view group and one of its children as shared elements at the same time), so it might be related to that (source: Glitch when animating nested views in a shared element Activity transition?).

Try only adding the ImageView and TextView as shared elements instead (not the parent relative layout container).




回答2:


It could be that all the items have the exact same transition because they all use the same name. You can use the method in this tutorial (https://mikescamell.com/shared-element-transitions-part-4-recyclerview/index.html) to set a unique transition name programmatically in onBindViewHolder():

ViewCompat.setTransitionName(
    holder.mySharedView, 
    "item_" + String.valueOf(sharedItem.getId()
);


来源:https://stackoverflow.com/questions/27258692/transition-of-nested-shared-elements-does-not-starts-from-the-expected-place

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!