That is it, can i remove a view from firebase recycler view adapter, but not deleting in the database?How?
final FirebaseRecyclerAdapter<Game,GameViewHolder> firebaseRecyclerAdapter=new FirebaseRecyclerAdapter<Game, GameViewHolder>(
Game.class,
R.layout.row,
GameViewHolder.class,
mdatabase
) {
#Override
protected void populateViewHolder(GameViewHolder viewHolder, Game model, final int position) {
viewHolder.setTitle(model.getGame_name());
viewHolder.setJugado(model.getJugado());
viewHolder.setCreator(model.getCreator_name());
recyclerView.setAdapter(firebaseRecyclerAdapter);
}
FirebaseRecyclerAdapter doesn't support this. The whole point of FirebaseRecyclerAdapter is that it stays in sync with the contents of the location that you originally gave it. If something deletes data from the database, it will be automatically and unconditionally deleted from your adapter.
If you want this behavior, you will have to implement your own RecyclerView adapter, preferably one that does not use an active listeners to be notified of every change to the location of the data. You would have to listen to the entire contents just once, then send that to an adapter to populate a RecyclerView.
And how about this in ViewHolder?
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
itemView.setVisibility(View.INVISIBLE);
}
});
Yes you can. You have to add this in your GameViewHolder class:
Create a function and get reference of your cardview
Create a layout params and Create an instance of the parent of your cardview then set the height and the width equals to 0
public void Remove() {
cardView = mView.findViewById(R.id.cardview);
cardView.setLayoutParams(new FrameLayout.LayoutParams(0,0));
}
Use the function
viewHolder.remove();
Related
I'm trying to attach an onClickListener() method to an item which is inside a Recycler view. I know I can easily achive that by doing it from the RecyclerAdapter, but the goal of doing that is to show a custom dialog with some information that parent fragment contains, there are some ways to pass data, but I think that's better to attach the listener from fragment instead, and this way I can directly access the data.
I've tried to access from the fragment the way I use to do it from the adapter, with some modifications:
myRecyclerAdapter.myViewHolder.reportContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(),"Touch",Toast.LENGTH_SHORT).show();
}
});
But aparently the myViewHolder object it's not created yet by the time I try to use it, so I get the Java NullPointerException (F..$&##^$&^%, don't misunderstand me, I love it).
So, I need some help to do what I'm trying to, or some other good ideas to try, warning: I;m really trying to avoid passing data, except with maybe a ViewModel (don't know if I can), becouse it's a lot of fields to pass
This is fundamentally incorrect. The problem here is, there are multiple ViewHolders in the RecylerView. Which one do you want to attach it to? There would be n number of items and not all items will be rendered at the same time.
Instead of updating the ViewHolder, use a callback.
class MyAdapter extends RecyclerView.Adapter {
MyAdapterCallback callback = null;
....
#Override
public void onBindViewHolder(holder: ViewHolder, position: Int) {
holder.reportContainer.setOnClickListener { // You can set this in OnCreateViewHolder as well.
if (callback != null) {
callback.onClick();
}
}
}
}
interface MyAdapterCallback {
void onClick()
}
From your fragment,
myAdapter.callback = new MyAdapterCallback() {
#Override
public void onClick() {
// Access your fragment variables here.
}
}
I'm using firebase-ui to retrieve from firebase and I want to remove from displaying all the status that are equal to unlive I don't want to delete it from firebase database but only removed it from displaying on the recyclerview tried also doing the solution Cannot call this method while RecyclerView is computing a layout or scrolling when try remove item from recyclerview here still encountering the error. Please help I'm stuck here for days. Can't find any solution. Thanks
mAdapter = new FirebaseRecyclerAdapter<Hotels_Model, Adapter_HotelsHolder>(mOptions) {
#Override
protected void onBindViewHolder(Adapter_HotelsHolder holder,int position, Hotels_Model model) {
String status = model.getStatus();
if (status.equals("unlive")) {
mAdapter.notifyItemRemoved(holder.getAdapterPosition());
mAdapter.notifyItemRangeChanged(holder.getAdapterPosition(), getItemCount());
}
}
This is my error if I scroll to the position where the status is unlive
Cannot call this method while RecyclerView is computing a layout or scrolling android.support.v7.widget.RecyclerView
So you can do it easily in that way:
mAdapter = new FirebaseRecyclerAdapter<Hotels_Model, Adapter_HotelsHolder>(mOptions) {
#Override
protected void onBindViewHolder(Adapter_HotelsHolder holder,int position, Hotels_Model model) {
String status = model.getStatus();
if (status.equals("unlive")) {
holder.yourRowView.setVisibility(View.GONE);
}
}
You don't need to remove your items from recyclerview.
So i have a recycler view loaded with items containing text and image and a checkbox. All the data is loaded just fine initially including the images using picasso. The checkbox is initially hidden, once i tap a button, which is not part of the recycler view. The checkboxes should appear in all the items of recycler view. Everything works fine except for the fact that the images disappear once i do that.
The way i am doing it is that i set the adapter to my recyclerview to null and then initialize a new recycler view adapter which has checkboxes visible and set it to my recycler view.
The same thing happens if i try to search for a particular list item using a search bar on top. Any idea why? Here is the code about how i am setting the adapter to my recycler view.
// set the adapter to null on cards list view.
cards_list_view.setAdapter(null);
// Initialize the adapter again.
deckCardRecycleAdapter = new DeckCardRecycleAdapter(getActivity(), cards_list, show_checkbox);
// Set the adapter again to list view.
cards_list_view.setAdapter(deckCardRecycleAdapter);
And here is my onBindViewHolder function in adapter.
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
typeface = Typeface.createFromAsset(context.getAssets(), "fonts/futura-medium.otf");
viewHolder.user_name.setTypeface(typeface);
viewHolder.user_name.setText(cards.get(position).getName().toString());
viewHolder.position.setTypeface(typeface);
viewHolder.position.setText(cards.get(position).getPosition().toString());
viewHolder.dot.setTypeface(typeface);
viewHolder.event_saved.setTypeface(typeface);
if(cards.get(position).getEvent_name().toString().equals("None")) {
viewHolder.event_saved.setVisibility(View.GONE);
viewHolder.dot.setVisibility(View.GONE);
}
else
viewHolder.event_saved.setText(cards.get(position).getEvent_name().toString());
viewHolder.date_saved.setTypeface(typeface);
String timestamp = cards.get(position).getTimestamp().toString();
viewHolder.date_saved.setText(toDate(timestamp));
if(cards.get(position).image_url.toString().equals("None"))
viewHolder.user_image.setImageResource(R.drawable.anonymous);
else {
String url_image = cards.get(position).image_url.toString();
Picasso.with(this.context).cancelRequest(viewHolder.user_image);
Picasso.with(context).load(url_image).into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
viewHolder.user_image.setImageBitmap(bitmap);
cards.get(position).setImage_url(getStringImage(bitmap));
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
}
Please help. Thanks in advance.
I don't think it's a good idea to reload data each time, it's make a lot of performance instead you can create interface and let the item listening to it, and just with one line of code you can change the visibility
Check this answer
interface Listener {
public void onVisibilityChanged(bool visible);
}
create an interface (set bool parameter for visible/invisible)
Create separate class for manage listener's (like this)
add listener for each item (make checkbox visible or invisible)
remove listener when item removed (avoid NullpointException)
clear listener's if recycler reset (avoid NullpointException)
call the method that have foreach and all the listeners will be triged
I know there are lot of ways to have an empty view for a RecyclerView. But my question is for FirebaseRecyclerView.
My layout is:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/feed_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<ProgressBar
android:id="#+id/feed_loading"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout>
So I am showing Loading ProgressBar before the RecyclerView fills its items. Now what if server doesn't have any item. In this situation my RecyclerView is empty always and my Loading ProgressBar always visible to user.
So instead of showing the ProgressBar for indefinite period, I want to show some empty layout. E.g. "No Data Found" or something similar message.
The final result should be: ProgressBar should be shown until data is loaded to RecyclerView and once data is loaded ProgressBar should be invisible. But if no data is present in server, some empty layout should be shown instead of ProgressBar.
In normal RecyclerView, we have a dataset (some ArrayList, etc) and if it is empty then we can show that empty layout. But in case of FirebaseRecyclerAdapter, I dont have the reference of Snapshot in my Activity or Context. Nor I have any callback which tells me that no data is present in server.
Any workaround will help a lot.
Here is what I would try. First check out the accepted answer to the question linked below. It provides some very good insight into how Firebase queries work. I'd consider the info trusted since the answer is by someone on the Firebase team:
How to separate initial data load from incremental children with Firebase?
So, based on the answer to the question linked above and the fact that the FirebaseRecyclerAdapter is backed by a FirebaseArray which is populated using a ChildEventListener I would add a Single value event listener on the same database reference used to populate your FirebaseRecyclerAdapter. Something like this:
//create database reference that will be used for both the
//FirebaseRecyclerAdapter and the single value event listener
dbRef = FirebaseDatabase.getInstance().getReference();
//setup FirebaseRecyclerAdapter
mAdapter = new FirebaseRecyclerAdapter<Model, YourViewHolder>(
Model.class, R.layout.your_layout, YourViewHolder.class, dbRef) {
#Override
public void populateViewHolder(YourViewHolder holder, Model model, int position){
//your code for populating each recycler view item
};
mRecyclerView.setAdapter(mAdapter);
//add the listener for the single value event that will function
//like a completion listener for initial data load of the FirebaseRecyclerAdapter
dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//onDataChange called so remove progress bar
//make a call to dataSnapshot.hasChildren() and based
//on returned value show/hide empty view
//use helper method to add an Observer to RecyclerView
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
That would handle the initial setup of the RecyclerView. When onDataChange is called on the single value event listener use a helper method to add an observer to the FirebaseRecyclerAdapter to handle any subsequent additions/deletions to database location.
mObserver = new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
//perform check and show/hide empty view
}
#Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
//perform check and show/hide empty view
}
};
mAdapter.registerAdapterDataObserver(mObserver);
Answer from: https://stackoverflow.com/a/40204298/2170278
the FirebaseUI adapters nowadays have an onDataChanged() method that you can override to detect when they're done loading a set of data.
See the source code on github. From there:
This method will be triggered each time updates from the database have been completely processed. So the first time this method is called, the initial data has been loaded - including the case when no data at all is available. Each next time the method is called, a complete update (potentially consisting of updates to multiple child items) has been completed.
You would typically override this method to hide a loading indicator (after the initial load) or to complete a batch update to a UI element.
The FirebaseUI sample app overrides onDataChanged() to hide its "loading" indicator:
public void onDataChanged() {
// If there are no chat messages, show a view that invites the user to add a message.
mEmptyListMessage.setVisibility(getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
I have a recyclerView in which i have a list of items displayed in a LinearLayout.There is a "increase" button in every list which will increment a quantity by "1".But when I click the button on the first list item to increment the number..the incremented value is displayed in the last list item of the recyclerView not in the desired position where i clicked.Can anyone help me find the solution?
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
myholder = holder;
holder.item_name_text.setText(data.get(position).getName());
holder.item_price_text.setText(data.get(position).getPrice().toString());
holder.item_quantity_text.setText("500");
//Adding item to the cart
holder.add_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(totalItem>=0 && totalItem<10){
totalItem++;
myholder.item_totalquantity_text.setText(String.valueOf(totalItem));
}else{
Toast.makeText(myholder.itemView.getContext(),"Cannot add more item",Toast.LENGTH_SHORT).show();
}
}
});
So I always think of recyclerviews as the frontend that displays my data. If you would like to make changes to the actual data itself and make sure it gets reflected in the recyclerview, you will need to ensure the changes are made inside the arraylist of data objects.
You will need to add a field inside the data object and call it counter. Then you must increment the counter once the user clicks on the onClickListener.
myholder.item_totalquantity_text.setText(data.get(position).setCounter(data.get(position).getCounter())+1);
Do not set OnClickListener() in onBindViewHolder(). Instead do it in your ViewHolder class itself. And main ly as RecyclerView re-uses the holder objects to represent the new set of data that is becoming visible. So the listener on which yo click might be belonging to some other view holder so it appears there instead.
Have a quick read of this and this. These are not very relevant to you but it has info to understnad recycling concept so you can fix your stuff easily.