3

I have spent some time trying to figure out how to add header/footer to my recyclerview but it is not working. the footer shows the but header and list item does not show on the emulator. My adapter

package com.example.system2.tranxav.adapters;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.example.system2.tranxav.R;
import com.example.system2.tranxav.model.Problems;

import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{

Context context;
private List<Problems> mDataset;
private static final int TYPE_HEADER = 0;
private static final int TYPE_FOOTER = 1;
private static final int TYPE_ITEM = 2;

public class ViewHolder extends RecyclerView.ViewHolder{
    public TextView tvProblems, tvPrice;
    public Button btnProblem;

    public ViewHolder(View itemView) {
        super(itemView);

    }
}

public void add(int position, Problems item){
    mDataset.add(position, item);
    notifyItemInserted(position);
}

public void remove(Problems item){
    int position = mDataset.indexOf(item);
    mDataset.remove(position);
    notifyItemRemoved(position);
}

public MyAdapter(List<Problems> myDataset){
    mDataset = myDataset;
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


    View itemView;
    Log.i("info", String.valueOf(viewType));
    if (viewType == TYPE_ITEM) {
        //Inflating recycle view item layout
        itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_problems, parent, false);
        ViewHolder vh = new ViewHolder(itemView);
        return  vh;
    } else if (viewType == TYPE_HEADER) {
        //Inflating header view
        itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.problem_recycler_header, parent, false);
        ViewHolder vh = new ViewHolder(itemView);
        return  vh;
    } else if (viewType == TYPE_FOOTER) {
        //Inflating footer view
        itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.problem_recycler_footer, parent, false);
        ViewHolder vh = new ViewHolder(itemView);
        return  vh;
    }
    throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    try {
    if (holder instanceof HeaderViewHolder) {
        HeaderViewHolder headerHolder = (HeaderViewHolder) holder;
        headerHolder.tvHeader.setText("Please kindly ask the mechanic what the problem is and check them to continue");

    } else if (holder instanceof FooterViewHolder) {
        FooterViewHolder footerHolder = (FooterViewHolder) holder;

        footerHolder.btnProblem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("info", "the button is clicked");
            }
        });
    }
    else if (holder instanceof ItemViewHolder) {
        ItemViewHolder itemView = (ItemViewHolder) holder;
        itemView.tvPrice.setText(mDataset.get(position).getPrice());
        itemView.tvProblems.setText(mDataset.get(position).getProblems());
    }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
@Override
public int getItemCount() {
    return mDataset.size()+2;
}

public int getItemViewType(int position) {


    if (position == 0) {
        return TYPE_HEADER;
    } else if (position == mDataset.size() + 1) {
        return TYPE_FOOTER;
    }
    return TYPE_ITEM;
}

private class HeaderViewHolder extends MyAdapter.ViewHolder {
    TextView tvHeader;

    public HeaderViewHolder(View view) {
        super(view);
        tvHeader = (TextView) view.findViewById(R.id.tvHeader);
    }
}
private class FooterViewHolder extends MyAdapter.ViewHolder {
    Button btnSubmitProblem;

    public FooterViewHolder(View view) {
        super(view);
        btnSubmitProblem = (Button) view.findViewById(R.id.btnProblem);
    }
}

private class ItemViewHolder extends MyAdapter.ViewHolder {
    TextView tvProblems, tvPrice;

    public ItemViewHolder(View itemView) {
        super(itemView);
        tvProblems = (TextView) itemView.findViewById(R.id.tvProblems);
        tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
    }
}

problem_recycler_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/tvHeader" />
 </LinearLayout>

footer_problem_recycler.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">

<Button
    android:text="Button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btnProblem" />
 </LinearLayout>

activity_problems.xml

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"

android:orientation="vertical"
android:paddingBottom="@dimen/zerodimen"
android:paddingLeft="@dimen/zerodimen"
android:paddingRight="@dimen/zerodimen"
android:paddingTop="16dp"
tools:context="com.example.system2.tranxav.ProblemsActivity">
<android.support.v7.widget.RecyclerView
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:paddingBottom="0dp"
    android:layout_marginBottom="0dp"
    android:scrollbars="none"
    android:id="@+id/problem_recycle_view"
    xmlns:android="http://schemas.android.com/apk/res/android" />

<TextView
    android:id="@+id/tvProblems"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:textSize="16dp"
    android:textStyle="bold" />

<TextView
    android:id="@+id/tvPrice"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:textStyle="bold" />

</LinearLayout>

I have checked through the code to know where the problem is but I cant figure it out. I am getting the data from my dataset but it does not display on the emulator.

James Z
  • 12,209
  • 10
  • 24
  • 44
user2940930
  • 93
  • 1
  • 9

2 Answers2

1

I think there is a small issue in position of onBindViewHolder

Can you change your code like this and give it a try.

else if (holder instanceof ItemViewHolder) {
        ItemViewHolder itemView = (ItemViewHolder) holder;
        itemView.tvPrice.setText(mDataset.get(position - 1).getPrice());
        itemView.tvProblems.setText(mDataset.get(position - 1).getProblems());
      } 

The issue with your code is you are returning the same viewholder you should change the code like this in onCreateViewHolder

    View itemView;
    Log.i("info", String.valueOf(viewType));
    if (viewType == TYPE_ITEM) {
        //Inflating recycle view item layout
        itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_problems, parent, false);
        ViewHolder vh = new ViewHolder(itemView);
        return  vh;
    } else if (viewType == TYPE_HEADER) {
        //Inflating header view
        itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.problem_recycler_header, parent, false);
        HeaderViewHolder vh = new HeaderViewHolder(itemView);
        return  vh;
    } else if (viewType == TYPE_FOOTER) {
        //Inflating footer view
        itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.problem_recycler_footer, parent, false);
        FooterViewHolder vh = new FooterViewHolder(itemView);
        return  vh;
    }
Sunil Sunny
  • 3,949
  • 4
  • 23
  • 53
  • The header and footer displays but the list does not display. Please can you check the code again. mDataset is not empty – user2940930 Mar 08 '18 at 13:46
  • @thanks is has worked but it showing me this error when I scroll to the bottom Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference – user2940930 Mar 08 '18 at 14:04
  • Post it as a separate question if the issue is still there ,but instead I will suggest you to read this https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it – Sunil Sunny Mar 08 '18 at 14:28
0

I had this problem and to make it simpler I used same layout for footer row as for all other rows.

So I did two relative layouts one below other. Top layout contains recycler, bottom layout contains footer added dynamically. Put both them in single relative layout and then put this in ScrollView.

Then I customized recyclerview a little to make it not cover entire screen vertically, so that both layouts are visible.

Final layout:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:scrollbars="vertical"
    android:background="@color/colorBG">

    <RelativeLayout
        android:id="@+id/layContent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <RelativeLayout
            android:id="@+id/layTop"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_alignParentTop="true">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:scrollbars="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/layBottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_alignParentBottom="true"
            android:layout_below="@id/layTop"
            android:background="@color/colorFooterBG">

            <!-- footer will be added here -->
        </RelativeLayout>
    </RelativeLayout>
</ScrollView>

And this code in onCreateView of fragment when setting up recycler:

private void setupFooterRecycler() {
    // use a linear layout manager
    RecyclerView.LayoutManager layManUS = new LinearLayoutManager(setupActivity().get());
    recycler.setLayoutManager(layManUS);
    recycler.addItemDecoration(new DividerItemDecoration(
            setupActivity().get(), LinearLayoutManager.VERTICAL));
    recycler.setNestedScrollingEnabled(true);
    // set fixed height
    DisplayMetrics displaymetrics = new DisplayMetrics();
    setupActivity().get().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
    // set recycler height to some percent of screen, needed to experiment
    int a =  (displaymetrics.heightPixels*70)/100;
    recycler.getLayoutParams().height =a;
    // use this setting to improve performance if you know that changes
    // in content do not change the layout size of the RecyclerView
    recycler.setHasFixedSize(true);
}

And here is how I add footer to layout in onCreateView of fragment, special thanks courtesy of acoustic:

View footerView = inflater.inflate(R.layout.footer_item,
            (ViewGroup) rootView.findViewById(R.id.layBottom));
10101101
  • 193
  • 1
  • 13