Call transition animation from RecyclerView Adapter instead of Activity
Asked Answered
E

2

6

I have an app with a RecyclerView filled with some cards, with help of a custom RecyclerView (RV) Adapter I made. I then tried to follow this tutorial in order to add a transition between activities. However, as shown in the tutorial, the animations are called when creating an Intent inside an Activity, and my OnClick code is inside the RVAdapter. This gives me no access to the Activity required on the method

Intent intent = new Intent(HomeActivity.this, TargetActivity.class);
intent.putExtra(TargetActivity.ID, Contact.CONTACTS[position].getId());
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
        // the context of the activity
        MainActivity.this,

        // For each shared element, add to this method a new Pair item,
        // which contains the reference of the view we are transitioning *from*,
        // and the value of the transitionName attribute
        new Pair<View, String>(view.findViewById(R.id.CONTACT_circle),
                getString(R.string.transition_name_circle)),
        new Pair<View, String>(view.findViewById(R.id.CONTACT_name),
                getString(R.string.transition_name_name)),
        new Pair<View, String>(view.findViewById(R.id.CONTACT_phone),
                getString(R.string.transition_name_phone))
);
ActivityCompat.startActivity(HomeActivity.this, intent, options.toBundle());

I tried to pass the Activity Object to the RVAdapter in its constructor method, but it only resulted in NullPointerExceptions.

Here's my RVAdapter code:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.AppVH>{


ArrayList<App> apps;

@Override
public AppVH onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
    return new AppVH(v);
}

@Override
public void onBindViewHolder(AppVH holder, int position) {
    holder.name.setText(apps.get(position).getName());
    holder.artist.setText(apps.get(position).getArtist());
    String p = "";
    if(apps.get(position).getPrice()==0.0) p="Free";
    else p= "$"+apps.get(position).getPrice()+" "+apps.get(position).getCurrency();
    holder.price.setText(p);
    Picasso.with(AppListActivity.context).load(apps.get(position).getUrlImLarge()).into(holder.icon);
}

@Override
public int getItemCount() {
    return apps.size();
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

RecyclerViewAdapter(ArrayList<App> applications){
    this.apps = applications;
}

// Clean all elements of the recycler
public void clear() {
    apps.clear();
    notifyDataSetChanged();
}

// Add a list of items
public void addAll(ArrayList<App> list) {
    apps.addAll(list);
    notifyDataSetChanged();
}

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

    CardView cv;
    TextView name;
    TextView artist;
    TextView price;
    ImageView icon;
    private final Context c;

    public AppVH(View itemView) {
        super(itemView);
        cv = (CardView) itemView.findViewById(R.id.cardview);
        name = (TextView) itemView.findViewById(R.id.app_name);
        artist = (TextView) itemView.findViewById(R.id.app_artist);
        price = (TextView) itemView.findViewById(R.id.app_price);
        icon = (ImageView) itemView.findViewById(R.id.app_icon);
        itemView.setOnClickListener(this);
        c = itemView.getContext();
    }

    @Override
    public void onClick(View v) {
        final Intent intent;
        Log.d("Debugtext","Card with position " + getAdapterPosition() + " was touched.");
        intent = new Intent(c, AppDetailActivity.class);
        intent.putExtra("app",apps.get(getAdapterPosition()));
        c.startActivity(intent);
    }
}
}

Here's how I add the adapter to the RecyclerView in my "HomeActivity".

RecyclerView rv = (RecyclerView) findViewById(R.id.recycler_view);

    rv.setHasFixedSize(true);
    GridLayoutManager gridlm = new GridLayoutManager(getApplicationContext(),columns);
    rv.setLayoutManager(gridlm);
    rvadapter = new RecyclerViewAdapter(apps);
    rv.setAdapter(rvadapter);

Is there an easy way to call the ActivityCompat.startActivity(...) method from within the Adapter?

Expiate answered 7/2, 2016 at 19:52 Comment(0)
E
9

So, I did a very simple thing: I casted the context as an activity. Wow.

        @Override
        public void onClick(View v) {
            final Intent intent;
            //Opens the AppDetailActivity showing the selected App Card
            //Log.d("Debugtext","Card with position " + getAdapterPosition() + " was touched.");
            intent = new Intent(c, AppDetailActivity.class);
            intent.putExtra("app",apps.get(getAdapterPosition()));

            ActivityOptionsCompat options = ActivityOptionsCompat.
                    makeSceneTransitionAnimation((Activity)c, (View)cv, "appcard");
            c.startActivity(intent, options.toBundle());
        }
Expiate answered 9/2, 2016 at 14:54 Comment(2)
I accepted this answer as I received no comments and a couple of upvotes. I'm not sure whether this is the better practice here, but it worked for me.Expiate
@ArpitPatel ArrayList<App> apps;Expiate
V
1
ActivityOptions options  = ActivityOptions.makeSceneTransitionAnimation((Activity) mContext);

Note: mContext was initialized in the recycler adapter constructor.

Vender answered 29/5, 2019 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.