Android:滚动时ListView标头丢失

时间:2014-04-24 14:48:27

标签: android android-layout listview android-listview

所以我有以下观点

list_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layoutSessionItem"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/lblGroupDate"
        style="@style/CustomText.GrayTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </TextView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/lblCourseCode"
            style="@style/CustomText.GrayText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/lblSessionCode"
            style="@style/CustomText.GrayText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</RelativeLayout>

所以基本上我从数据库中获得以下数据:

COURSE_CODE

SESSION_CODE

SESSION_DATE

我需要按SESSION_DATE对ListView项进行分组,我要做的是保留一个名为“PreviousDate”的变量,并将其与当前的SESSION_DATE进行比较,如果它不同,那么我启用带有ID的标头:“lblGroupDate”if日期是相同的我隐藏“lblGroupDate”。

这是我的适配器:

public class SessionListAdapter extends BaseAdapter {

    private Date PreviousDate = new Date();

    static class ViewHolder {
        TextView lblGroupDate;
        TextView lblCourseCode;
        TextView lblSessionCode;
    }

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

        ViewHolder holder;

        if (convertView == null) {
            convertView = mLayoutInflater.inflate(R.layout.list_view_item, null);

            holder = new ViewHolder();

            holder.lblGroupDate = (TextView) convertView.findViewById(R.id.lblGroupDate);
            holder.lblCourseCode = (TextView) convertView.findViewById(R.id.lblCourseCode);
            holder.lblSessionCode = (TextView) convertView.findViewById(R.id.lblSessionCode);
        } else {
            holder = (ViewHolder)convertView.getTag();
        }   

        SessionData session = (SessionData) getItem(position);

        if(session != null) {

            Date sessionDate = session.SESSION_DATE;

            if (!mPrevDate.equals(sessionDate)) {

                PreviousDate = sessionDate;

                // HIDE GROUP HEADER
                holder.lblGroupDate.setVisibility(View.GONE);
            }
            else {
                // SHOW GROUP HEADER
                holder.lblGroupDate.setVisibility(View.VISIBLE);
            }

            holder.lblCourseCode.setText(session.COURSE_CODE);
            holder.lblSessionCode.setText(session.SESSION_CODE);
        }
    }
}

这是问题

假设我有20条记录,当我向下滚动然后再次向上滚动时,启用了Group Header(lblGroupDate)的行在没有标题的情况下向上移动,标题被移动到接下来的3行。为什么会这样?

1 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为getView()可以随时从您的数据集中无序调用。您需要创建可以支持适配器的数据集。只需将适配器分类。稍后将用代码更新答案。

<强> SessionListAdapter.java

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.content.Context;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;


public class SessionListAdapter extends BaseAdapter
{
    private static final int TYPE_GROUP   = 0;
    private static final int TYPE_SESSION = 1;
    private static final int MAX_TYPES    = 2;

    private final LayoutInflater mLayoutInflater;
    private ArrayList<SessionViewData> mData;


    public SessionListAdapter(Context context, List<SessionData> sessionData)
    {
        mLayoutInflater = LayoutInflater.from(context);
        updateSessionViewData(sessionData);
    }

    public void updateSessionViewData(List<SessionData> sessionData)
    {
        Date previousDate = new Date();
        ArrayList<SessionViewData> data = new ArrayList<SessionViewData>();
        for(SessionData session: sessionData){
            if(!previousDate.equals(session.SESSION_DATE)){
                data.add(new SessionViewData(TYPE_GROUP, session));
                previousDate = session.SESSION_DATE;
            }
            data.add(new SessionViewData(TYPE_SESSION, session));
        }
        mData = data;
        notifyDataSetChanged();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        SessionViewData data = mData.get(position);

        if(convertView == null){
            final int layoutId;
            switch(data.type){
                case TYPE_GROUP:   layoutId = R.layout.list_session_group; break;
                case TYPE_SESSION: layoutId = R.layout.list_session_item;  break;
                default:
                    throw new IllegalArgumentException("Bad type for: " + data.session);
            }
            convertView = mLayoutInflater.inflate(layoutId, parent, false);
        }

        switch(data.type){
            case TYPE_GROUP:
                TextView lblGroupDate = ((TextView)convertView.findViewById(R.id.lblGroupDate));
                lblGroupDate.setText(DateUtils.formatDateTime(convertView.getContext(), 
                    data.session.SESSION_DATE.getTime(), DateUtils.FORMAT_SHOW_DATE));
                break;

            case TYPE_SESSION:
                TextView lblCourseCode  = (TextView)convertView.findViewById(R.id.lblCourseCode);
                lblCourseCode.setText(data.session.COURSE_CODE);
                TextView lblSessionCode = (TextView)convertView.findViewById(R.id.lblSessionCode);
                lblSessionCode.setText(data.session.SESSION_CODE);
                break;
        }

        return convertView;
    }

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

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

    @Override
    public int getItemViewType(int position)
    {
        return mData.get(position).type;
    }

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

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


    static class SessionViewData
    {
        int         type;
        SessionData session;


        public SessionViewData(int type, SessionData session)
        {
            this.type = type;
            this.session = session;
        }
    }
}

<强> list_session_group.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/lblGroupDate"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/CustomText.GrayTitle"
    />

<强> list_session_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layoutSessionItem"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
    <TextView
        android:id="@+id/lblCourseCode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/CustomText.GrayText"
        />
    <TextView
        android:id="@+id/lblSessionCode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/CustomText.GrayText"
        />
</LinearLayout>