2015-02-16 2 views
0

Я пытаюсь сделать 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: Top of my ListView

прокрутили: Scrolled down

я уже заметил (через вход виджеты-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; 
} 

Я надеюсь, что кто-то из вас может мне помочь.

Спасибо!

+0

См. Этот ответ: http://stackoverflow.com/a/19289890/950427.Вам нужно использовать шаблон «ViewHolder». –

+0

Извините, но это мне не помогает. Моя структура виджета Мне не нужно раздувать метод getView() адаптера. Все уже завышено и сохранено в классе Widget. –

+0

Вам нужно преобразовать код в шаблон 'ViewHolder' для' ListView'. «GetView» перерабатывает представление, позиции, которые вы видите, - это только видимые элементы просмотра списка (например, 0-5). –

ответ

0

ListView перерабатывает ваш View s, поэтому он не должен создавать новый каждый раз. Вам нужна логика, если создается новый вид, а также логика, если представление не является нулевым, но должно быть переработано.

В вашем методе getView у вас есть правильная логика для создания нового вида (if convertView == null).

Теперь вы должны сделать convertView, указав правильный виджет, если представление не является нулевым, потому что, если оно не является нулевым, оно пытается переработать представление, и вы возвращаете его, не меняя его, давая вам неожиданный результат.

+0

Но в моем первом коде, вырванном из метода getView, он даже не работает, если я просто беру сохраненное представление (return getItem (position) .getLayout();) и придает производительность sh * t. Почему это не работает? –

+0

@ Доминик, я не уверен, почему. Похоже, ваш 'widgetList' меняется. Я могу почти гарантировать, что, если ваши взгляды не соответствуют порядку, это из-за повторной переработки вида. Возможно, посмотрите на шаблон зрителя, как предложили другие. – MeetTitan

+0

Да, мой 'widgetList' меняется. Я сделал несколько тестов и зарегистрировал список. Я уже смотрел в ViewHolder Patter, но это не решает мою проблему. –

Смежные вопросы