Android: Не знаете, почему мой просмотр списка перепутан?

Я реализовал ListView, который работал правильно, пока я не добавил более 5 элементов и 2 заголовков. Я не совсем уверен, почему некоторые предметы не появляются, а другие появляются несколько раз. Любая помощь в исправлении этого будет высоко ценится. Код включен ниже.

Toolbox.java

public class Toolbox extends Fragment {
    private ListView lstView;
    private View rootView;
    List<Tools> tools;

    public static Toolbox newInstance(Context context) {
        Toolbox fragment = new Toolbox();
        return fragment;
    }

    public Toolbox() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        ((MainActivity) getActivity()).setActionBarTitle("Technical Toolbox");
        rootView = inflater.inflate(R.layout.fragment_toolbox, container, false);
        lstView =(ListView) rootView.findViewById(R.id.list);
        final FragmentActivity c = getActivity();
        //final RecyclerView recyclerView = (RecyclerView) recView.findViewById(R.id.reView);


        setToolBoxData();
        setToolBoxAdapter();
        return rootView;
    }

    private void setToolBoxAdapter() {
        ListArrayAdapter adapter = new ListArrayAdapter(getActivity(),tools);
        lstView.setAdapter(adapter);
    }

    private void setToolBoxData(){
        tools=new ArrayList<>();
        tools.add(new Header("Languages"));
        tools.add(new ListItem("Android",R.drawable.ic_android));
        tools.add(new ListItem("XML", R.drawable.ic_xml));
        tools.add(new ListItem("Java",R.drawable.ic_java));
        tools.add(new ListItem("JavaScript", R.drawable.ic_javascript));
        tools.add(new ListItem("C++", R.drawable.ic_cpp));
        tools.add(new ListItem("Visual Basic", R.drawable.ic_vb));
        tools.add(new ListItem("HTML", R.drawable.ic_html));
        tools.add(new ListItem("CSS", R.drawable.ic_css));
        tools.add(new Header("Source Control"));
        tools.add(new ListItem("Git", R.drawable.ic_git));
        tools.add(new ListItem("GitHub", R.drawable.ic_github_cat));
        tools.add(new ListItem("SourceTree", R.drawable.ic_sourcetree));
        tools.add(new ListItem("BitBucket", R.drawable.ic_bitbucket));
        tools.add(new Header("DataBase"));
        tools.add(new ListItem("Parse", R.drawable.ic_parse));
        tools.add(new ListItem("MS Access", R.drawable.ic_access));
        tools.add(new ListItem("SQL", R.drawable.ic_sql));
        tools.add(new Header("Design & IDE Tools"));
        tools.add(new ListItem("Android Studio", R.drawable.ic_androidstudio));
        tools.add(new ListItem("Visual Studio", R.drawable.ic_visual_studio));
        tools.add(new ListItem("Genymotion", R.drawable.ic_genymotion));
        tools.add(new ListItem("Ionic", R.drawable.ic_ionic));
        tools.add(new Header("Office Tools"));
        tools.add(new ListItem("MS Project", R.drawable.ic_project));
        tools.add(new ListItem("MS Visio", R.drawable.ic_visio));
        tools.add(new ListItem("MS Excel", R.drawable.ic_excel));
        tools.add(new ListItem("MS Word", R.drawable.ic_word));
    }
}

ListArrayAdapter.java

public class ListArrayAdapter extends ArrayAdapter<Tools> {
    private LayoutInflater mInflater;

    public enum RowType{ LIST_ITEM, HEADER_ITEM }

    public ListArrayAdapter(Context context, List<Tools> tools){
        super(context, 0, tools);
        mInflater = LayoutInflater.from(context);
    }

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

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

    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.listview_item, null);
                    holder.View=getItem(position).getView(mInflater, convertView);
                    break;
                case TYPE_SEPARATOR:
                    convertView = mInflater.inflate(R.layout.list_title, 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;
    }
}

Tools.java

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

ListItem.java

public class ListItem implements Tools {
    private final String str1;
    private final int pic1;

    public ListItem(String text1, int pic1) {
        this.str1 = text1;
        this.pic1 = pic1;
    }

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

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

        TextView text1 = (TextView) view.findViewById(R.id.listText);
        ImageView picture1 = (ImageView) view.findViewById(R.id.listIcon);
        text1.setText(str1);
        picture1.setImageResource(pic1);

        return view;
    }
}

Header.java

public class Header implements Tools {
    private final String         name;

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

    @Override
    public int getViewType() {
        return ListArrayAdapter.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;
    }
}

3 ответа

Решение

Вы только заполняете свои виджеты строк в if (convertView == null) дело. Если convertView не является null, вы просто возвращаете его без изменений, то есть у него будут данные position, не position это запрашивается.

IOW, вам нужно вызывать такие методы, как setText() а также setImageResource() на каждом getView() вызов, чтобы заполнить виджеты строки данными для запрошенного position,

Краткая предыстория:

На самом деле сегодня я столкнулся с этой же ошибкой. Как описано, я также сделал 90-95% идентичную реализацию. Однако я также видел принятый ответ в этой теме вопросов и ответов. Но я не могу с тобой согласиться! Поэтому я искал и искал, почему мой проще ArrayAdapter реализация не работает должным образом. В первый раз он загружается хорошо. Но вскоре после того, как я прокручиваю это однажды? Все типы строк перемешаны!

Обобщенный ответ:
Прочитайте Документ разработчика Android для получения дополнительной информации, которую вы могли бы найти ключ непосредственно. Для реализации нескольких типов Views за ListViewСтроки мы должны по существу реализовать, getItemViewType() а также getViewTypeCount() методы. А также getItemViewType() Документация дает нам Примечание следующим образом:

Примечание: целые числа должны быть в диапазоне 0 в getViewTypeCount() - 1, IGNORE_ITEM_VIEW_TYPE также могут быть возвращены.

Так в вашем getItemViewType() Вы должны вернуть значения для Типа представления, начиная с 0, до последнего типа как (количество типов - 1). Например, допустим, у вас есть только два типа представлений? Таким образом, в зависимости от объекта данных для представления, вы можете вернуть только 0 или 1 в getItemViewType() метод.

Если вы не получили подсказку или все еще не можете решить и нуждаетесь в дополнительной информации, пожалуйста, прочтите ее ниже:

Детальное объяснение:

Согласно Документации разработчика Android или Документу API, упоминалось, что для реализации нескольких типов представлений в ListView Адаптер, мы должны реализовать следующие методы:

public int getItemViewType (int position)
public int getViewTypeCount ()

И из вышеупомянутых двух методов, getItemViewType важно в нашем случае (где у нас есть несколько типов представлений). Это правда, верно? И что?

Вот где я и @8BitYoda ошиблись. Неправильная вещь ОП была в том, что он определил Enum где это не дает типы как диапазон integers в диапазоне от 0 до (getViewTypeCount() - 1),

И что я сделал, я определил типы следующим образом:

private static final int TYPE_ITEM = 1;
private static final int TYPE_ITEM = 2;

И сначала я не реализовал, getViewTypeCount(), поэтому я реализовал это следующим образом:

public int getViewTypeCount() {
      return 2;
}

Затем, вскоре после того, как я запустил приложение и попытался загрузить это представление с помощью ListView, оно дало сбой, выдав мне следующее исключение:

java.lang.ArrayIndexOutOfBoundsException: length = 2; index = 2 в android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:6643) в android.widget.ListView.measureHeightOfChildren(ListView.java:1292) в android.widget.ListView.onMeasure(ListView.java:11):
:
:
на com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Чего-чего?:O

Это косвенно говорит, что это связано с целым числом, которое я возвращаю из метода getViewTypeCount(), поскольку я возвращаю 2. И я возвращаю 2, потому что у меня есть только два типа. Поэтому я вернулся к документации Android, чтобы получить окончательную помощь. И это действительно помогло мне и решило мой вопрос, прочитав документ, касающийся методов, которые я реализовал.

Для быстрого взгляда посмотрите на изображение ниже:

С крошечным маленьким шрифтом он дал нам ЗАМЕТКУ.


Что примечание getItemViewType (int position) метод говорит?

Примечание: целые числа должны быть в диапазоне 0 в getViewTypeCount() - 1, IGNORE_ITEM_VIEW_TYPE также могут быть возвращены.

Поэтому сразу после этого я понял, что мне нужно переназначить type integers Я отправляю в начало от 0 до любого количества типов, таких как индекс массива с нуля. Так что я исправил эти две строки, и потом это сработало!

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

Извините, я знаю, что мой ответ прошел немного дольше, чем я ожидал, почти как мини-учебник. Но это нормально для меня, я потратил около часа, чтобы написать это, потому что я бы потратил около 5 часов, чтобы понять эту глупую ошибку. Кто думает, что типы должны назначаться, начиная с 0, как индекс массива на основе 0?

Поэтому я надеюсь, что мой ответ может быть полезен кому-то для решения этой ошибки.

Ура!!!

Вместо того, чтобы использовать позиции, вы должны использовать некоторую форму идентификатора для уникальности.

Также, поскольку представления перерабатываются, вам необходимо обновить их новыми данными.

if (convertView == null) {
        holder = new ViewHolder();
        switch (rowType) {
            case TYPE_ITEM:
                convertView = mInflater.inflate(R.layout.listview_item, null);
                holder.View=getItem(position).getView(mInflater, convertView);
                break;
            case TYPE_SEPARATOR:
                convertView = mInflater.inflate(R.layout.list_title, null);
                holder.View=getItem(position).getView(mInflater, convertView);
                break;
        }
        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    //here update the holder in else case also.
    }

    return convertView;
Другие вопросы по тегам