共享元素向后过渡不适用于片段中的recyclerview和cardviews

问题描述

我正在尝试在带有cardviews片段的回收者视图到仅包含1张卡片的片段之间创建过渡。问题在于后退过渡不起作用,而回车过渡则起作用。如果删除setReorderingallowed(true);,则向后过渡有效,但enter过渡停止工作。 这就是我所拥有的。

带有回收站视图和卡片视图的片段

public class OrdersFragment extends Fragment implements OrderAdapter.OnorderListener {

    private OrderAdapter mAdapter;

    private TextView bonnenTextView;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        postponeEnterTransition();
    }

    public View onCreateView(@NonNull LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_bonnen,container,false);
        bonnenTextView = view.findViewById(R.id.bonnen_text_view);
        RecyclerView orderRecyclerView = view.findViewById(R.id.order_recycler_view);
        RecyclerView.LayoutManager layoutManager = new linearlayoutmanager(getContext());
        orderRecyclerView.setLayoutManager(layoutManager);
        if (mAdapter == null) {
            mAdapter = new OrderAdapter(this);
            fetchOrders();
        }
        orderRecyclerView.setAdapter(mAdapter);
        return view;
    }

    private void fetchOrders() {
        new OrderFetcher().fetch(new Callback() {
            @Override
            public void onComplete(Result result) {
                if (result instanceof Result.Success) {
                    mAdapter.setorders((Order[]) ((Result.Success<?>)result).data);
                    mAdapter.notifyDataSetChanged();
                } else {
                    Toast.makeText(getContext(),"Could not load orders",Toast.LENGTH_SHORT).show();
                }
                startPostponedEnterTransition();
            }
        });
    }

    @Override
    public void onorderClick(int position,View view,Order order) {
        Log.i("OrderClick","Transition name " + view.getTransitionName());

        View carrierTextView = view.findViewById(R.id.carrier_text_view);
        View numberTextView = view.findViewById(R.id.id_text_view);
        View pickerTextView = view.findViewById(R.id.picker_text_view);
        View locationTextView = view.findViewById(R.id.location_text_view);

        FragmentTransaction transaction = getParentFragmentManager().beginTransaction();
        transaction.addSharedElement(view,view.getTransitionName());
        transaction.addSharedElement(carrierTextView,carrierTextView.getTransitionName());
        transaction.addSharedElement(numberTextView,numberTextView.getTransitionName());
        transaction.addSharedElement(pickerTextView,pickerTextView.getTransitionName());
        transaction.addSharedElement(locationTextView,locationTextView.getTransitionName());
        transaction.addSharedElement(bonnenTextView,bonnenTextView.getTransitionName());
        transaction.replace(R.id.nav_host_fragment,BonFragment.newInstance(view.getTransitionName(),order));
        transaction.addToBackStack(null);
        transaction.setReorderingallowed(true);
        transaction.commit();
    }
}

上面带有片段的XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ui.orders.OrdersFragment">

    <TextView
        android:id="@+id/bonnen_text_view"
        android:transitionName="bonnen_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:text="@string/orders"
        android:textColor="@color/secondary"
        android:textSize="40sp"
        android:textStyle="bold"
        android:typeface="normal" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/order_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="20dp"/>
</LinearLayout>

具有单张卡片视图的片段

public static BonFragment newInstance(String cardTransitionName,Order order) {
        BonFragment bonFragment = new BonFragment();

        Bundle args = new Bundle();
        args.putParcelable("orderParcel",order);
        args.putString("cardTransitionName",cardTransitionName);
        bonFragment.setArguments(args);

        return bonFragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater,Bundle savedInstanceState) {
        final View root = inflater.inflate(R.layout.fragment_bon,false);

        CardView orderCard = root.findViewById(R.id.order_card);
        TextView carrierTextView = root.findViewById(R.id.carrier_text_view);
        TextView numberTextView = root.findViewById(R.id.id_text_view);
        TextView pickerTextView = root.findViewById(R.id.picker_text_view);
        TextView locationTextView = root.findViewById(R.id.location_text_view);

        if (getArguments() != null && getArguments().getParcelable("orderParcel") != null) {
            Order order = getArguments().getParcelable("orderParcel");
            orderCard.setTransitionName(getArguments().getString("cardTransitionName"));
            if (order != null) {
                carrierTextView.setTransitionName("carrier" + order.getIndex());
                carrierTextView.setText(order.getCarrier());
                numberTextView.setTransitionName("number" + order.getIndex());
                numberTextView.setText(String.valueOf(order.getNumber()));
                pickerTextView.setTransitionName("picker" + order.getIndex());
                pickerTextView.setText(order.getPicker());
                locationTextView.setTransitionName("location" + order.getIndex());
                locationTextView.setText(order.getPosition());

                carrierTextView.setText("Lorem Ipsum");
                numberTextView.setText("Dolor sit amet");
                pickerTextView.setText("consectetur adipiscing elit");
                locationTextView.setText("Mauris semper");

            }
        }

        orderCard.setonClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getParentFragmentManager().popBackStack();
            }
        });

        Transition transition = TransitionInflater.from(getContext()).inflateTransition(R.transition.card_transition);
        setSharedElementEnterTransition(transition);
        setSharedElementReturnTransition(transition);
        return root;
    }

上面带有片段的XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ui.orders.OrdersFragment">

    <TextView
        android:transitionName="bonnen_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:text="@string/orders"
        android:textColor="@color/secondary"
        android:textSize="40sp"
        android:textStyle="bold"
        android:typeface="normal" />

    <androidx.cardview.widget.CardView
        android:id="@+id/order_card"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cardBackgroundColor="@color/primaryLight"
        android:foreground="?android:attr/selectableItemBackground"
        android:clickable="true"
        android:layout_margin="25dp">

        <LinearLayout
            android:transitionName="order_card_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_margin="10dp">
            <TextView
                android:id="@+id/carrier_text_view"
                android:transitionName="carrier_text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/secondary"
                android:textSize="20sp"
                android:textStyle="bold"/>
            <TextView
                android:id="@+id/id_text_view"
                android:transitionName="id_text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/secondary" />
            <TextView
                android:id="@+id/picker_text_view"
                android:transitionName="picker_text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/secondary" />
            <TextView
                android:id="@+id/location_text_view"
                android:transitionName="location_text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/secondary" />
        </LinearLayout>
    </androidx.cardview.widget.CardView>
</LinearLayout>

这就是setReorderingallowed(true);

的样子

This is what it looks like with setReorderingAllowed(true);

这是没有setReorderingallowed(true);

时的样子

This is what it looks like without setReorderingAllowed(true);

编辑 应用ianhanniballake给出的答案后,我开始使用它。 这是我所做的工作,以供将来参考。 我所做的唯一更改是在OrdersFragment类中。 我删除onCreate()方法的替代。 我从startPostponedEnterTransition();方法删除fetchOrders(),并添加

@Override
    public void onViewCreated(@NonNull View view,@Nullable Bundle savedInstanceState) {
        postponeEnterTransition();
        final ViewGroup parentView = (ViewGroup) view.getParent();
        parentView.getViewTreeObserver()
                .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                    @Override
                    public boolean onPreDraw() {
                        parentView.getViewTreeObserver().removeOnPreDrawListener(this);
                        startPostponedEnterTransition();
                        return true;
                    }
                });
        super.onViewCreated(view,savedInstanceState);
    }

就这样

解决方法

根据Use shared element transitions with a RecyclerView guide,您调用startPostponedEnterTransition()的时间过早-设置数据后(并调用notifyDataSetChanged()通知适配器),您需要等到{{ 1}}是实际测量和布局的。这就要求您添加一个RecyclerView,并且仅在触发后调用OnPreDrawListener