Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating shared element transitions using android fragments seems to be a nightmare

Animating a shared element transition between two fragments seems to be a pain. I have it working elsewhere in my app with the exact same code.

here is my on click code inside a recyclerview adapter:

private void click(int position, ItemViewHolder holder){

final ItemDescription itemDescription = itemListFiltered.get(position);
FragmentManager fm = mContext.getSupportFragmentManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && itemDescription != null) {

    //animate transition
    TransitionSet transitionSet = new TransitionSet();
    transitionSet.addTransition(new ChangeTransform());
    transitionSet.addTransition(new ChangeBounds());
    transitionSet.addTransition(new ChangeImageTransform());
    transitionSet.setDuration(300);

    //set up fragment
    ScanDetailsFragment frag = ScanDetailsFragment.newInstance(itemDescription, holder.productImage.getTransitionName());
    frag.setEnterTransition(transitionSet);
    frag.setExitTransition(transitionSet);

    fm.beginTransaction().replace(R.id.fragment_container, frag)
            .addSharedElement(holder.productImage, "product_image")
            .addToBackStack("item details")
            .commit();
}else {
    ScanDetailsFragment itemDetails = ScanDetailsFragment.newInstance(itemDescription);
    fm.beginTransaction().replace(R.id.fragment_container, itemDetails).addToBackStack("item details").commit();
}

I just can't seem to get this animation to work.

like image 835
shrewdu Avatar asked Aug 04 '15 02:08

shrewdu


1 Answers

here is how I did it

Fragment with the RecyclerView

public class DogFragment extends Fragment implements DogAdapter.OnItemCLickListener {

    public static final String TAG = "DogFragment";

    @InjectView(R.id.recyclerview_dog)
    RecyclerView mRecyclerView;

    DogAdapter adapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        final View v = inflater.inflate(R.layout.fragment_dog, container, false);
        ButterKnife.inject(this, v);
        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        final List<Integer> images = new ArrayList<>();
        images.add(R.drawable.dog1);
        images.add(R.drawable.dog2);
        images.add(R.drawable.dog3);

        final RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), 1);
        mRecyclerView.setLayoutManager(layoutManager);
        adapter = new DogAdapter(images);
        adapter.setOnItemClickListener(this);
        mRecyclerView.setAdapter(adapter);
    }

    public String getTAG() {
        return TAG;
    }

    @Override
    public void onItemClick(int position, int imageRefId, ImageView imageView) {
        SingleDogFragment fragment = SingleDogFragment.getInstance(getActivity(), adapter.getImageTransitionName(getActivity(), position), imageRefId);
        getFragmentManager().beginTransaction()
                .addSharedElement(imageView, adapter.getImageTransitionName(getActivity(), position))
                .replace(R.id.container, fragment, fragment.getTag())
                .addToBackStack(null)
                .commit();
    }
}

The adapter

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

    private OnItemCLickListener mItemClickListener;
    private List<Integer> mImages;

    public DogAdapter(List<Integer> images) {
        mImages = images;
    }

    public int getItem(int position) {
        return mImages.get(position);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.gridview_element_dog, viewGroup, false);

        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {
        viewHolder.mImageView.setImageResource(getItem(i));
        viewHolder.mImageView.setTransitionName(
                getImageTransitionName(viewHolder.mImageView.getContext(), i)
        );
    }

    public String getImageTransitionName(Context context, int position) {
        return context.getString(R.string.dog_transition_name) + position;
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        @InjectView(R.id.dog_imageview)
        ImageView mImageView;

        public ViewHolder(final View view) {
            super(view);
            ButterKnife.inject(this, view);
            view.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if (mItemClickListener != null) {
                mItemClickListener.onItemClick(getPosition(), getItem(getPosition()), mImageView);
            }
        }
    }

    public interface OnItemCLickListener {
        public void onItemClick(int position, int refId, ImageView imageView);
    }

    public void setOnItemClickListener(final OnItemCLickListener mItemClickListener) {
        this.mItemClickListener = mItemClickListener;
    }

}

Target fragment

public class SingleDogFragment extends Fragment {

    private static final String ARG_TRANSITION_NAME = "ARG_TRANSITION_NAME";
    private static final String ARG_IMAGE_REF_ID = "ARG_IMAGE_REF_ID";

    @InjectView(R.id.single_dog_imageview)
    ImageView mDogImage;

    public static SingleDogFragment getInstance(Context context, String transitionName, int imageRefId) {
        SingleDogFragment fragment = new SingleDogFragment();
        Bundle bundle = new Bundle();
        bundle.putString(ARG_TRANSITION_NAME, transitionName);
        bundle.putInt(ARG_IMAGE_REF_ID, imageRefId);
        fragment.setSharedElementEnterTransition(TransitionInflater.from(context).inflateTransition(R.transition.change_transform));
        fragment.setEnterTransition(TransitionInflater.from(context).inflateTransition(R.transition.slide_left));
        fragment.setExitTransition(TransitionInflater.from(context).inflateTransition(R.transition.slide_left));
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View v = inflater.inflate(R.layout.fragment_single_dog, container, false);
        ButterKnife.inject(this, v);
        mDogImage.setTransitionName(getArguments().getString(ARG_TRANSITION_NAME));
        mDogImage.setImageResource(getArguments().getInt(ARG_IMAGE_REF_ID));
        return v;
    }
}

change_transform.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <targets>
        <target android:excludeId="@android:id/statusBarBackground"/>
        <target android:excludeId="@android:id/navigationBarBackground"/> <!-- exclude the status bar and the navigation bar of the animation -->
    </targets>
    <changeBounds/>
    <changeTransform/>
</transitionSet>

And here is what it look like

enter image description here

Hope I could help !

like image 150
lcw_gg Avatar answered Sep 29 '22 10:09

lcw_gg