У меня есть ListView, на котором есть какие-то события. События отсортированы по дням, и я хотел бы иметь заголовок с датой на каждый день, а затем события слушают ниже.
Вот как я заполняю этот список:
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);
и так выглядит мой класс TwoText:
public class TwoText {
public String classID;
public String state;
public TwoText(String classID, String state) {
this.classID = classID;
this.state = state;
}
}
и так выглядит мой класс TwoTextArrayAdapter:
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;
}
}
а это 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>
в данный момент я добавляю заголовок как обычный объект списка, но я бы хотел, чтобы он был как заголовок и в моем случае имел дату.
У меня есть этот код в моем xml для заголовка:
<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" />
и я пытался скрыть его, когда это не нужно, и показать его, когда это необходимо, но я просто испортил остальную часть своего кода. Я попробовал еще несколько уроков, но они также дали тот же эффект.
Может ли кто-нибудь посоветовать мне, как это сделать?
Вероятно, вы ищете ExpandableListView, у которого есть заголовки (группы) для разделения элементов (дочерних элементов).
Хороший учебник по этой теме: здесь .
источник
onGroupClick
обрабатывает только щелчок по «заголовкам», и вам не нужно отключать щелчок или что-то в этом роде, просто отмените любое действие свертывания и установите для всех групп расширение с самого начала.ExpandableListView
в большинстве случаев это лучше всего. Однако у меня бывает ситуация, когда я хочу иногда отображать плоский список, а в другое время - список с заголовками. К сожалению,ExpandableListAdapter
интерфейс не расширяет его,ListAdapter
поэтому для полиморфизма я вынужден использовать решение @antew.В качестве альтернативы есть хорошая сторонняя библиотека, разработанная только для этого варианта использования. При этом вам необходимо сгенерировать заголовки на основе данных, хранящихся в адаптере. Они называются адаптерами Rolodex и используются с
ExpandableListViews
. Их можно легко настроить так, чтобы они работали как обычный список с заголовками.Используя
Event
объекты OP и зная, что заголовки основаны наDate
связанных с ним ... код будет выглядеть примерно так:Активность
Адаптер
источник
Что я сделал, чтобы сделать Date (например, 01 декабря 2016 г.) заголовком. Я использовал библиотеку StickyHeaderListView
https://github.com/emilsjolander/StickyListHeaders
Преобразуйте дату в длинную дату в миллисекундах [не включая время] и сделайте ее идентификатором заголовка.
источник
Вот образец проекта , основанный на подробном и полезном ответе antew, который реализует
ListView
с несколькими заголовками, которые включают держатели представлений для повышения производительности прокрутки.В этом проекте объекты, представленные в,
ListView
являются экземплярами классаHeaderItem
или классаRowItem
, оба из которых являются подклассами абстрактного классаItem
. Каждый подклассItem
соответствует разному типу представления в настраиваемом адаптереItemAdapter
. МетодgetView()
наItemAdapter
делегатах создание представления для каждого элемента списка для индивидуальногоgetView()
метода на любомHeaderItem
илиRowItem
, в зависимости отItem
подкласса , используемого в позиции перешла кgetView()
методу на адаптере. КаждыйItem
подкласс предоставляет свой собственный держатель представления.Вьюхолдеры реализованы следующим образом. В
getView()
методы наItem
подклассы проверить лиView
объект , который был передан вgetView()
метод наItemAdapter
равна нулю. Если это так, соответствующий макет расширяется, и создается экземпляр объекта-держателя представления, который связывается с расширенным представлением черезView.setTag()
. ЕслиView
объект не равен нулю, значит, объект держателя представления уже был связан с представлением, и держатель представления извлекается черезView.getTag()
. Способ использования держателей представлений можно увидеть в следующем фрагменте кодаHeaderItem
:Полная реализация ListView приводится ниже. Вот код Java:
Также есть два макета элементов списка, по одному для каждого подкласса Item. Вот макет
header
, используемый HeaderItem:А вот макет
row
, используемый RowItem:Вот изображение части полученного ListView:
источник