Android ListView 标头 [英] Android ListView headers

查看:31
本文介绍了Android ListView 标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 ListView 上有某种事件.事件按天排序,我希望每天都有带有日期的标题,然后在下面监听事件.

这是我填充该列表的方式:

ArrayListcrs = new ArrayList();crs.add(new TwoText("This will be header", event.getDate()));对于(事件事件:事件){crs.add(new TwoText(event.getStartString() + "-" + event.getEndString(), event.getSubject()));}arrayAdapter = new TwoTextArrayAdapter(this, R.layout.my_list_item, crs);lv1.setAdapter(arrayAdapter);

这就是我的 TwoText 类的样子:

public class TwoText {公共字符串类ID;公共字符串状态;public TwoText(字符串类ID,字符串状态){this.classID = classID;this.state = 状态;}}

这就是我的 TwoTextArrayAdapter 类的样子:

import java.util.ArrayList;导入 android.app.Activity;导入 android.content.Context;导入 android.view.LayoutInflater;导入 android.view.View;导入 android.view.ViewGroup;导入 android.widget.ArrayAdapter;导入 android.widget.TextView;公共类 TwoTextArrayAdapter 扩展了 ArrayAdapter{私有 ArrayList班级;私人活动骗局;文本视图分隔符;公共 TwoTextArrayAdapter(活动上下文,int textViewResourceId,ArrayList 类){超级(上下文,textViewResourceId,类);this.con = 上下文;this.classes = 类;}@覆盖public View getView(int position, View convertView, ViewGroup parent) {视图 v = 转换视图;如果(v == 空){LayoutInflater vi = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);v = vi.inflate(R.layout.my_list_item, null);}TwoText user = classes.get(position);如果(用户!= null){TextView content1 = (TextView) v.findViewById(R.id.list_content1);TextView content2 = (TextView) v.findViewById(R.id.list_content2);如果(内容 1 != 空){content1.setText(user.classID);}if(content2 != null) {content2.setText(user.state);}}返回 v;}}

这是 my_list_item.xml

<文本视图style="?android:attr/listSeparatorTextViewStyle"android:id="@+id/分隔符"机器人:文本=标题"android:layout_width="fill_parent"android:layout_height="wrap_content"机器人:背景=#757678"android:textColor="#f5c227"/><线性布局xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"机器人:方向=水平"><文本视图android:id="@+id/list_content1"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_margin="5dip"机器人:可点击=假"机器人:重力=中心"机器人:longClickable =假"机器人:paddingBottom =1dip"android:paddingTop="1dip"机器人:文本=样本"android:textColor="#ff7f1d"android:textSize="17dip"android:textStyle="粗体"/><文本视图android:id="@+id/list_content2"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_margin="5dip"机器人:可点击=假"机器人:重力=中心"机器人:链接点击=假"机器人:longClickable =假"机器人:paddingBottom =1dip"android:paddingTop="1dip"机器人:文本=样本"android:textColor="#6d6d6d"android:textSize="17dip"/></LinearLayout></LinearLayout>

我目前所做的是将标题添加为常规列表对象,但我希望将其作为标题,并且在我的情况下有日期.

我的 xml 中有此代码用于标题:

我尝试在不需要时隐藏它并在需要时显示它,但我只是搞砸了我的其余代码.我尝试了更多教程,但它们也有相同的效果.

有人能指导我如何做这种简单的方法吗?

解决方案

这是我的做法,关键是 getItemViewTypeAdapter 类中的 rel="noreferrer">getViewTypeCount.getViewTypeCount 返回列表中有多少类型的项目,在本例中,我们有一个标题项目和一个事件项目,所以有两个.getItemViewType 应该返回我们在输入 position 处有什么类型的 View.

Android 将负责在 convertView 中自动向您传递正确类型的 View.

以下代码的结果如下所示:

首先我们有一个接口,我们的两个列表项类型将实现

公共接口项{公共 int getViewType();public View getView(LayoutInflater inflater, View convertView);}

然后我们有一个接受 Item

列表的适配器

public class TwoTextArrayAdapter extends ArrayAdapter{私人 LayoutInflater mInflater;公共枚举行类型 {LIST_ITEM、HEADER_ITEM}public TwoTextArrayAdapter(上下文上下文,列表<项目>项目){超级(上下文,0,项目);mInflater = LayoutInflater.from(context);}@覆盖公共 int getViewTypeCount() {返回 RowType.values().length;}@覆盖公共 int getItemViewType(int position) {返回 getItem(position).getViewType();}

<块引用>

@Overridepublic View getView(int position, View convertView, ViewGroup parent) {返回 getItem(position).getView(mInflater, convertView);}

编辑更好的性能..滚动时可以注意到

private static final int TYPE_ITEM = 0;私有静态最终 int TYPE_SEPARATOR = 1;public View getView(int position, View convertView, ViewGroup parent) {ViewHolder 持有人 = null;int rowType = getItemViewType(position);查看视图;if (convertView == null) {持有人 = 新的 ViewHolder();开关(行类型){案例 TYPE_ITEM:convertView = mInflater.inflate(R.layout.task_details_row, null);holder.View=getItem(position).getView(mInflater, convertView);休息;案例 TYPE_SEPARATOR:convertView = mInflater.inflate(R.layout.task_detail_header, null);holder.View=getItem(position).getView(mInflater, convertView);休息;}convertView.setTag(holder);}别的{持有人 = (ViewHolder) convertView.getTag();}返回转换视图;}公共静态类 ViewHolder {公共视图;}}

然后我们有类来实现Item 并扩展正确的布局.在您的情况下,您将拥有一个 Header 类和一个 ListItem 类.

 public class Header 实现 Item {私有最终字符串名称;公共标题(字符串名称){this.name = 名称;}@覆盖公共 int getViewType() {返回 RowType.HEADER_ITEM.ordinal();}@覆盖公共视图 getView(LayoutInflater inflater, View convertView) {查看视图;if (convertView == null) {视图 = (视图) inflater.inflate(R.layout.header, null);//做一些初始化} 别的 {视图 = 转换视图;}TextView text = (TextView) view.findViewById(R.id.separator);text.setText(name);返回视图;}}

然后是 ListItem

 公共类 ListItem 实现了 Item {私有最终字符串str1;私有最终字符串 str2;公共列表项(字符串文本1,字符串文本2){this.str1 = text1;this.str2 = text2;}@覆盖公共 int getViewType() {返回 RowType.LIST_ITEM.ordinal();}@覆盖公共视图 getView(LayoutInflater inflater, View convertView) {查看视图;if (convertView == null) {视图 = (视图) inflater.inflate(R.layout.my_list_item, null);//做一些初始化} 别的 {视图 = 转换视图;}TextView text1 = (TextView) view.findViewById(R.id.list_content1);TextView text2 = (TextView) view.findViewById(R.id.list_content2);text1.setText(str1);text2.setText(str2);返回视图;}}

还有一个简单的Activity来显示它

public class MainActivity extends ListActivity {@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);列表<项目>items = new ArrayList();items.add(new Header("Header 1"));items.add(new ListItem("Text 1", "Rabble rabble"));items.add(new ListItem("Text 2", "Rabble rabble"));items.add(new ListItem("Text 3", "Rabble rabble"));items.add(new ListItem("Text 4", "Rabble rabble"));items.add(new Header("Header 2"));items.add(new ListItem("Text 5", "Rabble rabble"));items.add(new ListItem("Text 6", "Rabble rabble"));items.add(new ListItem("Text 7", "Rabble rabble"));items.add(new ListItem("Text 8", "Rabble rabble"));TwoTextArrayAdapter 适配器 = new TwoTextArrayAdapter(this, items);setListAdapter(适配器);}}

R.layout.header

的布局

<文本视图style="?android:attr/listSeparatorTextViewStyle"android:id="@+id/分隔符"机器人:文本=标题"android:layout_width="fill_parent"android:layout_height="wrap_content"机器人:背景=#757678"android:textColor="#f5c227"/></LinearLayout>

R.layout.my_list_item 的布局

<文本视图android:id="@+id/list_content1"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_margin="5dip"机器人:可点击=假"机器人:重力=中心"机器人:longClickable =假"机器人:paddingBottom =1dip"android:paddingTop="1dip"机器人:文本=样本"android:textColor="#ff7f1d"android:textSize="17dip"android:textStyle="粗体"/><文本视图android:id="@+id/list_content2"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_margin="5dip"机器人:可点击=假"机器人:重力=中心"机器人:链接点击=假"机器人:longClickable =假"机器人:paddingBottom =1dip"android:paddingTop="1dip"机器人:文本=样本"android:textColor="#6d6d6d"android:textSize="17dip"/></LinearLayout>

R.layout.activity_main.xml 的布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"工具:context=".MainActivity" ><列表视图android:id="@android:id/列表"android:layout_width="fill_parent"android:layout_height="fill_parent"/></RelativeLayout>

你也可以变得更有趣,使用 ViewHolders、异步加载内容或任何你喜欢的东西.

I have ListView that has some kind of events on it. Events are sorted by day, and I would like to have header with date on it for every day, and then events listen below.

Here is how I populate that list:

ArrayList<TwoText> crs = new ArrayList<TwoText>();

crs.add(new TwoText("This will be header", event.getDate()));

for (Event event : events) {
    crs.add(new TwoText(event.getStartString() + "-" + event.getEndString(), event.getSubject()));
}

arrayAdapter = new TwoTextArrayAdapter(this, R.layout.my_list_item, crs);
lv1.setAdapter(arrayAdapter);

and this is how my class TwoText looks:

public class TwoText {
    public String classID;
    public String state;

    public TwoText(String classID, String state) {
        this.classID = classID;
        this.state = state;
    }
}

and this is how my TwoTextArrayAdapter class looks:

import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class TwoTextArrayAdapter extends ArrayAdapter<TwoText> {

    private ArrayList<TwoText> classes;
    private Activity con;
    TextView seperator;

    public TwoTextArrayAdapter(Activity context, int textViewResourceId, ArrayList<TwoText> classes) {
        super(context, textViewResourceId, classes);
        this.con = context;
        this.classes = classes;

    }

    @Override

    public View getView(int position, View convertView, ViewGroup parent) {

        View v = convertView;

        if (v == null) {

            LayoutInflater vi = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            v = vi.inflate(R.layout.my_list_item, null);

        }

        TwoText user = classes.get(position);

        if (user != null) {

            TextView content1 = (TextView) v.findViewById(R.id.list_content1);

            TextView content2 = (TextView) v.findViewById(R.id.list_content2);

            if (content1 != null) {

                content1.setText(user.classID);
            }   
            if(content2 != null) {

                content2.setText(user.state);
            }
        }
        return v;
    }
}

and this is my_list_item.xml

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

    <TextView
        style="?android:attr/listSeparatorTextViewStyle"
        android:id="@+id/separator"
        android:text="Header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#757678"
        android:textColor="#f5c227" />

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/list_content1"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_margin="5dip"
            android:clickable="false"
            android:gravity="center"
            android:longClickable="false"
            android:paddingBottom="1dip"
            android:paddingTop="1dip"
            android:text="sample"
            android:textColor="#ff7f1d"
            android:textSize="17dip"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/list_content2"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_margin="5dip"
            android:clickable="false"
            android:gravity="center"
            android:linksClickable="false"
            android:longClickable="false"
            android:paddingBottom="1dip"
            android:paddingTop="1dip"
            android:text="sample"
            android:textColor="#6d6d6d"
            android:textSize="17dip" />
    </LinearLayout>

</LinearLayout>

what I do at the moment is that I am adding header just as regular list object, but Id like it to be as header and in my case have a date on it.

I have this code in my xml for header:

<TextView
        style="?android:attr/listSeparatorTextViewStyle"
        android:id="@+id/separator"
        android:text="Header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#757678"
        android:textColor="#f5c227" />

and I tried hiding it when it is unneccessary and showing it when neccessary but I just messed up rest of my code. I tried few more tutorials but they also had same effect.

Could anyone guide me on how to do that easy way?

解决方案

Here's how I do it, the keys are getItemViewType and getViewTypeCount in the Adapter class. getViewTypeCount returns how many types of items we have in the list, in this case we have a header item and an event item, so two. getItemViewType should return what type of View we have at the input position.

Android will then take care of passing you the right type of View in convertView automatically.

Here what the result of the code below looks like:

First we have an interface that our two list item types will implement

public interface Item {
    public int getViewType();
    public View getView(LayoutInflater inflater, View convertView);
}

Then we have an adapter that takes a list of Item

public class TwoTextArrayAdapter extends ArrayAdapter<Item> {
    private LayoutInflater mInflater;

    public enum RowType {
        LIST_ITEM, HEADER_ITEM
    }

    public TwoTextArrayAdapter(Context context, List<Item> items) {
        super(context, 0, items);
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getViewTypeCount() {
        return RowType.values().length;

    }

    @Override
    public int getItemViewType(int position) {
        return getItem(position).getViewType();
    }

@Override
public View getView(int position, View convertView, ViewGroup parent) {
   return getItem(position).getView(mInflater, convertView);
}

EDIT Better For Performance.. can be noticed when scrolling

private static final int TYPE_ITEM = 0; 
private static final int TYPE_SEPARATOR = 1; 

public View getView(int position, View convertView, ViewGroup parent)  {
    ViewHolder holder = null;
    int rowType = getItemViewType(position);
    View View;
    if (convertView == null) {
        holder = new ViewHolder();
        switch (rowType) {
            case TYPE_ITEM:
                convertView = mInflater.inflate(R.layout.task_details_row, null);
                holder.View=getItem(position).getView(mInflater, convertView);
                break;
            case TYPE_SEPARATOR:
                convertView = mInflater.inflate(R.layout.task_detail_header, null);
                holder.View=getItem(position).getView(mInflater, convertView);
                break;
        }
        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    }
    return convertView; 
} 

public static class ViewHolder {
    public  View View; } 
}

Then we have classes the implement Item and inflate the correct layouts. In your case you'll have something like a Header class and a ListItem class.

   public class Header implements Item {
    private final String         name;

    public Header(String name) {
        this.name = name;
    }

    @Override
    public int getViewType() {
        return RowType.HEADER_ITEM.ordinal();
    }

    @Override
    public View getView(LayoutInflater inflater, View convertView) {
        View view;
        if (convertView == null) {
            view = (View) inflater.inflate(R.layout.header, null);
            // Do some initialization
        } else {
            view = convertView;
        }

        TextView text = (TextView) view.findViewById(R.id.separator);
        text.setText(name);

        return view;
    }

}

And then the ListItem class

    public class ListItem implements Item {
    private final String         str1;
    private final String         str2;

    public ListItem(String text1, String text2) {
        this.str1 = text1;
        this.str2 = text2;
    }

    @Override
    public int getViewType() {
        return RowType.LIST_ITEM.ordinal();
    }

    @Override
    public View getView(LayoutInflater inflater, View convertView) {
        View view;
        if (convertView == null) {
            view = (View) inflater.inflate(R.layout.my_list_item, null);
            // Do some initialization
        } else {
            view = convertView;
        }

        TextView text1 = (TextView) view.findViewById(R.id.list_content1);
        TextView text2 = (TextView) view.findViewById(R.id.list_content2);
        text1.setText(str1);
        text2.setText(str2);

        return view;
    }

}

And a simple Activity to display it

public class MainActivity extends ListActivity {

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

        List<Item> items = new ArrayList<Item>();
        items.add(new Header("Header 1"));
        items.add(new ListItem("Text 1", "Rabble rabble"));
        items.add(new ListItem("Text 2", "Rabble rabble"));
        items.add(new ListItem("Text 3", "Rabble rabble"));
        items.add(new ListItem("Text 4", "Rabble rabble"));
        items.add(new Header("Header 2"));
        items.add(new ListItem("Text 5", "Rabble rabble"));
        items.add(new ListItem("Text 6", "Rabble rabble"));
        items.add(new ListItem("Text 7", "Rabble rabble"));
        items.add(new ListItem("Text 8", "Rabble rabble"));

        TwoTextArrayAdapter adapter = new TwoTextArrayAdapter(this, items);
        setListAdapter(adapter);
    }

}

Layout for R.layout.header

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

    <TextView
        style="?android:attr/listSeparatorTextViewStyle"
        android:id="@+id/separator"
        android:text="Header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#757678"
        android:textColor="#f5c227" />

</LinearLayout>

Layout for R.layout.my_list_item

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

    <TextView
        android:id="@+id/list_content1"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_margin="5dip"
        android:clickable="false"
        android:gravity="center"
        android:longClickable="false"
        android:paddingBottom="1dip"
        android:paddingTop="1dip"
        android:text="sample"
        android:textColor="#ff7f1d"
        android:textSize="17dip"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/list_content2"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_margin="5dip"
        android:clickable="false"
        android:gravity="center"
        android:linksClickable="false"
        android:longClickable="false"
        android:paddingBottom="1dip"
        android:paddingTop="1dip"
        android:text="sample"
        android:textColor="#6d6d6d"
        android:textSize="17dip" />

</LinearLayout>

Layout for R.layout.activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>

You can also get fancier and use ViewHolders, load stuff asynchronously, or whatever you like.

这篇关于Android ListView 标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆