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);
}
}
Related
App Screen
I want to automatically get the sum of the items once added in the recycler view and at the same time get the sum of the items when the Quantity changes and when an item from the recyclerView is removed. I am new in Android, and I cannot think of any way to achieve this. I am thinking something like the code below, but I don't know how to implement it.
TextView ProductPrice = itemView.findViewById(R.id.productPricelbl);
TextView QTY = itemView.findViewById(R.id.Quantity);
Int total;
private void GetTotal(){
total += Integer.parseInt(ProductPrice.getText().toString()) * Integer.parseInt(QTY .getText().toString())
}
I am using a custom adapter for my recycler view with the code below
public class ListViewAdapter extends RecyclerView.Adapter<DemoVH>{
ArrayList<ProductListViewModel> productList;
Context mContext;
public ListViewAdapter(ArrayList<ProductListViewModel> productList, Context context) {
this.productList = productList;
this.mContext = context;
}
#NonNull
#Override
public DemoVH onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view_row,parent,false);
return new DemoVH(view).linkadapter(this);
}
#Override
public void onBindViewHolder(#NonNull DemoVH holder, int position) {
final ProductListViewModel productListViewModel = productList.get(position);
holder.Product_Name.setText(productListViewModel.getProductName());
holder.Product_Barcode.setText(productListViewModel.getProductBarcode());
holder.Product_Price.setText(productListViewModel.getProductPrice());
}
#Override
public int getItemCount() {
return productList.size();
}
}
class DemoVH extends RecyclerView.ViewHolder{
TextView Product_Name;
TextView Product_Barcode;
TextView Product_Price;
TextView Product_QTY;
ImageView addQTY;
ImageView lessQTY;
private ListViewAdapter myAdapter;
int Quantity = 1;
public DemoVH(#NonNull View itemView) {
super(itemView);
Product_Name = itemView.findViewById(R.id.ProductNameLbl);
Product_Barcode = itemView.findViewById(R.id.ProductBarcodeLbl);
Product_Price = itemView.findViewById(R.id.ProductPriceLbl);
Product_QTY = itemView.findViewById(R.id.QTYLbl);
addQTY = itemView.findViewById(R.id.AddQTYBtn);
lessQTY = itemView.findViewById(R.id.lessQTYBtn);
itemView.findViewById(R.id.RemoveBtn).setOnClickListener(view -> {
myAdapter.productList.remove(getAdapterPosition());
myAdapter.notifyItemRemoved(getAdapterPosition());
});
addQTY.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Quantity = Quantity+=1;
Product_QTY.setText(String.valueOf(Quantity));
}
});
lessQTY.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(Quantity == 1){
Product_QTY.setText("1");
}else{
Quantity = Quantity-=1;
Product_QTY.setText(String.valueOf(Quantity));
}
}
});
}
public DemoVH linkadapter(ListViewAdapter adapter){
myAdapter = adapter;
return this;
}
}
You can take a global variable in recycler view adapter and keep adding the amount in that variable in onBindViewHolder().
And when any item is increased or decreased or removed you can add or decrease that amount from that global variable.
I am able to access the marks but want to store them at their respective locations only (meaning every student gets his marks and not someone else's)
This is how my Recycler View looks
Firebase Data Structure
I've got to the point where the data is being collected from a single Edit Text but cannot get its way to the right Student node.
Inside onBindViewHolder method
myViewHolder.btnUpdateMarks.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final View v = view;
Result r = new Result();
r.setMarks_scored(myViewHolder.etEnterMarks.getText().toString());
String text = myViewHolder.etEnterMarks.getText().toString();
myViewHolder.updateValue(text,r,v);
}
});
UpdateValue function
public void updateValue(String text, Result r, final View v){
final View view = v;
final Result result = r;
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
final DatabaseReference marksRef = firebaseDatabase.getReference().child("Batches").child("BATCH1");
marksRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot demo : dataSnapshot.getChildren()){
marksRef.child("Results").child("-LfB2Jz7vrbv0vMyYA02").setValue(result);
}
}
The marksRef is being hardcoded which shouldn't be the way.. I am not finding any possible way of getting those child variables inside the adapter class
Anyone with any better soultion to solving the problem please help!
Sorry for the bad communication please mention if anything is missing
-----EDIT---------
I have solved the problem by using a string array inside my activity class and passing it to the constructor of my RecyclerViewAdapter..
The problem is whenever i am typing anything in the edit text of 2nd or 3rd item after clicking the update button the cursor is automatically going to the first item's edittext
This is my adapter class
public class MarksListAdapter extends RecyclerView.Adapter<MarksListAdapter.MyViewHolder> {
Context context;
ArrayList<Result> resultArrayList;
String[] firebaseChildValues = new String[2];
String student_uid;
public MarksListAdapter(Context c, ArrayList<Result> p, String[] child) {
context = c;
resultArrayList = p;
firebaseChildValues = child;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.marks_list, viewGroup, false));
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, int i) {
myViewHolder.tvStudentName.setText(resultArrayList.get(i).getName());
myViewHolder.tvOutOf_List.setText(" / " + resultArrayList.get(i).getTotal_marks());
myViewHolder.etEnterMarks.setText(resultArrayList.get(i).getMarks_scored());
myViewHolder.tvStudentUid.setText(resultArrayList.get(i).getStudent_uid());
myViewHolder.btnUpdateMarks.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final View v = view;
student_uid = myViewHolder.tvStudentUid.getText().toString();
Result r = new Result();
r.setMarks_scored(myViewHolder.etEnterMarks.getText().toString());
String text = myViewHolder.etEnterMarks.getText().toString();
myViewHolder.updateValue(text, r, v, firebaseChildValues, student_uid);
}
});
}
#Override
public int getItemCount() {
return resultArrayList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvStudentName, tvOutOf_List, tvStudentUid;
EditText etEnterMarks;
Button btnUpdateMarks;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
tvStudentName = (TextView) itemView.findViewById(R.id.tvStudentName);
etEnterMarks = (EditText) itemView.findViewById(R.id.etEnterMarks);
tvOutOf_List = (TextView) itemView.findViewById(R.id.tvOutOf_List);
tvStudentUid = (TextView) itemView.findViewById(R.id.tvStudentUid);
btnUpdateMarks = (Button) itemView.findViewById(R.id.btnUpdateMarks);
}
public void updateValue(String text, Result r, final View v, String[] child, String suid) {
final View view = v;
final Result result = r;
String[] firebaseChildValues = child;
String resultValue = text;
String studentUid = suid;
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
final DatabaseReference marksRef = firebaseDatabase.getReference().child("Batches").child(firebaseChildValues[0]).child(studentUid).child("Results").child(firebaseChildValues[1]);
marksRef.child("marks_scored").setValue(resultValue).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d("TAG_MARKS", marksRef.toString());
}
}
});
}
}
}
Remove btnUpdateMarks.setOnClickListener from onBindViewHolder
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, int i) {
myViewHolder.tvStudentName.setText(resultArrayList.get(i).getName());
myViewHolder.tvOutOf_List.setText(" / " + resultArrayList.get(i).getTotal_marks());
myViewHolder.etEnterMarks.setText(resultArrayList.get(i).getMarks_scored());
myViewHolder.tvStudentUid.setText(resultArrayList.get(i).getStudent_uid());
}
In MyViewHolder Class set btnUpdateMarks.setOnClickListener
public MyViewHolder(#NonNull View itemView) {
super(itemView);
tvStudentName = (TextView) itemView.findViewById(R.id.tvStudentName);
etEnterMarks = (EditText) itemView.findViewById(R.id.etEnterMarks);
tvOutOf_List = (TextView) itemView.findViewById(R.id.tvOutOf_List);
tvStudentUid = (TextView) itemView.findViewById(R.id.tvStudentUid);
btnUpdateMarks = (Button) itemView.findViewById(R.id.btnUpdateMarks);
btnUpdateMarks.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
student_uid = tvStudentUid.getText().toString();
String text = etEnterMarks.getText().toString();
Result r = new Result();
r.setMarks_scored(text);
int itemClickedPosition = getLayoutPosition();
//updateValue(text, r, v, firebaseChildValues, student_uid);
//change your updateValue() method accordingly
}
});
}
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.
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.
I wan to attach an OnClickListener to a CardView, so i can get the ID from the card
I have a RecyclerView that has a custom adapter for displaying the cards. This is how it's implemented.
I tried other examples in stackoverflow but it didn't work .
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> {
private ArrayList<Patient> patients;
Context mContext;
String idPatient;
public CardAdapter(ArrayList<Patient> patients) {
this.patients = patients;
}
#Override
public CardAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_card_view, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(CardAdapter.ViewHolder viewHolder, int i) {
viewHolder.first_name.setText(patients.get(i).getFirstName());
viewHolder.last_name.setText(patients.get(i).getLastName());
viewHolder.id_patient.setText(String.valueOf(patients.get(i).getId()));
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//trying to get ID From card
ViewGroup parentView = (ViewGroup)v.getParent();
TextView idpatientview =(TextView)parentView.findViewById(R.id.idViewPatient);
idPatient = idpatientview.getText().toString();
PreferencesHelper.save(mContext, "idPatient", idPatient);
Intent intent = new Intent(mContext, BluetoothActivity.class);
mContext.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return patients.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView first_name,last_name,id_patient;
public ViewHolder(View view) {
super(view);
first_name = (TextView)view.findViewById(R.id.textViewName);
last_name = (TextView)view.findViewById(R.id.textViewLastName);
id_patient = (TextView)view.findViewById(R.id.idViewPatient);
}
}
}
If your onClick method is inside your onBindViewHolder, then you can get the current data directly
String first_name = patients.get(i).getFirstName();
String last_name = patients.get(i).getLastName();
String id_patient = String.valueOf(patients.get(i).getId());
in your onClickListener, the id of the patient corresponding to the clicked card is simply id_patient, the first name is first_name and the last name is last_name. You can now pass the data to your activity (with an interface for exemple)