i have a specific issue. Im creating a App which allows me to display recepts of certain dishes. I designed a custom Adapter which contains a TextView and RatingBar. So in my other Activity(ViewDatabase) i retrieve the dish-name from a JSON-File (method is called : showData) and display it on a ListView which gets the custom adapter.
My problem is now that dont know why i can only select either the name of my dish ( so the textview of my adapter ) or the ratingbar ( is also in my adapter).
I tried to put in the method : myListView.setItemsCanFocus(true); but still doesnt work.
Is i didnt implement a clicklistener to my text in the Adapter? I tried to implement one.I need a explicit intent which swaps the Activity but i cant
go from a Adapterclass to a other class in a intent.
In the ViewDatabse- Class is onItemClick my method for changing the activty if i click the text.
Here is my code :
Adapter:
a)
public UserInformationAdapter(Context context, List<UserInformation> objects) {
super(context, R.layout.rating_item, objects);
this.context = context;
table = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.rating_item, null);
}
TextView name = (TextView) v.findViewById(R.id.hauptgerichte);
RatingBar ratingBar = (RatingBar) v.findViewById(R.id.rate_bar);
UserInformation userInformation = table.get(position);
ratingBar.setOnRatingBarChangeListener(onRatingChangedListener(position));
ratingBar.setTag(position);
ratingBar.setRating(getItem(position).getRatingStar());
name.setText(userInformation.getName());
name.setTag(position);
return v;
}
private RatingBar.OnRatingBarChangeListener onRatingChangedListener(final int position) {
return new RatingBar.OnRatingBarChangeListener() {
#Override
public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
UserInformation item = getItem(position);
assert item != null;
item.setRatingStar(v);
Log.i("Adapter", "star: " + v);
}
};
}
}
This is the Item (for name and ratingbar):
public class UserInformation {
private String name;
private float ratingStar;
public UserInformation(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
void setRatingStar(float ratingStar) {
this.ratingStar = ratingStar;
}
float getRatingStar() {
return 0;
}
#Override
public String toString(){
return name;
}
}
This is the Activity which retrieves the Name:
Activity:
public class ViewDatabase extends AppCompatActivity {
private static final String TAG = "ViewDatabase";
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;
private String userID;
private ArrayList<String> array;
private final List<UserInformation> arr = new ArrayList<>();
private UserInformationAdapter adapter2;
private ListView mListView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_database_layout);
array = new ArrayList<>();
mListView = (ListView) findViewById(R.id.list_karnivoure);
mListView.setItemsCanFocus(true);
mAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
myRef = mFirebaseDatabase.getReference();
FirebaseUser user = mAuth.getCurrentUser();
userID = user.getUid();
myRef.child("shakes").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
showData(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void showData(DataSnapshot dataSnapshot) {
Iterable<DataSnapshot> children = dataSnapshot.getChildren();
for (DataSnapshot child: children){
UserInformation uInfo = child.getValue(UserInformation.class);
arr.add(uInfo);
adapter2 = new UserInformationAdapter(ViewDatabase.this, arr);
mListView.setAdapter(adapter2);
mListView.setItemsCanFocus(true);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mListView.setItemsCanFocus(true);
Object listItem = mListView.getItemAtPosition(position);
Intent i = new Intent(ViewDatabase.this,KarnivoureInput.class);
i.putExtra("name", listItem.toString());
startActivity(i);
}
});
}
https://stackoverflow.com/a/8955441/5608931
Try adding this attribue to TextView and RatingBar . It would be clickable but will not get Focused
android:focusable="false"
Related
I'm trying to delete an item from a listview, but there is a problem..i'm using a fragment and I don't know how to get the "delete image button" to add a onClickListener...
That's my xml of the delete button which is in payment_list_view.xml :
<ImageButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/trash_icon"
android:padding="10dp"
android:id="#+id/delete_payment_btn"
android:background="#android:color/white" />
Then, I have my PaymentFragment which contains my listview:
package com.nicola.baccillieri.splitpayment;
public class PaymentFragment extends Fragment {
private String descString;
private int price;
private String payedBy;
private ArrayList<String> descPayArray;
private ArrayList<Integer> priceArray;
private ArrayList<String> payedByArray;
int trash;
PaymentAdapter customAdapter;
private final static String SHARED_PREFS = "sharedPrefs";
FirebaseFirestore db;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
db = FirebaseFirestore.getInstance();
trash = (R.drawable.trash_icon);
descPayArray = new ArrayList<>();
priceArray = new ArrayList<>();
payedByArray = new ArrayList<>();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView=inflater.inflate(R.layout.payments_fragment,container,false);
ProgressBar detailsPb = rootView.findViewById(R.id.details_pb);
detailsPb.getIndeterminateDrawable().setColorFilter(0XFF3F51B5,
PorterDuff.Mode.MULTIPLY);
detailsPb.setVisibility(View.VISIBLE);
final ListView listView = rootView.findViewById(R.id.paymentLv);
String email = getEmail();
String groupName = getActivity().getIntent().getStringExtra("title");
DocumentReference docRef = db.collection("users").document(email).collection("Group").document(groupName);
docRef.collection("Payments")
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (QueryDocumentSnapshot document : queryDocumentSnapshots) {
//Extracting payment description from each document
descString = document.getId();
descPayArray.add(descString);
//Extracting cost and who payed from each document
price = document.getLong("cost").intValue();
priceArray.add(price);
payedBy = document.getString("payed by");
payedByArray.add(payedBy);
trash = R.drawable.trash_icon;
customAdapter = new PaymentAdapter(getActivity(), descPayArray, payedByArray, priceArray, trash);
listView.setAdapter(customAdapter);
ProgressBar detailsPb = rootView.findViewById(R.id.details_pb);
detailsPb.setVisibility(View.GONE);
// That's the line that cause the error
ImageButton deleteBtn = rootView.findViewById(R.id.delete_payment_btn);
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String groupName = getActivity().getIntent().getStringExtra("title");
int positionToRemove = (int) v.getTag();
String email = getEmail();
String paymentToRemove = descPayArray.get(positionToRemove);
DocumentReference docRef = db.collection("users").document(email).collection("Group").document(groupName).collection("Payments").document(paymentToRemove);
docRef.delete();
descPayArray.remove(positionToRemove);
customAdapter.notifyDataSetChanged();
}
});
}
// If there isn't any payment display a blank activity
ProgressBar detailsPb = rootView.findViewById(R.id.details_pb);
detailsPb.setVisibility(View.GONE);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
ProgressBar detailsPb = rootView.findViewById(R.id.details_pb);
detailsPb.setVisibility(View.GONE);
Toast.makeText(getContext(), "Failed to load payments", Toast.LENGTH_LONG).show();
}
});
return rootView;
}
public String getEmail() {
SharedPreferences sharedPreferences = this.getActivity().getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
String email = (sharedPreferences.getString("email", ""));
return email;
}}
and finally the file group_detail_activity.xml contains my 2 fragment with a tab layout.
Now, the app crash when It has to show the PaymentFragment, because ImageButton deleteBtn = rootView.findViewById(R.id.delete_payment_btn); says
`java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageButton.setOnClickListener(android.view.View$OnClickListener)' on a null object reference".
That's because my rootView contains payment_fragment.xml, and not the payment_list_view.xml. So It doesn't find the button.
I've tryed to add final View rootListView=inflater.inflate(R.layout.payment_list_view,container,false);
and then it shows the list view, but when I click on the delete button, it doesn't do anything.
What should I do?
That's my PaymentAdapter:
package com.nicola.baccillieri.splitpayment;
public class PaymentAdapter extends BaseAdapter {
private Context context;
private ArrayList<String> payDesc;
private ArrayList<String> payedBy;
private ArrayList<Integer> price;
private int trash;
LayoutInflater inflater;
public PaymentAdapter(Context context, ArrayList<String> payDesc, ArrayList<String> payedBy, ArrayList<Integer> price, int trash) {
this.context = context;
this.payDesc = payDesc;
this.payedBy = payedBy;
this.price = price;
this.trash = trash;
inflater = (LayoutInflater.from(context));
}
#Override
public int getCount() {
return payDesc.size();
}
#Override
public Object getItem(int position) {
return payDesc.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.payment_list_view, null);
TextView paymentDesc = convertView.findViewById(R.id.payedDescTv);
TextView payedByTv = convertView.findViewById(R.id.payedByTv);
TextView priceTv = convertView.findViewById(R.id.priceTv);
ImageButton trashIcon = convertView.findViewById(R.id.delete_payment_btn);
paymentDesc.setText(payDesc.get(position));
payedByTv.setText("Payed by " + payedBy.get(position));
priceTv.setText(String.valueOf(price.get(position)) + "€");
trashIcon.setImageResource(trash);
trashIcon.setTag(position);
return convertView;
}}
The problem is that I need to delete the item both from the listview and from firebase...so I need the getEmail() method e the getExtra which is in PaymentFragment..If i put the listener on the adapter, how can I delete o Firebase?
Try this way. On list clicked you can delete item
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
payedByArray.remove(position);
adapter.notifyItemRemoved(position);
}
});
Other way is to put the Delete Button in your payment_list_view and then in Adapter you can get position on that button click and delete it
From Custom_adapater's viewholder get the view id , and you can easily delete the item by using
payedByArray.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, payedByArray.size());
How to delete list item ,a SO's question already answered.. Have a look...
that might solve your problem.
You can set a listener to link the delete image button action to your fragment. Then can the button is click you trigger the listener and do what your want in your fragment. Yo can send the position to remove the good element
Your adapter don't know that list is being modified. you need to provide latest list to adapter after deletion of item.
Make your payedByArray list public in adapter code.
This activity code.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
payedByArray.remove(position);
//payedByArray is activity list;
adapter.payedByArray = payedByArray;
adapter.notifyItemRemoved(position);
}
});
For my first non-trivial Android app, I am making an app that involves chat rooms. I am using the chat room activity to teach myself recyclerView, which isn't covered as extensively as the somewhat antiquated listView in reference materials. I think I'm close to having a working recyclerView and adapter that I built trying to translate some of the elements of a listView into a recyclerView, but I am having trouble actually making the messages appear in the recyclerView. What am I doing wrong?
Here is my chat room activity:
public class ChatRoomActivity extends AppCompatActivity {
private static final String TAG = "Chat Room Activity";
private String mRoomID;
private String mRoomName;
private String mDisplayName;
private ArrayList<String> mUsernames = new ArrayList<>();
private ArrayList<String> mMessages = new ArrayList<>();
private RecyclerView mRecyclerView;
private EditText mInputText;
private ImageButton mSendButton;
private DatabaseReference mDatabaseReference;
private ChatRecyclerViewAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_room);
Log.d(TAG," onCreate: started.");
// identifies views
mInputText = findViewById(R.id.messageInput);
mSendButton = findViewById(R.id.sendButton);
//gets user display name from current user and gets Firebase reference
setupDisplayName();
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
// gets Google Place ID from shared preferences
SharedPreferences preferences = getSharedPreferences(PLACE_PREFS, 0);
mRoomID = preferences.getString(PLACE_ID_KEY, null);
mRoomName = preferences.getString(PLACE_NAME_KEY, null);
Toast.makeText(this, mRoomID + mRoomName, Toast.LENGTH_LONG).show();
// Creates listener to send the message when the "enter" button is pressed
mInputText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
sendMessage();
return true;
}
});
// Adds an OnClickListener to the sendButton to send a message
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendMessage();
}
});
}
private void setupDisplayName() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
mDisplayName = user.getDisplayName();
}
private void sendMessage() {
// Grabs the text the user typed in and pushes the message to Firebase
String input = mInputText.getText().toString();
if (!input.equals("")) {
Log.d(TAG, "Message sent");
Message chat = new Message(input, mDisplayName);
mDatabaseReference.child(mRoomID + "_messages").push().setValue(chat);
mInputText.setText("");
}
}
private void initRecyclerView(){
Log.d(TAG, "initRecyclerView: init recyclerview" );
mRecyclerView = findViewById(R.id.chatRecyclerView);
mAdapter = new ChatRecyclerViewAdapter(this,mMessages,mUsernames,mRoomID,mDatabaseReference);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
#Override
protected void onStart() {
super.onStart();
initRecyclerView();
}
#Override
protected void onStop() {
super.onStop();
mAdapter.cleanup();
}
}
And here is my adapter:
public class ChatRecyclerViewAdapter extends RecyclerView.Adapter<ChatRecyclerViewAdapter.ViewHolder> {
private static final String TAG = "ChatRecyclerViewAdapter";
private ArrayList<String> mMessage = new ArrayList<>();
private ArrayList<String> mAuthor = new ArrayList<>();
private String mRoomID;
private Context mContext;
private DatabaseReference mDatabaseReference;
private ArrayList<DataSnapshot> mSnapshotList;
private ChildEventListener mListener = new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
mSnapshotList.add(dataSnapshot);
notifyDataSetChanged();
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
public ChatRecyclerViewAdapter(Context mContext, ArrayList<String> mMessage, ArrayList<String> mAuthor, String mRoomID, DatabaseReference reference) {
this.mMessage = mMessage;
this.mAuthor = mAuthor;
this.mContext = mContext;
this.mRoomID = mRoomID;
mSnapshotList = new ArrayList<>();
mDatabaseReference = reference.child(mRoomID+"_messages");
mDatabaseReference.addChildEventListener(mListener);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_msg_row,parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Log.d(TAG,"onBindViewHolder called");
holder.message.setText(mMessage.get(position));
holder.author.setText(mAuthor.get(position));
}
#Override
public int getItemCount() {
return mMessage.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView author;
TextView message;
RelativeLayout singleMessageContainer;
public ViewHolder(View itemView) {
super(itemView);
author = itemView.findViewById(R.id.chatAuthor);
message = itemView.findViewById(R.id.chatMessage);
singleMessageContainer = itemView.findViewById(R.id.singleMessageContainer);
}
}
void cleanup() {
mDatabaseReference.removeEventListener(mListener);
}
}
The way you're inserting the records into ArrayList in onChildAdded() and retrieving it in onBindViewHolder() of RecyclerView adapter is totally wrong.
Why do you need to create an ArrayList of Firebase Datasnapshots? Use the Message class instead (you didn't post Message class structure in your question).
Alter the ChatRecyclerViewAdapter like this
public class ChatRecyclerViewAdapter extends RecyclerView.Adapter<ChatRecyclerViewAdapter.ViewHolder> {
// private ArrayList<String> mMessage = new ArrayList<>(); // comment or remove this line
// private ArrayList<String> mAuthor = new ArrayList<>(); // comment or remove this line
private String mRoomID;
private Context mContext;
private DatabaseReference mDatabaseReference;
// private ArrayList<DataSnapshot> mSnapshotList; // comment or remove this line
private ArrayList<Message> messageList; // add this member
}
The constructor
public ChatRecyclerViewAdapter(Context mContext, ArrayList<String> mMessage, ArrayList<String> mAuthor, String mRoomID, DatabaseReference reference) {
// this.mMessage = mMessage; // comment or remove this line
// this.mAuthor = mAuthor; // comment or remove this line
this.mContext = mContext;
this.mRoomID = mRoomID;
messageList = new ArrayList<>(); // initialize messageList object
mDatabaseReference = reference.child(mRoomID+"_messages");
mDatabaseReference.addChildEventListener(mListener);
}
And inside onChildAdded() method.
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
// convert Datasnapshot into a Message object
Message mes = dataSnapshot.getValue(Message.class);
// add it to an ArrayList of Message
messageList.add(mes); // notice the changes
notifyDataSetChanged();
}
Inside onBindViewHolder() method
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
// get single Message object from ArrayList
Message mes = messageList.get(position); // notice the difference
// just assuming that you've getter methods in your Message class
// please look into your code
holder.message.setText(mes.getMessage());
holder.author.setText(mes.getAuthor());
}
In getCount() method
#Override
public int getItemCount() {
return messageList.size(); // return the size of the ArrayList
}
Note: The way you implemented Chat using Firebase and RecyclerView is totally wrong. You should use/handle Firebase event listeners in an Activity or Fragment instead of it in an Adapter.
Before going into advanced stuff in Android please learn basic things first. You really need to understand how Firebase and RecyclerView works in first place.
Looking at the code above, ChatRecyclerViewAdapter's getItemCount() method returns the size of the messages array (mMessage.size()). But, notifyDataSetChanged() is called after adding an item to the DataSnapshot arraylist.
You have to also add the message from the snapshot to the messages array for the list to update when you call notifyDataSetChanged().
Also, it is recommended that you avoid calling notifyDataSetChanged() in general for performance reasons. RecyclerView.Adapter has helper methods such as notifyItemInserted or notifyItemRangeInserted to notify the adapter about new additions to the list.
My Datastructure
I am trying to get the TeacherId from the teacher with the same email of the currently logged in teacher from my database.Then store it to a string variable then later pass it to an adapter class for querying again. but everytime I try to retrieve it using ValueEventListener it returns null.
My Code
public class SchedList extends AppCompatActivity {
//member vars. ui objects
public ListView SubSchedListView;
public TextView schedList;
public TextView tIDTextView;
//data vars
private String email;
private String teacherid;
private ArrayList<DataSnapshot> snapshot;
//classes
private TeacherAccount ta;
private subjSchedAdapter mAdapter;
//
private DatabaseReference mDatabaseReference;
private SharedPreferences prefs;
//listener
private String x;
private String y;
private String z;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sched_list);
mDatabaseReference = FirebaseDatabase.getInstance().getReference().child("teacheraccount").child("TeacherId");
//ui objects
SubSchedListView = (ListView) findViewById(R.id.SubSchedListView);
schedList = (TextView) findViewById(R.id.schedTextView);
tIDTextView = (TextView) findViewById(R.id.tIDTextView);
//data vars
Intent intent = new Intent();
email = intent.getStringExtra("email");
snapshot = new ArrayList<>();
}
#Override
public void onStart() {
super.onStart();
Intent intent = new Intent();
Query query = mDatabaseReference.orderByChild("Email").equalTo(intent.getStringExtra("email"));
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ta = dataSnapshot.getValue(TeacherAccount.class);
x = ta.getTeacherId(); //the part where it says it returns null
y = dataSnapshot.getValue(String.class);
if (dataSnapshot.getKey().equals("TeacherId")) {
z = dataSnapshot.getValue(String.class);
}
Log.d("WHICH_HAS", x + y + z);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
// Setting the adapter
Log.d("WHICH_HAS", x + y + z);
//mAdapter = new subjSchedAdapter(this, mDatabaseReference,teacherid);
SubSchedListView.setAdapter(mAdapter);
}
#Override
public void onStop() {
super.onStop();
mAdapter.cleanup();
}
}
At which part is there something wrong ? should the valueListener be in the Onstart ? OnCreate ? or on its own function ? if so, at which part do I call the function ? at what other parts did I do wrong at ?
How do you pass a string data to a base adapter class ?
My Base Adapter class
public class subjSchedAdapter extends BaseAdapter{
private Activity mActivity;
private DatabaseReference mDatabaseReference;
private String mTeacherId;
private ArrayList<DataSnapshot> mSnapshotList;
private Query query;
private Context mContext;
// child event listener
private ChildEventListener mListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
mSnapshotList.add(dataSnapshot);
notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
mSnapshotList.add(dataSnapshot);
notifyDataSetChanged();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
//constructor
public subjSchedAdapter(Activity activity, DatabaseReference ref, String id){
mActivity = activity;
//mTeacherId = subjteacherid;
mDatabaseReference = ref.child("subjects");
//this is where id = the teacherId I retrieved
query = mDatabaseReference.orderByChild("teacherid").equalTo(id).limitToFirst(1);
query.addChildEventListener(mListener);
mSnapshotList = new ArrayList<>();
}
//view holder
static class ViewHolder{
TextView subjectCodeAndName;
TextView time;
TextView sectionName;
TextView teacherId;
LinearLayout.LayoutParams params;
}
#Override
public int getCount() {
return mSnapshotList.size();
}
#Override
public SubjectScheds getItem(int position) {
DataSnapshot snapshot = mSnapshotList.get(position);
return snapshot.getValue(SubjectScheds.class);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.subject_sched_list, parent, false);
final ViewHolder holder = new ViewHolder();
holder.subjectCodeAndName = (TextView) convertView.findViewById(R.id.subjectCodeAndName);
holder.time = (TextView) convertView.findViewById(R.id.time);
holder.sectionName = (TextView) convertView.findViewById(R.id.sectionName);
holder.teacherId = (TextView) convertView.findViewById(R.id.teacherid);
holder.params = (LinearLayout.LayoutParams) holder.subjectCodeAndName.getLayoutParams();
convertView.setTag(holder);
}
final SubjectScheds subjectsched = getItem(position);
final ViewHolder holder = (ViewHolder) convertView.getTag();
String subjcodeandname = subjectsched.getSubjectCode() + " - " + subjectsched.getSubjectName();
String time = "time : " + subjectsched.getTime();
String sectionName = "section : " + subjectsched.getSectionname();
String teacherId = "teacher : " + subjectsched.getTeacherid();
holder.subjectCodeAndName.setText(subjcodeandname);
holder.time.setText(time);
holder.sectionName.setText(sectionName);
holder.teacherId.setText(teacherId);
return convertView;
}
public void cleanup(){
mDatabaseReference.removeEventListener(mListener);
}
}
The part in the code where I set the adapter
Method Call
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot finalSnap :dataSnapshot.getChildren()){
ta = finalSnap.getValue(TeacherAccount.class);
x = ta.getTeacherId(); //the part where it says it returns null
tIDTextView.setText(x);
Display(x);
}
}
Method
private void Display(String x){
mAdapter = new subjSchedAdapter(this,mDatabaseReference,x);
SubSchedListView.setAdapter(mAdapter);
}
You have got the wrong database reference if you want to OrderbyChiled by Email then you want to get the reference to the parent of that specific field.
As per your case you need to find reference to teacher account as per follow:
mDatabaseReference = FirebaseDatabase.getInstance().getReference().child("teacheraccount");
I have to develop a chat app in android using firebase,It consist of different groups having options of leaving and joining the group,First time it doesn't show joined and leaved groups but on second time when we scroll list view or change view then it shows correctly.I have to fix the issue kindly look the below code and show what problems should be fixed.
public class Allgroups extends AppCompatActivity {
private DatabaseReference mDatabaseRef;
private List<ImageUpload> imgList;
private List<groupuserstoken> imgList1;
ListView listView;
private ImageListAdapter adapter;
private DatabaseReference databaseReference;
ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_allgroups);
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please wait loading groups...");
listView=(ListView)findViewById(R.id.allgroups11);
mDatabaseRef = FirebaseDatabase.getInstance().getReference();
imgList=new ArrayList<>();
final Query query = mDatabaseRef.child("Groups");
listView.smoothScrollByOffset(10);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
ImageUpload img = snapshot.getValue(ImageUpload.class);
imgList.add(img);
}
adapter = new ImageListAdapter(Allgroups.this, R.layout.custommenu, imgList);
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String name=imgList.get(i).getName();
String path=imgList.get(i).getUrl();
String topic=imgList.get(i).getTopic();
Intent intent= new Intent(getApplicationContext(),Main4Activity.class);
intent.putExtra("name",name);
intent.putExtra("path",path);
intent.putExtra("topic",topic);
startActivity(intent);
}
});
}
}
public class ImageListAdapter extends ArrayAdapter<ImageUpload> {
private Activity context;
private int resource;
private List<ImageUpload> listImage;
private DatabaseReference mDatabaseRef;
private List<groupuserstoken> imgList1;
ProgressDialog progressDialog;
int pos;
public ImageListAdapter(#NonNull Activity context, #LayoutRes int resource, #NonNull List<ImageUpload> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
listImage = objects;
}
TextView tvName;
TextView tvDes;
TextView statuss;
Button leave;
ImageView img;
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.custommenu, null);
}
// final LayoutInflater inflater = context.getLayoutInflater();
// v = LayoutInflater.from(getContext()).inflate(R.layout.custommenu, parent, false);
ImageUpload listImage1 = getItem(position);
if (listImage1 !=null) {
tvName = (TextView) v.findViewById(R.id.as);
tvDes = (TextView) v.findViewById(R.id.aa);
statuss = (TextView) v.findViewById(R.id.users);
img = (ImageView) v.findViewById(R.id.addgroup1);
leave = (Button) v.findViewById(R.id.leavegroup);
mDatabaseRef = FirebaseDatabase.getInstance().getReference();
final String name = listImage.get(pos).getName();
final Query query1 = mDatabaseRef.child(name + "user");
query1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
imgList1 = new ArrayList<>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
groupuserstoken img = snapshot.getValue(groupuserstoken.class);
imgList1.add(img);
}
String token = FirebaseInstanceId.getInstance().getToken();
if (!(imgList1.isEmpty())) {
if (!(imgList1.contains(token))) {
leave.setText("Leave Group");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
tvName.setText(listImage1.getName());
tvDes.setText(listImage1.getDescription());
statuss.setText(listImage1.getMembers() + " Users ");
Glide.with(context).load(listImage1.getUrl()).into(img);
}
leave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String groupname = listImage.get(position).getName();
mDatabaseRef = FirebaseDatabase.getInstance().getReference().child(groupname+"user").child(FirebaseInstanceId.getInstance().getToken());
mDatabaseRef.child("token").setValue(FirebaseInstanceId.getInstance().getToken());
}
});
return v;
}
}
Please use setTag() and getTag() in your adapter, but for better practice is to use RecyclerView instead of ListView.
I just started learning android studio for about a month. Sorry if I have posted this in wrong format or asked the wrong question. I have a GridView at my OverviewPage which has a custom adapter that extends ArrayAdapter. I have a GridItem class that contains the objects that I wish to display in the each grid. What I would like to do is to update my GridView to have a new grid every time a new child is created in the Databse.
This is my GridItem class.
package com.example.android.testlogin;
import java.io.Serializable;
public class GridItem implements Serializable {
int mImageView;
String mTitleHere;
String mPriceHere;
public GridItem(int ImageView, String titleHere, String priceHere) {
mImageView = ImageView;
mTitleHere = titleHere;
mPriceHere = priceHere;
}
public int getmImageView() {
return mImageView;
}
public void setmImageView(int ImageView) {
mImageView = ImageView;
}
public String getmTitleHere() {
return mTitleHere;
}
public void setmTitleHere(String TitleHere) {
mTitleHere = TitleHere;
}
public String getmPriceHere() {
return mPriceHere;
}
public void setmPriceHere(String PriceHere) {
mPriceHere = PriceHere;
}
}
This is my custom Adapter.
package com.example.android.testlogin;
public class GridAdapter extends ArrayAdapter<GridItem> {
public GridAdapter(Activity context, ArrayList<GridItem> packageName){
super(context ,0, packageName);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Check if the existing view is being reused, otherwise inflate the view
View listItemView = convertView;
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.grid_item, parent, false);
}
GridItem currentItem = getItem(position);
ImageView putPic = (ImageView) listItemView.findViewById(R.id.imageHere);
TextView putTitle = (TextView) listItemView.findViewById(R.id.titleHere);
TextView putPrice = (TextView)listItemView.findViewById(R.id.per_price);
//Set Text for TextView and ImageResources for ImageView.
putPic.setImageResource(currentItem.getmImageView());
putTitle.setText(String.valueOf(currentItem.getmTitleHere()));
putPrice.setText(String.valueOf("$: " + currentItem.getmPriceHere()));
// Return the whole list item layout (containing 2 TextViews and an ImageView)
// so that it can be shown in the ListView
return listItemView;
}
}
This is my OverviewPage which acts as the main page when user login. Users should be able to see all the grid created.
package com.example.android.testlogin;
public class OverviewPage extends AppCompatActivity {
private GridView lvPackage;
private GridAdapter adapter;
private FirebaseAuth mAuth1;
private FirebaseAuth.AuthStateListener mAuthListener1;
private DatabaseReference mDatabaseReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.overview_page);
lvPackage = (GridView) findViewById(R.id.grid);
mDatabaseReference = FirebaseDatabase.getInstance().getReference().child("comPostsCopy");
mAuth1 = FirebaseAuth.getInstance();
mAuthListener1 = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() == null) {
startActivity(new Intent(OverviewPage.this , MainActivity.class));
}
}
};
//Add sample data for grid;
final ArrayList<GridItem> elements = new ArrayList<GridItem>();
elements.add(new GridItem(R.mipmap.ic_launcher_round, "Hello there", "120"));
elements.add(new GridItem(R.mipmap.ic_launcher_round, "Bare Bears", "50"));
elements.add(new GridItem(R.mipmap.ic_launcher_round, "Not Fun", "50"));
mDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Loop Through Children
for(DataSnapshot ds : dataSnapshot.getChildren());
*//Read Data from Firebase Database and get required data to be shown on new grid.*
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//Initialize Adapter
adapter = new GridAdapter(this, elements );
lvPackage.setAdapter(adapter);
lvPackage.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Do something
Toast.makeText(OverviewPage.this, "Not yet", Toast.LENGTH_SHORT).show();
}
});
}
#Override
protected void onStart() {
super.onStart();
mAuth1.addAuthStateListener(mAuthListener1);
}
}
This is my Firebase Database
Firebase Database
I would only like to get for example the child key "title" and "pricePerGuest" shown on my new grid.
I know I would have to loop through each child in my comPostsCopy child. However, I have no idea how to get some paticular data from the added child in the addValueEventListener method.