Я пытаюсь сделать Android ListView собственными, настраиваемыми и так называемыми «виджетами».Android ListView ArrayAdapter не работает должным образом
Это мой виджет родительского класса:
public class Widget {
protected Context context;
protected int layout;
protected int headlineId;
protected int leftButtonId;
protected int rightButtonId;
protected int headlineTextId;
protected View fragment;
protected LayoutInflater inflater;
protected View widgetView;
protected TextView headline;
protected ImageButton leftButton, rightButton;
protected void init() {
context = fragment.getContext();
widgetView = inflater.inflate(layout, parentLayout, false);
headline = (TextView) widgetView.findViewById(headlineId);
leftButton = (ImageButton) widgetView.findViewById(leftButtonId);
rightButton = (ImageButton) widgetView.findViewById(rightButtonId);
headline.setText(headlineTextId);
leftButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(fragment.getContext(), "[Move]", Toast.LENGTH_SHORT).show();
}
});
rightButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(fragment.getContext(), "[Hide]", Toast.LENGTH_SHORT).show();
}
});
}
public View getLayout() {
return widgetView;
}
public int getLayoutId() {
return layout;
}
public void setLayout(View layout) {
this.widgetView = layout;
}
public int getHeadlineTextId() {
return headlineTextId;
}
public TextView getHeadline() {
return headline;
}
public void setHeadline(String s) {
headline.setText(s);
}
public void setHeadline(int resId) {
setHeadline(context.getString(resId));
}
}
Я использую этот класс в расширении моих виджетов подклассов, как этот (экстракт):
public class NowWidget extends Widget {
private TextView degree;
public NowWidget(View fragment, LayoutInflater inflater) {
super();
this.fragment = fragment;
this.inflater = inflater;
this.layout = R.layout.widget_now;
this.headlineId = R.id.widget_now_card_headline;
this.leftButtonId = R.id.widget_now_card_left_button;
this.rightButtonId = R.id.widget_now_card_right_button;
this.headlineTextId = R.string.now;
init();
}
public void init() {
super.init();
degree = (TextView) widgetView.findViewById(R.id.widget_now_degree);
}
public void setDegree(String s) {
degree.setText(s);
}
}
Идея класса виджета : Все (включая представление со всеми данными) сохраняется в этом классе и может быть вызвано через getLayout().
В моих фрагментах я создаю виджеты и заполняю их данными (Getter and Setter). Сначала я работал с обычным LinearLayouts и просто добавил к нему виджеты. Все работало правильно.
Но теперь я должен использовать ListViews (производительность) и попытался его с помощью следующего адаптера:
public class WidgetAdapter extends ArrayAdapter<Widget> {
private ArrayList<Widget> widgets;
public WidgetAdapter(Context context, ArrayList<Widget> widgets) {
super(context, 0, widgets);
this.widgets = widgets;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getItem(position).getLayout();
}
private static class WidgetHolder {
public Widget widget;
}
}
Я установил адаптер в моем фрагменте так:
CustomWidgetListView widgetListView = (CustomWidgetListView) fragment.findViewById(R.id.now_list_view);
ArrayList<Widget> widgetList = new ArrayList<Widget>();
for (int i = 0; i < 20; i++) {
NowWidget nowWidget = new NowWidget(fragment, inflater);
nowWidget.setHeadline("Widget " + i);
widgetList.add(nowWidget);
}
WidgetAdapter adapter = new WidgetAdapter(context, widgetList);
widgetListView.setAdapter(adapter);
виджеты получают созданную и я вижу их в своем ListView. Это не моя проблема.
НО: виджеты не в правильном порядке: все, что находится за пределами экрана при загрузке, не создается и «старые» виджеты показаны:
Начало моей ListView:
прокрутили:
я уже заметил (через вход виджеты-ArrayList), что изменения ArrayList на прокрутке. Но почему?
Я действительно не знаю, почему это происходит. Я уже пробовал много других getView-методов в моем адаптере, но иногда в ListView не было виджетов, или они все еще были в неправильном порядке.
Я также попытался это (сейчас работает):
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
Widget widget = getItem(position);
convertView = widget.getLayout();
}
return convertView;
}
Я надеюсь, что кто-то из вас может мне помочь.
Спасибо!
См. Этот ответ: http://stackoverflow.com/a/19289890/950427.Вам нужно использовать шаблон «ViewHolder». –
Извините, но это мне не помогает. Моя структура виджета Мне не нужно раздувать метод getView() адаптера. Все уже завышено и сохранено в классе Widget. –
Вам нужно преобразовать код в шаблон 'ViewHolder' для' ListView'. «GetView» перерабатывает представление, позиции, которые вы видите, - это только видимые элементы просмотра списка (например, 0-5). –