Nano Hash - криптовалюты, майнинг, программирование

Элементы DynamicListView исчезают при перетаскивании

Я следовал этому руководству Google и реализовал динамический ListView для перетаскивания https://www.youtube.com/watch?v=_BZIvjMgH-Q

listView = (DynamicListView) findViewById(R.id.listview);
adapter = new StableArrayAdapter(this, R.layout.text_view, arraylist);
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

// added the items later and called notifyDataSetChanged();
    arraylist.add("item 1");
    arraylist.add("item 2");
    arraylist.add("item 3");
    arraylist.add("item 4");

adapter.notifyDataSetChanged();

Он показывает все элементы в списке, но когда я перетаскиваю элементы, они исчезают.

Если я добавлю элементы перед установкой адаптера listView.setAdapter(adapter);, все будет работать нормально.

Исходный код библиотеки http://developer.android.com/shareables/devbytes/ListViewDraggingAnimation.zip< /а>

Как это исправить?

ОБНОВЛЕНИЕ

StableArrayAdapter.java

package com.example.android.navigationdrawerexample;

import android.content.Context;
import android.widget.ArrayAdapter;

import java.util.HashMap;
import java.util.List;

public class StableArrayAdapter extends ArrayAdapter<String> {

    final int INVALID_ID = -1;

    int mRowLayout;
    List<String[]> mStrings;
    HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();

    // constructor
    public StableArrayAdapter(Context context, int rowLayout, List<String> objects) {
        super(context, rowLayout, objects);
        for (int i = 0; i < objects.size(); ++i) {
            mIdMap.put(objects.get(i), i);
        }
    }

    @Override
    public long getItemId(int position) {
        if (position < 0 || position >= mIdMap.size()) {
            return INVALID_ID;
        }
        String item = getItem(position);
        return mIdMap.get(item);
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }
}

ОБНОВЛЕНИЕ 2 Я добавил элементы в objects здесь, как было предложено, и пока все работает нормально, но разве это не то же самое, что добавлять элементы в MainActivity перед настройкой адаптера?

public StableArrayAdapter(Context context, int rowLayout, List<String> objects) {
    super(context, rowLayout, objects);

    objects.add("item 1");
    objects.add("item 2");
    objects.add("item 3");
    objects.add("item 4");
    objects.add("item 5");

    for (int i = 0; i < objects.size(); ++i) {
        mIdMap.put(objects.get(i), i);
    }
}

ОБНОВЛЕНИЕ 3 Размер объектов известен только в конструкторе и mIdMap.put("item 6", objects.size()); в коде не влияет.

 // constructor
    public StableArrayAdapter(Context context, int rowLayout, List<String> objects) {
        super(context, rowLayout, objects);

        this.objects = objects;

        objects.add("item 1");
        objects.add("item 2");
        objects.add("item 3");
        objects.add("item 4");
        objects.add("item 5");

        for (int i = 0; i < objects.size(); ++i) {
            mIdMap.put(objects.get(i), i);
        }

        mIdMap.put("item 6", objects.size());    // has no effect

    }

    public void addItem(String item) {
        int index = objects.size();
        mIdMap.put(item, index);
    }

  • Пожалуйста, отправьте код для StableArrayAdapter. И добавьте еще один тег перетаскивания. На мой взгляд, этот пост не относится к андроид-анимации. 09.07.2015
  • Вы уже решили эту проблему? Если нет, вы можете ответить на мой опубликованный ответ для вашего статуса по этому вопросу. 10.07.2015
  • Vinay, В следующий раз разместите свой комментарий в моем ответе, чтобы я его заметил. Я почти пропустил ваш вопрос в ОБНОВЛЕНИИ 2. Или добавьте свой вопрос в свой пост и в качестве комментария к моему опубликованному ответу. В любом случае.... 11.07.2015
  • vinay, Ответ - это НЕ то же самое, что добавление пунктов в MainActivity ПОСЛЕ настройки адаптера. Ваш исходный код добавил больше строк ПОСЛЕ настройки адаптера. Причина в том, что объект mIdMap имеет другой адрес памяти, чем объект arraylist. Это важные знания в Java, удачи. 11.07.2015
  • Винай, я добавил комментарии/код в разделе ОБНОВЛЕНИЕ в своем опубликованном ответе. 17.07.2015
  • Я думаю, что это решение вашей проблемы: ссылка 06.12.2015

Ответы:


1

Обычно я добавляю элементы в ArrayList или изменяю объект в коде адаптера (StableArrayAdapter в вашем случае), а не вне адаптера, как вы сделали. Но это может быть нормально, если объект вне ArrayAdapter имеет тот же адрес, что и список в StableArrayAdapter. Я подозреваю, что это не так.

В вашем случае убедитесь, что такой код, как arraylist.add("item 1"), добавляет строки в объект ArrayList в StableArrayAdapter. Опять же, я подозреваю, что это не так.

Чтобы ускорить процесс, опубликуйте код для StableArrayAdapter. Читателям неудобно помогать, если они должны скачать код.

НОВЫЙ предлагаемый код:

В StableArrayAdapter добавьте общедоступный метод, например:

// This method is opposite of getItemId().
public void addItem(String item) {
    // Add the string into the objects
    objects.add(item);

    // size of objects should be added by one after add() above
    int index = objects.size();
    mIdMap.put(item, index);
}

Вне StableArrayAdapter:

listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

// added the item and called notifyDataSetChanged();
adapter.addItem("item 1");
adapter.addItem("item 2");

adapter.notifyDataSetChanged();

Примечание. Вместо добавления элементов в arraylist вызовите метод адаптера объекта StableArrayAdapter.

ОБНОВЛЕНИЕ 1. Проблема в том, что методы setCheeseList() и swapElements() в классе DynamicListView НЕ работают для динамического добавления элементов. Также изменен addItem() в StableArrayAdapter. Я уже исправил это в своем проекте, но это нелегко объяснить. Так что я попробую.

Предложения по коду:

Часть 1, ОТ:

private void handleCellSwitch() {
...
   swapElements(mCheeseList, originalItem, getPositionForView(switchView));
   ((BaseAdapter) getAdapter()).notifyDataSetChanged();
...

TO:

private void handleCellSwitch() {
...
   // Swap the 2 items with animation for the dragNdrop feature
   final SwappableListAdapter adapter = (SwappableListAdapter) getAdapter();
   adapter.swap(originalItem, getPositionForView(switchView));
...

Примечания:

  • Вместо вызова локального метода swapElements() для обмена значениями между mCheeseList я вызываю метод swap() интерфейса SwappableListAdapter, который реализован в классе StableArrayAdapter.
  • В основном идея состоит в том, чтобы получить правильные данные в StableArrayAdapter.

Часть 2 Код для интерфейса SwappableListAdapter:

public interface SwappableListAdapter {
        /**
         * Swaps between 2 items in the adapter, one is the mobile item, another is the selected item.
         * Method notifyDataSetChanged is called in the swap() when finished.
         * @param index1 The selected row view, dragged and to be moved.
         * @param index2 The row which moved due to the dragged row item.
         */
    public void swap(int index1, int index2);
}

Примечания:

  • Это интерфейс, созданный в классе DynamicListView, потому что это класс, который будет выполнять фактический вызов.
  • Это устранит проблему с ошибкой компилятора.

Часть 3 Код для реализации метода swap() в классе StableArrayAdapter.

КОМУ:

public class StableArrayAdapter extends ArrayAdapter<String> implements DynamicListView.SwappableListAdapter {
   ...
   @Override
   public void swap(int indexOne, int indexTwo) {
      // Swap mIdMap object related to indexOne and indexTwo
      String item = getItem(indexOne);

      notifyDataSetChanged();
}

Примечания:

  • Над swap() нужно поработать. В моем проекте не используется HashMap для подкачки, и мне не нравится текущая реализация (от инженера Google) HashMap. У меня может быть время, чтобы исправить это. Возможно, вы можете исправить этот метод. Надеюсь, у вас уже есть идея.
  • Класс StableArrayAdapter теперь реализует интерфейс SwappableListAdapter и имеет доступ к переопределению swap().
  • Идея интерфейса заключается в том, что адаптер теперь является центральной точкой хранения данных! Текущая реализация хранит данные как в адаптере, так и в DynamicListView, а этого быть не должно.
09.07.2015
  • @Vinay, глядя на опубликованный код, теперь я знаю, что я прав. Одним из простых решений является создание общедоступного метода в StableArrayAdapter, который принимает новые строковые значения в arraylist. Метод будет обновлять объект mIdMap. Как вы думаете? Вы можете это сделать? 09.07.2015
  • Есть ли другой способ добавить объекты в MainActivity? Потому что в одном из моих приложений я использую Retrofit API для получения информации о погоде для 5 разных мест. Итак, я вызываю API в цикле for -> добавляю его в список массивов -> adapter.notifyDataSetChanged(); Элементы добавляются, но исчезают при перетаскивании. 11.07.2015
  • @Vinay, я добавил тексты в НОВЫЙ раздел предлагаемого кода. Я надеюсь, что это ясно. Самое главное, я надеюсь, вы понимаете, почему ваш исходный код не работает. 11.07.2015
  • Теперь я могу понять лучше, но я все еще не могу заставить его работать. Странно видеть, когда я добавляю строку mIdMap.put(item 6, objects.size()); после цикла for в UPDATE 2 он не отображается в списке. Я что-то пропустил ? 14.07.2015
  • я добавил элементы, используя общедоступный метод класса codeviewer.org/view/code:534b stableArrayAdapter с метод codeviewer.org/view/code:534c 14.07.2015
  • @Vinay, насколько я понимаю, это означает, что теперь вы не видите никаких элементов в ListView. Это правильно? Сейчас я смотрю на метод setCheeseList(). Это не обычный стандарт использования адаптера. К сожалению, дизайн кода не подходит для динамического добавления элементов в адаптер. На мой вопрос, пожалуйста, постарайтесь ответить быстро, так как мне или кому-либо из нас трудно запоминать одну проблему за другой. Спасибо. 15.07.2015
  • да, я не вижу никаких предметов сейчас. Вот класс DynamicListView codeviewer.org/view/code:535c. 15.07.2015
  • @Vinay, я добавил комментарии/код в раздел ОБНОВЛЕНИЕ. 17.07.2015
  • Я внес изменения именно так, как вы предложили мне, и это работает отлично. Для тех, кто ищет точное решение. Я обновлю его как ответ. 18.07.2015
  • Вы, сэр, просто прекрасны. Я хотел бы как-нибудь угостить вас кофе, если вы планируете посетить район залива. 18.07.2015
  • @ Винай, я могу принять твое предложение кофе. Мне нравится район залива, а Лос-Анджелес не слишком далеко. Могу я узнать ваш адрес электронной почты? 22.07.2015
  • @Vinay, просто любопытно, это усилия для проекта в компании? Было бы круто, если так. Я живу в Лос-Анджелесе и, возможно, захочу работать в районе залива, потому что мне нравится Сан-Франциско. Спасибо за любой ответ. 22.07.2015
  • @Vinay, спасибо, что поделились этой информацией, для меня это звучит безумно! Отправил вам письмо. 22.07.2015
  • Привет @TheOriginalAndroid, как насчет пользовательского просмотра списка с использованием базового адаптера .... Я проверил много вопросов и блогов, в основном я получил пример DynamicListView с Arrayadapter (который, я думаю, здесь, в ответах), я попытался реализовать baseadapter вместо arrayadapter, но не повезло. 12.08.2016

  • 2

    Огромное спасибо @The Original Android

    Сводка изменений, внесенных для работы при динамическом добавлении элементов.

    StableArrayAdapter.java

    добавлен метод addItem

    public void addItem(String item) {
        // Add the string into the objects
        objects.add(item);
    
        // size of objects should be added by one after add() above
        int index = objects.size();
        mIdMap.put(item, index);
    }
    

    MainActivity.java

    listView.setCheeseList(al);
    listView.setAdapter(adapter);
    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    
    // called addItem method inside MainActivity
    adapter.addItem("item 1");
    adapter.addItem("item 2");
    adapter.addItem("item 3");
    adapter.addItem("item 4");
    
    adapter.notifyDataSetChanged();
    

    DynamicListView.java

    Изменено с

        private void handleCellSwitch() {
         ...   
           swapElements(mCheeseList, originalItem, getPositionForView(switchView));
           ((BaseAdapter) getAdapter()).notifyDataSetChanged();
         ...
        }
    

    to

       private void handleCellSwitch() { 
        ...      
          final SwappableListAdapter adapter = (SwappableListAdapter) getAdapter();
          adapter.swap(mCheeseList,originalItem, getPositionForView(switchView)); // I still had to pass the arraylist   
        ...
        }
    

    Создан интерфейс внутри DynamicListView.java

    public interface SwappableListAdapter {    
        public void swap(int index1, int index2);
    }
    

    StableArrayAdapter.java реализует интерфейс SwappableListAdapter и переопределяет метод подкачки

    public class StableArrayAdapter extends ArrayAdapter<String> implements DynamicListView.SwappableListAdapter {
    
        @Override
        public void swap(ArrayList a,int index1, int index2) {
    
            Object temp = a.get(index1);
            a.set(index1, a.get(index2));
            a.set(index2, temp);
    
            notifyDataSetChanged();
        }
    }
    
    18.07.2015
  • Я рад, что вы решили проблему! Я все еще не хочу зависеть от объекта списка mCheeseList. mCheeseList слишком мощен, поскольку даже DynamicListView может изменять содержимое этого объекта. Я также рад, что вы полностью протестировали код, поскольку я не смог этого сделать из-за своей структуры кода. Но я все еще хочу провести дальнейшее расследование и найти лучшее решение (на мой взгляд). Хочешь, я уведомлю тебя об этом? 21.07.2015
  • Да, пожалуйста. пожалуйста, сообщите мне, если у вас есть некоторые выводы 22.07.2015

  • 3

    Это может быть не та же самая проблема, но она похожа, и Google привел меня сюда. Мой вид списка в основном работает, но есть определенная последовательность действий, которая заставит некоторые элементы исчезнуть. Щелчок по ним впоследствии вызывает исключение NullPointerException.

    Вот шаги для воспроизведения ошибки:

    1. Перетащите элемент наверх.
    2. Перетащите другой элемент вверх или вниз.
    3. Элемент вверху исчезнет.
    4. Перетащите другой элемент вверх или вниз.
    5. Верхний элемент снова появится.
    6. Поведение продолжается, если вы переходите к шагу 2

    После отладки я обнаружил, что мой метод StableArrayAdapter.getView() вызывается дважды, только для пустого элемента вверху списка. Это привело меня к этому вопросу 0, в котором упоминалось «предоставление динамической полной высоты».

    Чтобы исправить это, я установил layout_height для моего DynamicListView на «wrap_content».

    28.12.2016
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..