Update the recycler view textview? - android

I have a RecyclerView defined in my android project. The Adapter for the RecyclerView is as follows
public class CustomAdapter1 extends RecyclerView.Adapter<CustomAdapter1.MyViewHolder> {
private Fragment1 myFrag;
private ArrayList<DataModel1> dataSet;
DBHandler db;
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView butAccept,butReject;
TextView nick,stat,tit,cat,desc,dt;
public CardView cardView;
public MyViewHolder(View itemView) {
super(itemView);
this.nick = (TextView) itemView.findViewById(R.id.nick);
this.stat = (TextView) itemView.findViewById(R.id.stat);
this.tit = (TextView) itemView.findViewById(R.id.tit);
this.cat = (TextView) itemView.findViewById(R.id.cat);
this.desc = (TextView) itemView.findViewById(R.id.desc);
this.dt = (TextView) itemView.findViewById(R.id.dt);
this.butAccept = (TextView)itemView.findViewById(R.id.accept_textview);
cardView = (CardView) itemView.findViewById(R.id.card_view);
cardView.setOnClickListener(this);
butAccept.setOnClickListener(this);
db = new DBHandler(itemView.getContext());
}
#Override
public void onClick(View v) {
if( v.getId() == butAccept.getId()){
String x = String.valueOf(dataSet.get(getAdapterPosition()).getMeetId());
myFrag.showToast(x);
}
}
}
public CustomAdapter1(ArrayList<DataModel1> data,Fragment1 frag) {
this.dataSet = data;
myFrag = frag;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardfrag1, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
#Override
public void onBindViewHolder(final MyViewHolder holder,final int listPosition) {
TextView nick = holder.nick;
TextView stat = holder.stat;
TextView tit = holder.tit;
TextView cat = holder.cat;
TextView desc = holder.desc;
TextView dt= holder.dt;
nick.setText(dataSet.get(listPosition).getNick());
stat.setText(dataSet.get(listPosition).getStat());
tit.setText(dataSet.get(listPosition).getTit());
cat.setText(dataSet.get(listPosition).getCat());
desc.setText(dataSet.get(listPosition).getDesc());
dt.setText(dataSet.get(listPosition).getDt());
}
#Override
public int getItemCount() {
return dataSet.size();
}
}
The final TextView butAccept has dynamic values.I have an internal DB that has the column Status. When the value of the Status is 1 I need to change the text that is being displayed in the TextView butAccept.
How should I do this? Should I write a function in my CustomAdapter, or in the fragment in which I am using the adapter?
In my Fragment I have a function :
private void checkTheAcceptStatus(int x){
int status = db.getMeetingStatus(x);
Toast.makeText(getActivity(),String.valueOf(status),Toast.LENGTH_SHORT).show();
if(status == 1){
}
}
This function is being called everytime a new item is added to the adapter. The internal DB is being queried correctly and if the value of Status is being returned. If the value is 1 what should I do?
I saw this question, but this is unclear and I was unable to come to any conclusion from this.

If I understood correctly every row in your list has this accept button. So in your onBindViewHolder() you cant set the buttons text depending on the state of your status variable. When you detect changes in your db you can use the various notify methods provided depending on your needs: notifyItemChanged(...), notifyItemRangeChanged(...), notifyItemAdded(...), notifyItemRemoved(...) etc. Your onBindViewHolder should look something like this:
#Override
public void onBindViewHolder(final ViewHolder vh, int position) {
if(dataSet.get(position).getStatus() == 1){
vh.butAccept.setText("Your status 1 case text here");
} else {
vh.butAccept.setText("Your status not 1 case text here");
}
}
Also you can just use notifyDataSetChanged() if you want to refresh the whole list, but the methods above are more efficient.

Related

update an item with animation in RecyclerView Adapter

I am using RcyclerView adapter wich holding a chat messages list.
every time a message added to firebase I am using the 'onChildAdded' listener to update the adapter list. I also want to update certain messages by adding their background a changing color-animation.
the problem is I don't know how to access the position of specific messages in my adapter.
this is my chatListadapter:
class ChatListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<ChatMessage> msgList;
private static final int VIEW_TYPE_MESSAGE_LEFT = 1;
private static final int VIEW_TYPE_MESSAGE_RIGHT = 2;
private DataReferences DB;
ChatListAdapter(List<ChatMessage> msgList) {
this.msgList = msgList;
}
#Override
public int getItemCount() {
return msgList.size();
}
#Override
public int getItemViewType(int position) {
DB = DataReferences.getInstance();
ChatMessage msg = msgList.get(position);
if (!msg.uid.equals(DB.uid)) {
return VIEW_TYPE_MESSAGE_LEFT;
}
} else
return VIEW_TYPE_MESSAGE_RIGHT;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == VIEW_TYPE_MESSAGE_LEFT) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_received, parent, false);
return new LeftViewHolder(view);
} else {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_sent, parent, false);
return new RightViewHolder(view);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int
position) {
ChatMessage msg = msgList.get(position);
if (msg.critic)
switch (holder.getItemViewType()) {
case VIEW_TYPE_MESSAGE_LEFT:
((LeftViewHolder) holder).bind(msg);
break;
case VIEW_TYPE_MESSAGE_RIGHT:
((RightViewHolder) holder).bind(msg);
break;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
private class LeftViewHolder extends RecyclerView.ViewHolder {
TextView messageText, timeText, nameText;
public LeftViewHolder(View itemView) {
super(itemView);
timeText = (TextView) itemView.findViewById(R.id.text_message_time);
nameText = (TextView) itemView.findViewById(R.id.text_message_name);
messageText = (TextView)
itemView.findViewById(R.id.text_message_body);
}
void bind(ChatMessage message) {
messageText.setText(message.getMsg());
timeText.setText(message.getTime());
nameText.setText(message.UserName);
}
}
private class RightViewHolder extends RecyclerView.ViewHolder {
TextView messageText, timeText;
public RightViewHolder(View itemView) {
super(itemView);
timeText = (TextView) itemView.findViewById(R.id.text_message_time);
messageText = (TextView)
itemView.findViewById(R.id.text_message_body);
}
void bind(ChatMessage message) {
messageText.setText(message.getMsg());
timeText.setText(message.getTime());
}
}
}
I suggest you to used FirebaseRecyclerAdapter which come in FirebaseUI library (https://github.com/firebase/FirebaseUI-Android/blob/master/database/README.md). It makes handling data in RecyclerView become easier.
To make adapter update specific item. In populateViewHolder of FirebaseRecyclerAdapter you could do something like this (suppose you want to change message background if the message has been read)
override fun populateViewHolder(viewHolder: FieldViewHolder?, model: Message, position: Int) {
if(model.isRead) {
viewholder.updateBackground()
}
}
If you use plain RecyclerView it might need some effort to find specific position and update UI accordingly.
Hope it's help.

notifyDataSetChanged not working on when adapter change

I am getting data from server and then parsing it and storing it in a List. I am using this list for the RecyclerView's adapter. I am using Fragments.
I extended
RecyclerView.Adapter<RecyclerView.ViewHolder>
this my complete adapter class
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> {
private List<ProductModel> list;
ItemClickListener itemClickListener;
public GridAdapter(List<ProductModel> list, ItemClickListener itemClickListener) {
this.list = list;
this.itemClickListener = itemClickListener;
}
public void update(int position,ProductModel pm){
Log.v("update adapter",position+"");
list.set(position,pm);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final ProductModel cp = list.get(position);
holder.tvName.setText(cp.name);
holder.tvPrice.setText(cp.price);
holder.ratingBar.setRating(cp.rate);
Log.v("grid",cp.id + "=="+ cp.checked);
if(cp.checked==1){
holder.imgCheck.setVisibility(View.VISIBLE);
}else{
holder.imgCheck.setVisibility(View.GONE);
}
LayerDrawable stars = (LayerDrawable) holder.ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);
holder.lnrItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemClickListener.onItemClick(cp,position);
}
});
}
#Override
public int getItemCount() {
return list.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName, tvPrice;
ImageView imgMenu, imgCheck;
LinearLayout lnrItem;
RatingBar ratingBar;
public ViewHolder(View itemView) {
super(itemView);
lnrItem = itemView.findViewById(R.id.lnrItem);
imgMenu = itemView.findViewById(R.id.imgMenu);
imgCheck = itemView.findViewById(R.id.imgCheck);
tvName = itemView.findViewById(R.id.tvName);
ratingBar = itemView.findViewById(R.id.ratingBar);
tvPrice = itemView.findViewById(R.id.tvPrice);
}
}
}
and in fragment activity i use this code to load adapter to recyclerview
public void fillListProduct(List<ProductModel> mItems) { //method for load adapter for the first time
mAdapterGrid = new GridAdapter(mItems,this);
recGrid.setAdapter(mAdapterGrid);
}
void update(){ //method to change checked value
mAdapterGrid.update(cp.row,cp);
mAdapterGrid.notifyDataSetChanged();
}
in my custom adapter i have 3 variable lets call id, name, checked, everything work properly, in first load i set 0 as default value for checked, in my scenario user can change checked value by tap the row of recycleview.
my question is, when user tap desire row then checked will change from 0 to 1 and display it to recycelview, i already use notifydatasetchange() but not working.
Please help.
thanks
Try to remove mAdapterGrid.notifyDataSetChanged();
and modify this function in your adpater:
public void update(int position,ProductModel pm){
Log.v("update adapter",position+"");
list.set(position,pm);
notifyItemChanged(position);
}

Multiple edittext in Recyclerview

We're making an app which makes it possible to share group costs.
In order to do this you can select people with whom you would like to share the next bill.
I made a sort of "list-view-item" which contains a "Debit" and "Credit" field for each user and added these items to a Recyclerview according to how many people are sharing the payment.
However, now i am trying to read all the values that were entered in these edittexts but i don't know how.
The code that generates the the list in the recyclerview is the following:
private void initRecyclerView() {
rvTransactions = (RecyclerView) findViewById(R.id.rvTransactions);
lmTransactions = new LinearLayoutManager(this);
rvTransactions.setLayoutManager(lmTransactions);
transactionAdapter = new RecyclerView.Adapter<CustomViewHolder>() {
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_transaction, viewGroup, false);
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(CustomViewHolder viewHolder, int i) {
viewHolder.noticeSubject.setText(participatingUsers.get(i).getFirstname() + " " + participatingUsers.get(i).getLastname());
}
#Override
public int getItemCount() {
return participatingUsers.size();
}
};
rvTransactions.setAdapter(transactionAdapter);
}
private class CustomViewHolder extends RecyclerView.ViewHolder {
private TextView noticeSubject;
private EditText userDebt,userCredit;
public CustomViewHolder(View itemView) {
super(itemView);
noticeSubject = (TextView) itemView.findViewById(R.id.tvTransactionUser);
userCredit = (EditText) findViewById(R.id.etTransactionPayed);
userDebt = (EditText) findViewById(R.id.etTransactionOwes);
}
}
The participatingUsers object is a list of users.
A user has the following fields:
private int id;
private boolean isSelected;
private String firstname, lastname, email, password, api_key, creditcardnumber;
I want to be able to get the values that were entered in the edittexts "payed" and "owes" for all the users.
Loop over the childCount of the RecyclerView and check to make sure the item your reading is of type CustomViewHolder, cast to that type and read EditText Values. Something like:
public void printAllEditTextValues(){
int childCount = rvTransactions.getChildCount();
for(int i = 0; i < childCount; i++){
if(rvTransactions.findViewHolderForLayoutPosition(i) instanceOf CustomViewHolder){
CustomViewHolder childHolder = (CustomViewHolder) rvTransactions.findViewHolderForLayoutPosition(i);
Log.d("EDIT_TEXT_1" , childHolder.userCredit.getText().toString());
Log.d("EDIT_TEXT_2" , childHolder.userDebt.getText().toString());
}
}
your adapter is missing thie itemView.findViewById(int) for your edit text, use:
private class CustomViewHolder extends RecyclerView.ViewHolder {
private TextView noticeSubject;
private EditText userDebt,userCredit;
public CustomViewHolder(View itemView) {
super(itemView);
noticeSubject = (TextView) itemView.findViewById(R.id.tvTransactionUser);
userCredit = (EditText) itemView.findViewById(R.id.etTransactionPayed);
userDebt = (EditText) itemView.findViewById(R.id.etTransactionOwes);
}
}

Update progressbar in Recyclerview

I want to update a progressbar in a recyclerview item.
Now I have no idea, how to get the progressbar within an item and update it from another class, which isn't connected in anyway with this adapter.
Here's my code:
public class TransmissionAdapter extends RecyclerView.Adapter<TransmissionAdapter.ViewHolderUI> {
public static class ViewHolderUI extends RecyclerView.ViewHolder{
ImageView fileTypeImage;
TextView fileName;
TextView progressDescription;
TextView timeAgoTrans;
ProgressBar uploadProgess;
public ViewHolderUI(View itemView) {
super(itemView);
fileTypeImage = (ImageView) itemView.findViewById(R.id.file_type_image);
fileName = (TextView) itemView.findViewById(R.id.file_name);
progressDescription = (TextView) itemView.findViewById(R.id.progress_description);
timeAgoTrans = (TextView) itemView.findViewById(R.id.time_ago_trans);
uploadProgess = (ProgressBar) itemView.findViewById(R.id.progress_bar_transmission);
}
}
#Override
public ViewHolderUI onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_view, null);
return new ViewHolderUI(itemView);
}
#Override
public void onBindViewHolder(ViewHolderUI holder, int position) {
holder.fileName.setText(TransmissionsView.itemTexte.get(position));
}
#Override
public int getItemCount() {
return TransmissionsView.itemTexte.size();
}
}
I tried to put the progress in an arraylist and update the progress in the recyclerlist using notifyDataSetChanged and set the current progress in "onBindViewHolder" method. But if the progressbar is to fast the UI Thread skipped frames, so is this the right way?!

How to add OnClickListner to CardView?

I am working with RecyclerView and CardView. I want to attach OnClickListner to each card. I tried with many answers available on stackoverflow, but they are not working for me. So far I have tried -
public class SubjectAdapter extends RecyclerView.Adapter<SubjectAdapter.ViewHolder> implements View.OnClickListener,
View.OnLongClickListener{
private static final String LOGCAT = "SubjectAdapter";
private final Context mContext;
List<Subject> SubjectsList;
public SubjectAdapter(Context context) {
super();
this.mContext = context;
SQLiteDatabase.loadLibs(mContext);
DBHelper myDbHelper = new DBHelper(mContext);
SubjectsList = new ArrayList<Subject>();
SubjectsList = myDbHelper.getAllSubjects();
myDbHelper.close();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.subject_cardview_row, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
// Below two lines are NOT working
viewHolder.tvSubjectName.setOnClickListener(this);
//viewHolder.setOnClickListener(this);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
Subject subject = SubjectsList.get(i);
viewHolder.tvSubjectName.setText(subject.getSubject_Name());
viewHolder.tvCounts.setText(String.valueOf(subject.getSubject_Number_of_Questions()));
// Below two lines are NOT working
viewHolder.tvSubjectName.setOnClickListener(this);
//viewHolder.setOnClickListener(this);
}
#Override
public int getItemCount() {
return SubjectsList.size();
}
#Override
public void onClick(View v) {
// It's not working either
ViewHolder holder = (ViewHolder) v.getTag();
int position = holder.getPosition();
if (v.getId() == holder.tvSubjectName.getId()){
Log.d(LOGCAT, "tvSubjectName onClick at" + position);
//Toast.makeText(mContext, "tvSubjectName onClick at" + position, Toast.LENGTH_LONG).show();
} else {
Log.d(LOGCAT, "RecyclerView Item onClick at " + position);
//Toast.makeText(mContext, "RecyclerView Item onClick at " + position, Toast.LENGTH_LONG).show();
}
}
#Override
public boolean onLongClick(View v) {
return false;
}
class ViewHolder extends RecyclerView.ViewHolder {
public TextView tvSubjectName;
public TextView tvCounts;
public ViewHolder(View itemView) {
super(itemView);
tvSubjectName = (TextView) itemView.findViewById(R.id.tv_subject_name);
tvCounts = (TextView) itemView.findViewById(R.id.tv_text_counts);
}
}
}
As one can see, I have tried setOnClickListener with both onCreateViewHolder and onBindViewHolder, also as separate onClick, but none of them seems to be working for me. So, I want to know, How to add OnClickListner to CardView?
View returned by onClick does not necessarily correspond to View row hierarchy of the recycler view.
I think you should modify onBindViewHolder with
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
final Subject subject = SubjectsList.get(i);
viewHolder.tvSubjectName.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Log.d(LOGCAT, "tvSubjectName onClick at" + i);
// etc
}
});
...
}
If you use long click then replace View.OnClickListener with View.OnLongClickListener and onClick with onLongClick.
This worked for me !
Put the setOnClickListener-method inside the constructor of your ViewHolder class.
class ViewHolder extends RecyclerView.ViewHolder
{
public TextView tvSubjectName;
public TextView tvCounts;
public ViewHolder(View itemView)
{
super(itemView);
tvSubjectName = (TextView) itemView.findViewById(R.id.tv_subject_name);
tvCounts = (TextView) itemView.findViewById(R.id.tv_text_counts);
itemView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//write here the code for wathever you want to do with a card
//...
}
});
}
}
Check out Lucas Rocha's new TwoWayView API.
TwoWayLayoutManager is a simple API on top of LayoutManager that does all the laborious work for you so that you can focus on how the child views are measured, placed, and detached from the RecyclerView.
Follow his site and implementation of the API is relatively simple and might help you through some of the difficult complexities RecyclerView and CardView pose.
http://lucasr.org/2014/07/31/the-new-twowayview/
Set OnClickListener to itemView in RecyclerView.ViewHolder constructor, also you can fetch position of cardView using getAdapterPosition() method which can help you to pass the data to new activity using putExtra method of intent. doc for getAdapterPosition method
`
class ViewHolder extends RecyclerView.ViewHolder
{
public TextView tvSubjectName;
public TextView tvCounts;
public ViewHolder(View itemView)
{
super(itemView);
tvSubjectName = (TextView) itemView.findViewById(R.id.tv_subject_name);
tvCounts = (TextView) itemView.findViewById(R.id.tv_text_counts);
itemView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
int position = getAdapterPosition();
// use position to put extra data
}
});
}
`
If you really want to implement onclick listener then do the following
add a View object in your ViewHolderClass and initialize it to the itemView recieved in the constructor
2.setOnClickListener to the view object you declared(in ViewHolder) onBindViewHolder in the Adapter class
this will work for the entire cardView

Categories

Resources