Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android recyclerview setVisibility View.GONE still occupies space

I want to list only the disliked items in my recyclerview. I have a full list of items in rv in MainActivity (did not set visibility here). I can set for each items like or dislike by clicking on imagebutton. The MainActivity shows full list of items (cardviews) that shows imagebutton likes or not. If item is liked, this is stored in firebase db as separate entry under Likes with item key (firebase key .push) and not under Items. (in firebase db I have Users, Items, Likes).

Here is my subactivity code, DislikedItemsActivity, where I want to show only items that are disliked by using setVisibility(View.GONE) for items that are liked. This still holds the space between items for the View.GONE items as well (though these cardviews are empty).

mRecyclerView = (RecyclerView) findViewById(R.id.rvItemList);
mRecyclerView .setHasFixedSize(true);

final LinearLayoutManager linearLayoutManager = new 
LinearLayoutManager(this);
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true); 

mRecyclerView.setLayoutManager(linearLayoutManager);

final FirebaseRecyclerAdapter<Item, MainActivity.ItemViewHolder> 
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Item, 
MainActivity.ItemViewHolder>(
            Item.class,
            R.layout.list_item,
            MainActivity.ItemViewHolder.class,
            mDatabase

    ) {
        @Override
        protected void populateViewHolder(final MainActivity.ItemViewHolder viewHolder, final Item model, final int position) {

            final String itemKey = getRef(position).getKey();

            mDatabaseItemsLiked.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {

        // if item is not liked, thus no user set in db ( I want to see only items that are liked in my recyclerview)
                    if (!dataSnapshot.child(itemKey).hasChild(mAuth.getCurrentUser().getUid())) {

                        viewHolder.mView.setVisibility(View.VISIBLE);

                        viewHolder.itemNameSetup(model.getItemName());
                        viewHolder.mView.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {

                                Intent itemSheetIntent = new Intent(DislikedItemsActivity.this, ItemSheetActivity.class);
                                adatlapIntent.putExtra("item_key", itemKey);
                                startActivity(itemSheetIntent);
                            }
                        });

                    } else {

                        viewHolder.mView.setVisibility(View.GONE);

                        mRecyclerView.getAdapter().notifyItemRemoved(position); //this puts together the visible items, but when scrolling, it gets messed up

        }

                }

                @Override
                public void onCancelled(DatabaseError databaseError) {
                    Log.e(TAG, databaseError.toString());
                }
            });
        }

        @Override
        public void onBindViewHolder(MainActivity.TermekViewHolder viewHolder, int position) {
            super.onBindViewHolder(viewHolder, position);

        }
    };
    mRecyclerView.setAdapter(firebaseRecyclerAdapter);
}

I looked for many solutions like onBindViewHolder, notifyDataChanged, set margin to 0, set layout size in xml to wrap_content. The best I could get is to have the not-liked items without space with mRecyclerView.getAdapter().notifyItemRemoved(position);, but scrolling the list backwards the whole rv gets messed up (duplicate entry, empty spaces, disordered list).

I don't know how to list only the disliked items from the complete item list from MainActivity rv in a new activity? My code above shows only disliked items, but only until I scroll to end of list, if I scroll backwards the rv gets messed up. I logged the positions of views (18items) in onBindViewHolder and first it counts all items in sequence (17,16,15,14...0), but scrolling from end of list to backwards the position jumps from 0 to 4 like 7times (changes always how many times) then it is the same for item 5,6, until item 17 (all of their positions showed in onBindViewHolder 7 or 8 times during scrolling ie. 5,5,5,5,6,6,6,6) and only for backward scrolling and during backward move rv shows only disliked items or empty views or duplicate entry of disliked item.

my xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="@drawable/hatter"
tools:context="com.example.user.itemlist.ItemsLikedActivity">

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rvItemList"
    >
</android.support.v7.widget.RecyclerView>

(don't know how to add pics) When disliked list appears, it shows first item (cardview takes up the full screen), and when I start to scroll the list (from 1. visible item to next visible item) if there is space(item1 vis and next vis item is 4), rearrange and I can see that next visible item(item4) moves to 1. visible item, then the rest of the list is arranged well, until I start to scroll back, then it rearranges the rv with spaces and with double entry. The list goes back and forth until both end (which is the length of full items list and not just the disliked items), but visible items gets all messed up.

like image 247
Zeghra Avatar asked Sep 18 '17 10:09

Zeghra


2 Answers

use this code to remove occupied space :

ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
params.height = 0;
holder.itemView.setLayoutParams(params);
like image 180
Hadi Ahmadi Avatar answered Sep 27 '22 18:09

Hadi Ahmadi


I found solution to filter the complete database. In my question I wanted to get only the liked/disliked items in a separate activity, though my previous code showed filtered items, but with gaps. In below code, I changed the DatabaseReferences (mDatabase -node with complete item list and mDatabaseItemsLiked -node with item uid and user uid).

This gave only empty cards with only number as the likedItems, but to get name from the mDatabase (complete list), I used dataSnapshot.getValue(Item.class).getItemName().

firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Item, 
MainActivity.ItemViewHolder>(
        Item.class,
        R.layout.list_item,
        MainActivity.ItemViewHolder.class,
        mDatabaseItemsLiked

) {
    @Override
    protected void populateViewHolder(final MainActivity.ItemViewHolder
            viewHolder, final Item model, final int position) {

        final String itemKey = getRef(position).getKey();

        mDatabase.child(itemKey).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
viewHolder.itemNameSetup(dataSnapshot.getValue(Item.class).getItemName());
viewHolder.mView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {

                            Intent itemSheetIntent = new Intent(LikedItemsActivity.this, ItemSheetActivity.class);
                            adatlapIntent.putExtra("item_key", itemKey);
                            startActivity(itemSheetIntent);
                        }
                    });

This works for me without any problem. I hope it is network efficient.

like image 23
Zeghra Avatar answered Sep 27 '22 18:09

Zeghra