I have a recyclerView called "Notes", I'm trying to add an new recylerview called "Assignments" which will be created inside the notes recylerview item.
When I click on a recylerview item (notes) it send me to ClassworkActivity in which the assignments' recyclerview will be added to it.
So I want to add the assignment recyclerview as a child of the notes recyclerview.
Here's what I tried:
final AssignmentAdapter assignmentAdapter=new AssignmentAdapter(assignlist,this);
recyclerView.setAdapter(assignmentAdapter);
FloatingActionButton fab = findViewById(R.id.fab);
mCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
String userID = mCurrentUser.getUid();
firebaseDatabase=FirebaseDatabase.getInstance();
databaseReference = firebaseDatabase.getReference().child("Users").child(userID).child("Notes").child(id).child("Assignments");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot dataSnapshot1: dataSnapshot.getChildren())
{
AssignListdata listdata=dataSnapshot1.getValue(AssignListdata.class);
assignlist.add(listdata);
}
assignmentAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
// fab
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getApplicationContext(), AddAssignmentActivity.class));
}
});
But I'm getting the error on this line:
databaseReference = firebaseDatabase.getReference().
child("Users").
child(userID).
child("Notes").
child(id).
child("Assignments");
since I didn't create the variable id : child(id). which is the id of the Notes List
Can anyone tell me how to declare this variable?
Another thing is that the assignments are created as a Notes in the NotesActivity, not in the ClassworkActivity!
Also, this is a github link of my project, Please take a look at it:
Notes App
When you click on recyclerView item of Notes, get the noteID usinng which position is clicked.
now when you open ClassworkActivity, bind that id with intent and get it in ClassworkActivity onCreate() and while creating AssignmentAdapter use that noteID as id.
pass noteId using intent as:
Intent myIntent = new Intent(CurrentActivity.this, ClassworkActivity.class); // UPDATE CURRENT ACTIVITY NAME
myIntent.putExtra("noteID", noteID);
startActivity(myIntent);
and receive in ClassworkActivity onCreate() as:
Intent mIntent = getIntent();
int id = mIntent.getIntExtra("noteID", 0);
Related
I having some trouble with how to use a Button to access another activity with data from firebase. I'm just getting an error "Can't pass null for argument 'pathString' in child()". But when I try in another activity with OnItemClick on a listview item it works. Why is that?
What I'm trying to do is: I have a activity with a listview that stores and get data from firebase. What I want is, if I click on one of the items in that listview I want a new activity with buttons, and these buttons will get me to another activity with a listview that are related to the first activity (related data). So the activity with the buttons are the same activity for every listview items i click on, like just a "dummy" activity. Is this possible?
Here is the code:
lvjobbinfo works fine, but add doesn't. I want lvjobbinfo and add to do the same.
public class MainActivity extends AppCompatActivity {
EditText etinfonavn;
ListView lvjobbinfo;
TextView tvjobbnavn;
Button add;
DatabaseReference databaseJOBBINFO;
List<Main> jobbinfo;
public static final String infonavn = "infonavn";
public static final String infoid = "infoid";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
databaseJOBBINFO = FirebaseDatabase.getInstance().getReference().child("Jobbinfo");
lvjobbinfo = (ListView)findViewById(R.id.lvjobbinfo);
lvjobbinfo.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
Main main = jobbinfo.get(i);
Intent intent = new Intent(getApplicationContext(), Notater.class);
intent.putExtra(infoid, main.getInfoId());
intent.putExtra(infonavn, main.getInfonavn());
startActivity(intent);
return true;
}
});
tvjobbnavn = (TextView)findViewById(R.id.tvjobbnavn);
etinfonavn = (EditText) findViewById(R.id.etinfonavn) ;
add = (Button)findViewById(R.id.add);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent add = new Intent(MainActivity.this, Notater.class);
startActivity(add);
}
});
Intent intent = getIntent();
jobbinfo = new ArrayList<>();
String id = intent.getStringExtra(Jobbliste.jobbId);
String navn = intent.getStringExtra(Jobbliste.jobbnavn);
tvjobbnavn.setText(navn);
databaseJOBBINFO = FirebaseDatabase.getInstance().getReference("Jobbinfo").child(id);
}
#Override
protected void onStart() {
super.onStart();
databaseJOBBINFO.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
jobbinfo.clear();
for (DataSnapshot infosnapshot : dataSnapshot.getChildren()) {
final Main main = infosnapshot.getValue(Main.class);
jobbinfo.add(main);
final listMain infolistadapter = new listMain(MainActivity.this, jobbinfo);
lvjobbinfo.setAdapter(infolistadapter);
infolistadapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I am removing a list item with a PopupMenu on my RecyclerViewAdapter, but when the item is removed it stays on the Firebase.
This is on the onBindViewHolder on the RecyclerAdapter
holder.opcionesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//creating a popup menu
PopupMenu popup = new PopupMenu(context, holder.opcionesButton);
//inflating menu from xml resource
popup.inflate(R.menu.menu_edit);
//adding click listener
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.edit_item:
//handle menu1 click
break;
case R.id.delete_item:
tareasList.remove(position);
notifyItemRemoved(position);
Toast.makeText(context, "Tareas eliminada!", Toast.LENGTH_SHORT).show();
break;
}
return false;
}
});
//displaying the popup
popup.show();
}
});
And this is on the MainFragment
final Query tareasQuery = mTareasDatabase.child(userId);
tareasQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Tareas tareas = new Tareas();
tareas.setFecha(dataSnapshot.getValue(Tareas.class).getFecha());
tareas.setDescripcion(dataSnapshot.getValue(Tareas.class).getDescripcion());
tareas.setLista(dataSnapshot.getValue(Tareas.class).getLista());
tareas.setPrioridad(dataSnapshot.getValue(Tareas.class).getPrioridad());
mTareasList.add(tareas);
mTareasAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
String tareasId = dataSnapshot.getValue(Tareas.class).getTareasId();
mTareasDatabase.child(userId).child(tareasId).removeValue();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
String tareasId = dataSnapshot.getValue(Tareas.class).getTareasId();
mTareasDatabase.child(userId).child(tareasId).removeValue();
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Everything is working fine, except that is not deleting it from the firebase
Solution
Remove the item from the firebase and the recycler view at the same time
case R.id.delete_item:
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
String tareasId = tareas.getTareasId();
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String userId = user.getUid();
DatabaseReference databaseReference = firebaseDatabase.getReference("Tareas")
.child(userId).child(tareasId);
databaseReference.removeValue();
tareasList.remove(position);
notifyItemRemoved(position);
Toast.makeText(context, "Tareas eliminada!", Toast.LENGTH_SHORT).show();
break;
Okay I solved it. I just had to add all the database references on the delete item, and remove it from the recycler view and the database at the same time
case R.id.delete_item:
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
String tareasId = tareas.getTareasId();
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String userId = user.getUid();
DatabaseReference databaseReference = firebaseDatabase.getReference("Tareas")
.child(userId).child(tareasId);
databaseReference.removeValue();
tareasList.remove(position);
notifyItemRemoved(position);
Toast.makeText(context, "Tareas eliminada!", Toast.LENGTH_SHORT).show();
break;
this is because you are deleting from the local list only. You have to remove the value from firebase too. For deleting use code
firebaseRef.removeValue();
In your firebaseRef you have to show which value you want to delete.
I have a mChildEventListener that queries for the first n items from Firebase Database and another mChildEventListener2 (triggered when the user scroll up and clicks on a Load More button) that queries for the next n items and adds them to the ChatMessagesList.
When the user clicks on the Load More button: the ChatMessagesList is updated and notifyDataSetChanged is called. The mMessageListView is updated but it scrolls down to the buttom every time. I explained this behavior because of the xml attribute: android:transcriptMode="alwaysScroll".
When I remove transcriptMode="alwaysScroll" and the user presses on the Load More button, the mMessageListView scrolls this time to the top.
None of these behaviors are wanted. I would like that when the user presses the button, the mMessageListView would maintain its' scrolling position. (for obvious reasons)
I tried calling notifyDataSetChanged from a new thread. No results.
I tried using listView.setSelectionFromTop(lastViewedPosition, topOffset); or using list.smoothScrollToPosition(); but none achieved a smooth experience that I would want.
How can I maintain the scrolling position after the mMessageListView is updated?
This is the code:
private ChildEventListener mChildEventListener;
private ChildEventListener mChildEventListener2;
List<ChatMessage> ChatMessages = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
...
mMessageAdapter = new MessageAdapter(this, R.layout.item_message_sent, ChatMessages);
mMessageListView.setAdapter(mMessageAdapter);
mChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if(i == 0) {
current_last_key = dataSnapshot.getKey();
}
else {
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
mMessageAdapter.add(chatMessage);
}
i++;
}
...
};
Query messagesQuery = mDatabaseReference.child("chat_messages").
child(chatId).limitToLast(25);
messagesQuery.addChildEventListener(mChildEventListener);
...
}
#Override
public void onClick(View v) {
j = 0;
mChildEventListener2 = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if(!dataSnapshot.getKey().equals(current_last_key)) {
if (j == 0) {
current_last_key = dataSnapshot.getKey();
}
else {
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
ChatMessages.add(j- 1, chatMessage);
}
}
else
{
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
ChatMessages.add(0 , chatMessage);
loadMoreTextView.setVisibility(View.GONE);
}
mMessageAdapter.notifyDataSetChanged();
j++;
}
... };
Query query = mDatabaseReference.child("chat_messages").
child(chatId).orderByKey().endAt(current_last_key).limitToLast(10);
query.addChildEventListener(mChildEventListener2);
}
notifyDataSetChanged()
Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
Try to see if "onCreate()" is called again when updating
FirebaseUI lib handles all that for you and simplifies your code.
BTW, you can use mAdapter.notifyItemInserted(ChatMessages.size() - 1); or mMessageAdapter.notifyItemRangeInserted(ChatMessages.size() - 1, ChatMessages.size() - 1 + numberOfItemsBeingInserted); and make the other required changes in order for this to work, instead of using mMessageAdapter.notifyDataSetChanged();
I am developing an Android app, and I have already implemented authentication with Firebase. After logging in, in my NavigationDrawerActivity I have a ListView that I had set a FirebaseListAdapater to that gets user specific data.
In my onCreate() method I have the following:
firebaseAuth = FirebaseAuth.getInstance();
FirebaseUser localUser = firebaseAuth.getCurrentUser();
String localUserEmail = localUser.getEmail();
String localUserEmailUniqueID = getEmailAddressUniqueID(localUserEmail);
String dbUsersRoot = "https://DATABASENAME.firebaseio.com/Users/";
String dbUniqueRefForCurrentUser = dbUsersRoot + localUserEmailUniqueID +"/parishioners";
DatabaseReference databaseReferenceCurrentUser = FirebaseDatabase.getInstance().getReferenceFromUrl(dbUniqueRefForCurrentUser);
final FirebaseListAdapter<String> firebaseListAdapter = new FirebaseListAdapter<String>(
this,
String.class,
android.R.layout.simple_list_item_2,
databaseReferenceCurrentUser
) {
#Override
protected void populateView(View v, String model, int position) {
TextView textView = (TextView) v.findViewById(android.R.id.text1);
textView.setText(model);
}
};
mListView.setAdapter(firebaseListAdapter);
Now, in my onStart() method I have added an setOnClickListener to a button that wishes to add a new item into my list , like this :
#Override
protected void onStart(){
super.onStart();
mButtonAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
firebaseAuth = FirebaseAuth.getInstance();
FirebaseUser localUser = firebaseAuth.getCurrentUser();
String localUserEmail = localUser.getEmail();
String localUserEmailUniqueID = getEmailAddressUniqueID(localUserEmail);
String dbUsersRoot = "https://DATABASENAME.firebaseio.com/Users/";
String dbUniqueRefForCurrentUser = dbUsersRoot + localUserEmailUniqueID +"/parishioners";
DatabaseReference databaseReferenceCurrentUser = FirebaseDatabase.getInstance().getReferenceFromUrl(dbUniqueRefForCurrentUser);
databaseReferenceCurrentUser.push().setValue(editTextNewMember.getText().toString().trim());
}
});
}
On clicking the Add Button, I'll have in my database something like this (supposing the EditText has in it the string 'capuccino'):
"luminittta" : {
"parishioners" : {
"-KX1GcEWPMy7oFWgt_3h" : "capuccino"
Now, my List will show 'capuccino' (since it's a realtime database my list will automatically get updated with the newly added value).
My question is:
How can I implement next a delete functionality that when the user long clicks an item from the ListView it gets removed?
Entire Database looks like this:
{
"Users" : {
"davidivanmircea" : {
"parishioners" : {
"-KX1FNcgSXgsMNz6QRIS" : "Gus Crick",
"-KX1FVIzzPM4nMrMvm9x" : "Florentino Williams",
"-KX1FZ27M-KS5TQZQ76u" : "Marc Raff",
"-KX1FbercKpPrl9r9tb4" : "Frederick Haddon",
"-KX1FgguOlRRN4sZKS8Z" : "Cristobal Wolfe",
"-KX1FkgwifQLIHplsZNx" : "Scott Nodal",
"-KX1Fp64Sa2QD94GR9uK" : "Odis Nevers",
"-KX1FrYK5PeuBucEiamY" : "Chauncey Mossman",
"-KX1FvIBDSrvppC3e4Ip" : "Alfonso Ignacio",
"-KX1Fy7dEHH8Z9JV-BRL" : "Douglas Hettinger",
"-KX1WdtbV4PEiscJV6E_" : "Daniel Muresan",
"-KX1WvYqekJZdWS6wGh6" : "Angelina Jolie"
}
},
"luminittta" : {
"parishioners" : {
"-KX1GYuSsgmHyGk5LQLA" : "mocha",
"-KX1G_Q130sWitNGzlAR" : "triplo",
"-KX1GaPIhuIyhV4vmLGe" : "latte",
"-KX1GcEWPMy7oFWgt_3h" : "capuccino",
"-KX1Gf7TKY3N8IQETig-" : "machiatto",
"-KX1Gh4KoYpcVpCDFI2x" : "cafe melange",
"-KX1GoCutX3XO-CRWWB3" : "ristretto",
"-KX1GpvdE5i9UR2ZaX0K" : "americano",
"-KX1Grb8S5QZu4HT9cuW" : "espresso"
}
}
}
}
Thank you very much for your help !
PS: I have modified my actual database name with 'DATABASENAME' inside the code.
Change your "populateView" to this one:
#Override
protected void populateView(View v, String model, int position) {
TextView textView = (TextView) v.findViewById(android.R.id.text1);
textView.setText(model);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mRecycleViewAdapter.getRef(position).removeValue();
Log.d("TAG", model + " removed from the list");
}
});
}
};
To remove a specific item on LongClick write this in populateView
v.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
getRef(position).removeValue();
notifyDataSetChanged();
return true;
}
});
After reading the code Nirel and Frank provided, I changed my FirebaseListAdapter into a RecyclerView succesfully and implemented my Delete functionality (on clicking the item from the list).
For the record, RecyclerView does not come with an onClickListener by itself, so anyone who will be in the same situation as I was will need to implement it. I have used http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/ and it works like a charm.
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