Android ListView with section headers and footers?

牧云@^-^@ 提交于 2020-01-06 08:12:10

问题


I want create the custom list to inflate the different data for each row by grouping the data I managed to get each section headers by the type of Data but I want to add the footer for each section as well. I don't know how to execute it

I tried to return the section footer by getitemviewtype() but it has to be return in everyitem type so don't know how to execute it

public override View GetView(int position, View convertView, ViewGroup parent)
    {
        programTabAllItemHolder programTabAllItemHolder;
        View view = convertView;
        if (view == null)
        {
            programTabAllItemHolder = new programTabAllItemHolder();
            if (GetItemViewType(position) == 0)
            {
                view = LayoutInflater.From(context).Inflate(Resource.Layout.FTSProgramItemLayout, parent, false);
                programTabAllItemHolder.searchprogramdate = view.FindViewById<TextView>(Resource.Id.searchdate);
                programTabAllItemHolder.searchprogramtime = view.FindViewById<TextView>(Resource.Id.searchtime);
                programTabAllItemHolder.searchProgramTitle = view.FindViewById<TextView>(Resource.Id.searchprogramtitle);
                programTabAllItemHolder.linearsearchdatetime = view.FindViewById<RelativeLayout>(Resource.Id.linearsearchdatetime);
                programTabAllItemHolder.programseparator = view.FindViewById<View>(Resource.Id.programline);
                programTabAllItemHolder.searchprogramresults = view.FindViewById<TextView>(Resource.Id.searchprogramresults);

            }
            else if (GetItemViewType(position) == 1)
            {
                view = LayoutInflater.From(context).Inflate(Resource.Layout.FTSParticipantItemLayout, parent, false);
                programTabAllItemHolder.initialsView = view.FindViewById<TextView>(Resource.Id.searchparticipantinitialsView);
                programTabAllItemHolder.Listimageview = view.FindViewById<ImageView>(Resource.Id.searchparticipantlistimageView);
                programTabAllItemHolder.searchParticipantTitle = view.FindViewById<TextView>(Resource.Id.searchparticipanttitle);
                programTabAllItemHolder.searchparticipantresults = view.FindViewById<TextView>(Resource.Id.searchparticipantresults);
            }
            else if (GetItemViewType(position) == 2)
            {
                view = LayoutInflater.From(context).Inflate(Resource.Layout.FTSInformationItemLayout, parent, false);
                programTabAllItemHolder.searchinformationlistimageView = view.FindViewById<ImageView>(Resource.Id.searchinformationlistimageView);
                programTabAllItemHolder.searchinformationtitle = view.FindViewById<TextView>(Resource.Id.searchinformationtitle);
                programTabAllItemHolder.searchinformationresults = view.FindViewById<TextView>(Resource.Id.searchinformationresults);

            }

            view = LayoutInflater.From(context).Inflate(Resource.Layout.SearchFooterView, parent, false);
            programTabAllItemHolder.searchfooterview = view.FindViewById<LinearLayout>(Resource.Id.ftsfooterview);


            view.Tag = programTabAllItemHolder;
        }
        else
        {
            programTabAllItemHolder = view.Tag as programTabAllItemHolder;
        }

        if (GetItemViewType(position) == 0)
        {
            // setColorsforprogram
            SetViewStyleforProgram(programTabAllItemHolder);
            programTabAllItemHolder.searchProgramTitle.Text = programVTs[position].Title;
            programTabAllItemHolder.searchprogramdate.Text = programVTs[position].StartDate.ToString("dd MMM");
            programTabAllItemHolder.searchprogramtime.Text = programVTs[position].StartDate.ToString("hh:mm tt");
        }


        // participant view
        else if (GetItemViewType(position) == 1)
        {
            programTabAllItemHolder.searchParticipantTitle.Text = programVTs[position].FirstName + programVTs[position].LastName;
            //If profile icon is missing then show initials of First Name and Last Name ahead
            if (string.IsNullOrEmpty(programVTs[position].IconUrl))
            {
                programTabAllItemHolder.Listimageview.Visibility = ViewStates.Gone;
                programTabAllItemHolder.initialsView.Visibility = ViewStates.Visible;
                programTabAllItemHolder.initialsView.Text = Utils.getUserFirstandLastChar(programVTs[position].FirstName, programVTs[position].LastName);
                programTabAllItemHolder.initialsView.SetTextColor(Color.ParseColor(Utils.topNavForegroundColor));

                //Round background image of initials
                GradientDrawable initialsShape = new GradientDrawable();
                initialsShape.SetShape(ShapeType.Oval);
                initialsShape.SetCornerRadius(100f);
                initialsShape.SetColor(Color.ParseColor(Utils.topNavBackgroundColor));
                initialsShape.SetStroke(1, Color.ParseColor(Utils.topNavBackgroundColor));

                //Invert the colors if theme is light
                if (!Util.IsColorDark(Color.ParseColor(Utils.topNavBackgroundColor)))
                {
                    initialsShape.SetColor(Color.ParseColor(Utils.topNavForegroundColor));
                    initialsShape.SetStroke(1, Color.ParseColor(Utils.topNavForegroundColor));
                    programTabAllItemHolder.initialsView.SetTextColor(Color.ParseColor(Utils.topNavBackgroundColor));
                }

                programTabAllItemHolder.initialsView.SetBackgroundDrawable(initialsShape);
            }
            else
            {
                programTabAllItemHolder.initialsView.Visibility = ViewStates.Gone;
                MyApp.picassoWithCache.Load(programVTs[position].IconUrl).Into(programTabAllItemHolder.Listimageview);
            }
            //int check = position + 1;
            //if ( check%3 == 0)
            //{
            //    programTabAllItemHolder.seachparticipantsshowmore.Visibility = ViewStates.Visible;
            //}

        }
        else if (GetItemViewType(position) == 2)
        {
            programTabAllItemHolder.searchinformationtitle.Text = programVTs[position].Title;
            if (string.IsNullOrEmpty(programVTs[position].IconUrl))
            {
                programTabAllItemHolder.searchinformationlistimageView.SetImageResource(Resource.Drawable.linked_info_default_icon);
            }
            else
            {
                MyApp.picassoWithCache.Load(programVTs[position].IconUrl).Into(programTabAllItemHolder.searchinformationlistimageView);
            }

        }



        return view;
    }

回答1:


You can create a custom view, inflate it then can use like this:

View headerView = getLayoutInflater().inflate(R.layout.listview_header, null);
listView.addHeaderView(headerView);

For more information, you can check this link




回答2:


There are a number of ways to achieve this but because you don't give any code examples for your Adapter and data structure so it is difficult to give an exact answer.

Edit Update After getView was added:

It looks like your Data Structure is an Array of Objects You just need to Override the getItemViewType method as I did below to return the right type for the contents of the Current Object.

This could be done by adding a new member variable to you Object to indicate the row type.

e.g. programVTs[position].rowType with values of 0 or 1 or 2 depending on row type

Then your getItemViewType could look something like:-

@Override
    public int getItemViewType(int position) {
        return programVTs[position].rowType;
}

OR

I think you could deduce the row type from the content

pseudocode below for getItemViewType

if (programVTs[position].Title and programVTs[position].StartDate are not null or empty)
return 0;

else if (programVTs[position].FirstName and programVTs[position].LastName are not null or empty)
return 1;

else return 2;

End Update

BUT there is a common theme on how section headers are usually added.

Section headers are usually inserted as normal listview rows in the dataset but are a different Object type or has addition member variable to denote they are a header.

When the getView method of the Adapter processes the item it checks the Object type or member variable to format that row as a normal item or section header row.

This method can easily be expanded to add footers as well, you need to insert an extra data item that has the properties that cause getView to treat it like a footer.

One way of doing it:- Create some Java objects for Header and Footers Rows (Normal rows just use a String Object) Create a list of generic Objects for your Adapter to process Then the Adapter checks the type of Object is in the list and processes accordingly


public class Footer {

    public String itemText;

    public Footer(String text){
        itemText = text;
    }
}

public class Header {

    public String itemText;

    public Header(String text){
        itemText = text;
    }
}

public class ItemAdapter extends BaseAdapter {

    private ArrayList<Object> mData;
    private LayoutInflater mInflater;

    private static final int NORMAL_ITEM = 0;
    private static final int HEADER_ITEM = 1;
    private static final int FOOTER_ITEM = 2;

    public ItemAdapter(Context context, ArrayList<Object> data){
        mData = data;
        mInflater = (LayoutInflater.from(context));
    }

    @Override
    public int getCount(){
        return mData.size();
    }

    @Override
    public Object getItem(int position){
        return mData.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getViewTypeCount() {
        return 3;
    }

    @Override
    public int getItemViewType(int position) {
        Object mObject = getItem(position);
        if (mObject instanceof String){
            return NORMAL_ITEM;
        } else if (mObject instanceof Header) {
            return HEADER_ITEM;
        } else if (mObject instanceof Footer) {
            return FOOTER_ITEM;
        } else {
            return IGNORE_ITEM_VIEW_TYPE;
        }
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        int rowType = getItemViewType(position);
        Object object = getItem(position);

        View view;
        TextView textView;

        // In this simple case all row items are inflated as Textview's to contain the string
        // With the background color changed after inflation
        // But each object could use a different layout for each object type
        // e.g An ImageView, etc
        switch (rowType) {
            case NORMAL_ITEM:
                view = mInflater.inflate(R.layout.list_item, parent, false);
                textView = (TextView) view.findViewById(R.id.list_item);
                textView.setText((String) object);
                break;
            case HEADER_ITEM:
                view = mInflater.inflate(R.layout.list_item, parent, false);
                textView = (TextView) view.findViewById(R.id.list_item);
                // Set the background to red because it is a Header row
                textView.setBackgroundColor(Color.RED);
                // Cast the object from generic list to Header type
                Header header = (Header) object;
                textView.setText(header.itemText);
                break;
            case FOOTER_ITEM:
                view = mInflater.inflate(R.layout.list_item, parent, false);
                textView = (TextView) view.findViewById(R.id.list_item);
                // Set the background to green because it is a Header row
                textView.setBackgroundColor(Color.GREEN);
                Footer footer = (Footer) object;
                textView.setText(footer.itemText);
                break;

                default:
                    return convertView;

        }

        return view;
    }

}

public class MainActivity extends AppCompatActivity {

    private ItemAdapter mAdapter;
    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create the dataset for the Adapter
        ArrayList<Object> mList = new ArrayList<Object>();
        mList.add(new Header("Header 1"));
        mList.add("Item 1");
        mList.add("Item 2");
        mList.add(new Footer("Footer 1"));
        mList.add(new Header("Header 2"));
        mList.add("Item 3");
        mList.add(new Footer("Footer 2"));

        // Create Adapter
        mAdapter = new ItemAdapter(this, mList);

        listView = (ListView) findViewById(R.id.listView);
        listView.setAdapter(mAdapter);
    }
}

activity_main.xml

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

list_item.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="match_parent">

    <TextView
        android:id="@+id/list_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>



This will produce a view like



来源:https://stackoverflow.com/questions/57873565/android-listview-with-section-headers-and-footers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!