Search code examples
androidfirebaseandroid-recyclerviewfirebaseui

Padding between Firebase RecyclerView items


I have been trying to get some padding between the Firebase RecyclerView items.I tried using ItemDecoration, but it works only with the first item of the RecyclerView. Would be a great help if you could point out my mistake.

This is what I get

What i Get

What I am trying to get is a layout where there is a padding between each recyclerview item so that I could see the shadow of each item.

Here's my Java code where I use the Firebase RecyclerView to load items.

public class CommunityFragment extends Fragment {
    private static final String KEY_RECYCLER_STATE = "";
    private RecyclerView mConvList;
    private DatabaseReference mConvDatabase;
    private DatabaseReference mUsersDatabase;
    private DatabaseReference mMessageDatabase;
    private Bundle mBundleRecyclerViewState;
    private Parcelable mListState;
    private static final String TAG = "ChatsFragment";

    public CommunityFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {


        View mMainView = inflater.inflate(R.layout.fragment_chats, container, false);

        mConvList = (RecyclerView) mMainView.findViewById(R.id.conv_list);
        FirebaseAuth mAuth = FirebaseAuth.getInstance();

        String mCurrent_user_id = Objects.requireNonNull(mAuth.getCurrentUser()).getUid();

        mConvDatabase = FirebaseDatabase.getInstance().getReference().child("Chat").child(mCurrent_user_id);
        mConvDatabase.keepSynced(true);

        mUsersDatabase = FirebaseDatabase.getInstance().getReference().child("Users");
        mUsersDatabase.keepSynced(true);

        mMessageDatabase = FirebaseDatabase.getInstance().getReference().child("messages").child(mCurrent_user_id);
        mMessageDatabase.keepSynced(true);

        mConvList = mMainView.findViewById(R.id.conv_list);
        mConvList.setHasFixedSize(true);
        mConvList.setLayoutManager(new LinearLayoutManager(getContext()));

        // Inflate the layout for this fragment
        return mMainView;
    }

    @Override
    public void onStart() {
        super.onStart();

        Query conversationQuery = mConvDatabase.orderByChild("timestamp");

        FirebaseRecyclerOptions<Conv> friendsFirebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Conv>()
                .setQuery(conversationQuery, Conv.class)
                .build();

        FirebaseRecyclerAdapter<Conv, ConvViewHolder> firebaseConvAdapter = new FirebaseRecyclerAdapter<Conv, ConvViewHolder>(friendsFirebaseRecyclerOptions) {
            @Override
            protected void onBindViewHolder(@NonNull final ConvViewHolder holder, int position, @NonNull final Conv model) {

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

                assert list_user_id != null;
                Query lastMessageQuery = mMessageDatabase.child(list_user_id).limitToLast(1);

                lastMessageQuery.addChildEventListener(new ChildEventListener() {

                    @Override
                    public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                        String data = Objects.requireNonNull(dataSnapshot.child("message").getValue()).toString();
                        String seen_ = Objects.requireNonNull(dataSnapshot.child("seen").getValue()).toString();
                        holder.setMessage(data, Boolean.parseBoolean(seen_));

                    }

                    @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) {

                    }
                });

                mUsersDatabase.child(list_user_id).addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                        final String userName = dataSnapshot.child("Name").getValue().toString();
                        holder.setName(userName);
                        holder.mView.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Intent chatIntent = new Intent(getContext(), ChatActivity.class);
                                chatIntent.putExtra("user_id", list_user_id);
                                chatIntent.putExtra("user_name",userName);
                                startActivity(chatIntent);
                            }
                        });

                    }


                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {

                    }
                });

            }
            @NonNull
            @Override
            public ConvViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
                View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_q_layout, viewGroup, false);
                return new ConvViewHolder(view);
            }
        };
        mConvList.addItemDecoration(new PaddingItemDecoration(200));
        firebaseConvAdapter.startListening();
        mConvList.setAdapter(firebaseConvAdapter);

    }

    public void onPause(){
        super.onPause();
        mBundleRecyclerViewState = new Bundle();
        mListState = mConvList.getLayoutManager().onSaveInstanceState();
        mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, mListState);
    }

    public void onResume(){
        super.onResume();
        if (mBundleRecyclerViewState != null) {
            new Handler().postDelayed(new Runnable() {

                @Override
                public void run() {
                    mListState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
                    mConvList.getLayoutManager().onRestoreInstanceState(mListState);

                }
            }, 50);
        }
        mConvList.setLayoutManager(new LinearLayoutManager(getContext()));
    }

    public  class ConvViewHolder extends RecyclerView.ViewHolder {

        View mView;

        public ConvViewHolder(@NonNull View itemView) {
            super(itemView);
            mView = itemView;
        }

        public void setName(String name){
            TextView userNameView = (TextView) mView.findViewById(R.id.question_title);
            userNameView.setText(name);
        }

        public void setMessage(String message, boolean isSeen) {
            TextView userStatusView = (TextView) mView.findViewById(R.id.question_catergory);

            //Log.i("textData", "State is " + isSeen);
            if(!isSeen){
                userStatusView.setText("New Message");
                userStatusView.setTypeface(userStatusView.getTypeface(), Typeface.BOLD);
            }else{
                userStatusView.setText("No New Messages");
                userStatusView.setTypeface(userStatusView.getTypeface(), Typeface.NORMAL);
            }

        }
    }

}

This is my PaddingItemDecoration class.

public class PaddingItemDecoration extends RecyclerView.ItemDecoration {
    private final int size;

    public PaddingItemDecoration(int size) {
        this.size = size;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

        // Apply offset only to first item
        if (parent.getChildAdapterPosition(view) == 0) {
            outRect.top += size;
            outRect.bottom += size;

        }
    }

And this is the XML file of my Adapter I use to load my RecyclerView items.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/relativeLayout3"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/message_text_background"
    android:elevation="4dp"
    android:padding="10dp">

    <TextView
        android:id="@+id/question_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:padding="10dp"
        android:text="Display Name"
        android:textColor="#020202"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/question_catergory"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:text="catergory"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/question_title" />

    <TextView
        android:id="@+id/counter_value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="counter"
        app:layout_constraintEnd_toStartOf="@+id/answers_given"
        app:layout_constraintTop_toBottomOf="@+id/question_title" />

    <TextView
        android:id="@+id/answers_given"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="answers"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/question_title" />

</androidx.constraintlayout.widget.ConstraintLayout>

Solution

  • Instead of using this PaddingItemDecoration, just add margin around your XML file of adapter.

    As I can see you already added padding to the parent constraint layout (try margin), so just remove your decoration class and just try simply printing list to screen, you should be good to go.

    Below image is an example of ListItem layout for adapter from my app, yours also should look like this one.

    Try to add margin 10dp

    enter image description here

    If you aren't able to do so, try implementing the way shown in this article.