How to go back to same recyclerview item position - android

I am using a recyclerview which loads items from firebase database. On clicking the item, a new activity opens and displays the data. But when I return to the recyclerview activity, it opens from the top and not from the position I left from. How to implement opening activity from the left position.
The onBindViewHolder goes like this:
#Override
protected void onBindViewHolder(#NonNull myViewHolder holder, int position, #NonNull MainModel model) {
holder.headi.setText(model.getHeading());
holder.arti.setText(model.getArticle());
holder.date.setText(model.getPublishedDate());
holder.user.setText(model.getUsername());
Glide.with(holder.img.getContext())
.load(model.getImageUrl())
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(holder.img);
holder.relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent= new Intent(context, Read.class);
intent.putExtra("Heading",model.getHeading());
intent.putExtra("Article",model.getArticle());
intent.putExtra("ImageUrl",model.getImageUrl());
intent.putExtra("PublishedDate", model.getPublishedDate());
intent.putExtra("PublishedBy", model.getUsername());
context.startActivity(intent);
((Activity)context).finish();
}
});
}
The back button in the Read activity goes like this:
public void back(View view)
{
if (fAuth.getCurrentUser()!=null)
{
i= new Intent(Read.this,Scroll2.class);
}
else{
i= new Intent(Read.this,Scroll.class);
}
startActivity(i);
finish();
}

First store the visible top item position in onPause() of your Activity
int lastPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
Save it by using savedInstanceState and restore in onResume() by using
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(lastPosition,0);

Related

Using setOnClickListener on RecyclerView Fragment to move to another activity

I want to (1) pass the position variable and (2) open a new activity when an item is clicked.
I found that I need to create Activity variable in order to use Intent, and I also found that I can use putExtra to pass the position variable.
Although the below code works for regular_activity.java, it does not work for fragment.java. It completely shuts down the app when I open this fragment.
#Override
public void onClick(View view) {
Intent int_detail = new Intent(activity, bottom_nav_search_details.class);
int_detail.putExtra("position", position);
activity.startActivity(int_detail); }
Just in case anyone finds useful, here is longer lines of codes. When I remove the above part (Intent part), everything works--Log successfully shows different positions when I click different items.
private Activity activity;
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, final int position) {
final ExampleItem currentItem = exampleList.get(position);
holder.imageView.setImageResource(currentItem.getImageResource());
holder.textView1.setText(currentItem.getText1());
holder.parentLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.i(TAG, "Clicked " + position);
Intent int_detail = new Intent(activity, bottom_nav_search_details.class);
int_detail.putExtra("position", position);
activity.startActivity(int_detail);
}
});
}

Card View Click on card to move to next activity

I am working on a project in android and i just learn about card view class.
I made a card who generates a toast when user clicks on it.
But i also want my card to call another activity when user clicks on it.
I am posting part of my code below.
btnProceed.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showToast("Proceed to the next step");
Intent intent = new Intent(MyLocationUsingLocationAPI.this, click_picture.class);
startActivity(intent);
}
});
I have made changes in my code as you said but when i click on proceed button my app crashes.What is wrong with code?
the main idea here is to define your actionClickListener
1. create a custom recycleView Adapter
public class AdapterCustomList extends RecyclerView.Adapter<RecyclerView.ViewHolder>
2. define onItemClickListener interface
public interface OnItemClickListener {
void onItemClick( whateverArgsYouWant );
}
3. make an attribute of the interface and define a setter for it
private OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mOnItemClickListener = mItemClickListener;
}
4. append a listener to each item while its created in the adapter class
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
...
OriginalViewHolder vItem = (OriginalViewHolder) holder;
vItem.baseCard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick( whateverArgsYouWant );
}
}
});
}
this method will be called when items of recycle view is created (in case you use card view inside a recycle view)
5. use your onClickListener in the Activity you want
AdapterCustomList mAdapter = new AdapterCustomList (getActivity(), recyclerView,yourListItemsHere));
recyclerView.setAdapter(mAdapter);
// on item list clicked
mAdapter.setOnItemClickListener(new AdapterPostList.OnItemClickListener() {
#Override
public void onItemClick( whateverArgsYouWant ) {
...
statements
...
}
});

How can I find which item in which RecyclerView was tapped?

I currently have a layout that has 4 horizontal RecyclerViews in succession. They all display how they are supposed to. However now I want to be able to click on a specific item in a RecyclerView and have it bring up more information. I have the click working with a single RecyclerView by overriding the onItemClick method. The only problem is I have 4 and I can't tell which RecyclerView is being clicked.
This is how I currently do it with one RecyclerView.
#Override
public void onItemClick(View view, int position) {
Intent intent = new Intent(this, DetailedInfo.class);
intent.putExtra(DETAILED_INFO, customAdapter.getVideo(position));
startActivity(intent);
}
I have all of the RecyclerViews in a list so I can grab a specific one like this:
((VideoAdapter) recyclerViewList.get(1).getAdapter()).getVideo(position));
I just don't know how to find the one that was actually clicked.
you could do this inside adapter. pass your activity as context to your adapter.
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, DetailedInfo.class);
intent.putExtra(DETAILED_INFO, getVideo(position));
startActivity(intent);
}
});
}

How to open a new activity when an item is clicked in Firebase RecyclerView

I have used FirebaseRecyclerView from Firebase UI to show a list of data. Now when I click on one of the items, depending on the ID of the item in database, I want to open DetailActivity. How can I get Firebase generated ID(eg: -KRAVjAhr6A_spgJZEET) in populateViewHolder.
Query queryRef = mDatabase.child("user-tickets").child(userId);
FirebaseRecyclerAdapter<Ticket, TicketViewHolder> adapter = new FirebaseRecyclerAdapter<Ticket, TicketViewHolder>(
Ticket.class,
R.layout.item_ticket,
TicketViewHolder.class,
queryRef
) {
#Override
protected void populateViewHolder(TicketViewHolder viewHolder, Ticket model, int position) {
//want to get Id here for this record
}
};
you must put your data in a ArrayList then on your populateView attche onClickListener on your view and pass the id that is clicked using a Bundle, remember you have set your view to clickable="true" on your xml if its not a button.
viewHolder.container.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString("ID_KEY", items.get(position).getId());
Intent intent = new Intent(context.getApplicationContext(), DetailActivity.class);
intent.putExtra("EXTRAS_KEY", bundle);
context.startActivity(intent);
}
});
I have implemented one TouchListener for each Item click, in the onClick callback, depending on the position, you can get the key as shown:
mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(this, mRecyclerView, new RecyclerClickListener() {
#Override
public void onClick(View view, int position) {
String key = adapter.getRef(position).getKey();
}
#Override
public void onLongClick(View view, int position) {
}
}));
Credit: How to get obj key from FirebaseListAdapter on Item Click. FirebaseUI

RecyclerView getAdapterPosition() returns -1 on a callback so I can't show the new appearance for the item

Each item on my RecyclerView has a button that has three states: OPEN, LOADING, and CLOSED.
Initially all the buttons are in the OPEN state. When a button is clicked, the state is changed to LOADING and a network call is performed in the background. After the network call succeeds, the button state should be changed to CLOSED.
So in my adapter I used the following:
holder.button.setOnClickListener(v -> {
holder.state = LOADING;
notifyItemChanged(holder.getAdapterPosition()); /* 1 */
callNetwork(..., () -> {
/* this is the callback that runs on the main thread */
holder.state = CLOSED;
notifyItemChanged(holder.getAdapterPosition()); /* 2 */
});
});
The LOADING state is always visualized correctly at /* 1 */ because getAdapterPosition() gives me the correct position.
However, the CLOSED state of the button is never visualized, because getAdapterPosition at /* 2 */ always returns -1.
I might understand getAdapterPosition() wrongly in this case.
How do I refresh the appearance of an item on a callback?
From the docs:
Note that if you've called notifyDataSetChanged(), until the next
layout pass, the return value of this method will be NO_POSITION
NO_POSITION is a constant whose value is -1. This might explain why you are getting a return value of -1 here.
In any case, why don't you find the position of the model in the underlying dataset and then call notifyItemChanged(int position)? You could save the model as a field in the holder.
For example:
public class MyHolder extends RecyclerView.ViewHolder {
private Model mMyModel;
public MyHolder(Model myModel) {
mMyModel = myModel;
}
public Model getMyModel() {
return mMyModel;
}
}
holder.button.setOnClickListener(v -> {
holder.state = LOADING;
notifyItemChanged(holder.getAdapterPosition());
callNetwork(..., () -> {
/* this is the callback that runs on the main thread */
holder.state = CLOSED;
int position = myList.indexOf(holder.getMyModel());
notifyItemChanged(position);
});
});
Alternatively you can just ignore if the position is -1, like this:
holder.button.setOnClickListener(v -> {
holder.state = LOADING;
int preNetworkCallPosition = holder.getAdapterPosition();
if (preNetworkCallPosition != RecyclerView.NO_POSITION) {
notifyItemChanged(preNetworkCallPosition);
}
callNetwork(..., () -> {
/* this is the callback that runs on the main thread */
holder.state = CLOSED;
int postNetworkCallPosition = holder.getAdapterPosition();
if (postNetworkCallPosition != RecyclerView.NO_POSITION) {
notifyItemChanged(postNetworkCallPosition);
}
});
});
getAdapterPosition(); It will always return -1 when recyclerview makes layout calculations. You are calling this methods inside ViewHolder.. It means RecyclerView is doing calculations.
If you need position inside click actions of view, call it in the public void onClick(final View v) method for example:
"#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
final Students user = mUsers.get(position);
holder.Name.setText(user.getFullname());
holder.Index.setText(user.getIndex_number());
if (user.getThumbnail().equals("default")) {
holder.profile_image.setImageResource(R.drawable.profile_pic);
} else {
Picasso.get().load(user.getThumbnail())
.placeholder(R.drawable.profile_pic)
.into(holder.profile_image);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
**list_user_id = mUsers.get(position).getId();**
Intent Sub = new Intent(mContext, UserProfileActivity.class);
Sub.putExtra("user_id1", list_user_id);
mContext.startActivity(Sub);
BUT NOT
getAdapterPosition(); It will always return -1 when recyclerview makes layout calculations. You are calling this methods inside ViewHolder.. It means RecyclerView is doing calculations.
If you need position inside click actions of view, call it in the public void onClick(final View v) method for example:
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
final Students user = mUsers.get(position);
holder.Name.setText(user.getFullname());
holder.Index.setText(user.getIndex_number());
**list_user_id = mUsers.get(position).getId();**
if (user.getThumbnail().equals("default")) {
holder.profile_image.setImageResource(R.drawable.profile_pic);
} else {
Picasso.get().load(user.getThumbnail())
.placeholder(R.drawable.profile_pic)
.into(holder.profile_image);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
Intent Sub = new Intent(mContext, UserProfileActivity.class);
Sub.putExtra("user_id1", list_user_id);
mContext.startActivity(Sub);

Categories

Resources