Урок 44. События в ListView

Обсуждение уроков
Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 44. События в ListView

Сообщение KamiSempai » 05 сен 2012, 12:03

Может быть Вы забыли указать слушателя в импорте?

Код: Выделить всё

import android.widget.AdapterView.OnItemClickListener
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

math64
Сообщения: 235
Зарегистрирован: 16 июл 2012, 07:47

Re: Урок 44. События в ListView

Сообщение math64 » 05 сен 2012, 12:14

Т.е. ошибка не на слушателе, а на спиннере (т.е. создание слушателя не комментируешь)?
Попробуй сменить версию СДК (у меня например, стоит android-16 (4.1 - последняя версия с исходниками) и android-10 (2.3.3 - как телефоне).
Если при этом ошибка пропадёт - по видимому, та версия скачалась с ошибками, попробуй обновить.
KamiSempai писал(а):Может быть Вы забыли указать слушателя в импорте?
Ну. да - может быть импорт не на тот слушатель.
Я советую оставить

Код: Выделить всё

import android.widget.AdapterView
и писать

Код: Выделить всё

AdapterView.OnItemClickListener spinnerListner = new AdapterView.OnItemClickListener() { ... };

etlt
Сообщения: 8
Зарегистрирован: 30 авг 2012, 20:19

Re: Урок 44. События в ListView

Сообщение etlt » 05 сен 2012, 13:41

Сейчас стоят API 10, 15, 16
переустановил API 10 т.к. пишу именно под неё
в импорте все норм пробовал и OnItemClickListener и AdapterView.OnItemClickListener

Очень странно, но такая ерунда только со спеннерами

dil_android
Сообщения: 103
Зарегистрирован: 10 сен 2012, 11:58

Re: Урок 44. События в ListView

Сообщение dil_android » 05 окт 2012, 19:49

Здравствуйте.

Пытаясь разобраться в адаптерах, приходишь к удивительным открытиям.
Так например, пытаясь реализовать удаление записей при помощи метода onContextItemSelected (урок 51) приминительно к ArrayAdapter<CharSequence>, узнал, что этот вид адаптера удаление, дополнение и редактирование записей не поддерживает (read-only).

http://stackoverflow.com/questions/3476 ... rayadapter

Проверил на примере:

Код: Выделить всё

public class MainActivity extends Activity {

    private static final int CM_DELETE_ID = 1;
    ArrayAdapter<CharSequence> adapter;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        String[] strings = new String[]{"One", "Two", "Three"};
        adapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_list_item_1, android.R.id.text1, strings);

        ListView list = (ListView) this.findViewById(R.id.list);
        list.setAdapter(adapter);
        registerForContextMenu(list);

    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
            ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add(0, CM_DELETE_ID, 0, "Удалить запись");
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        if (item.getItemId() == CM_DELETE_ID) {
            // получаем инфу о пункте списка
            AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) item.getMenuInfo();
            // удаляем Map из коллекции, используя позицию пункта в списке

            adapter.remove(adapter.getItem(acmi.position));

            // уведомляем, что данные изменились
            adapter.notifyDataSetChanged();
            return true;
        }
        return super.onContextItemSelected(item);
    }
}

действительно, приложение валится при нажатии на удалить.
Скажите пожалуйста, это так должно быть или все таки есть возможности удаления, дополнения и редактирования записей в ArrayAdapter<CharSequence>.
Если да, можно ли пример.

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Урок 44. События в ListView

Сообщение rezak90 » 05 окт 2012, 20:31

всё он поддерживает, проверь что возвращает acmi.position, было бы легче найти ошибку если бы указывал строку где вылетает и лог ошибок.
А так я тысячу раз буду повторять что лучше писать кастомные адаптеры и всегда будешь знать где что не работает.
R.id.team
Политика на форуме запрещена

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 44. События в ListView

Сообщение AndreyI » 06 окт 2012, 02:20

rezak90 писал(а): лучше писать кастомные адаптеры и всегда будешь знать где что не работает.
А исходники на что?

Теперь по вопросу
Для любого адаптера источник данных всегда первичен, от него и нужно плясать (как от печки :)), ListView это только инструмент для отображения данных, а адаптер "знает" как связать источник данных и ListView. Поэтому, если вы хотите что-то изменить в ListView думайте прежде всего о том, что нужно будет, прежде всего, изменять источник данных.
В данном случае в качестве источника данных используется строковый массив String[]
Если обратиться к исходникам и посмотреть конструктор адаптера, который используется для данного примера, то мы увидим следующее:

Код: Выделить всё

   public ArrayAdapter(Context context, int textViewResourceId, T[] objects) {
        init(context, textViewResourceId, 0, Arrays.asList(objects));
    }
Строковый массив преобразуется в List с помощью статического метода Arrays.asList далее смотрим справку по этому методу
Returns a List of the objects in the specified array. The size of the List cannot be modified, i.e. adding and removing are unsupported, but the elements can be set. Setting an element modifies the underlying array.
Из чего нетрудно догадаться почему адаптер не может модифицировать источник данных для нашего ListView.
Собственно, логику разработчиков можно понять, т.к. в качестве источника данных используется массив, а в JAVA размеры массива после его создания изменить нельзя и дабы не возникало коллизий между источником данных и их отображением в ListView они использовали для преобразования именно этот метод, хотя вполне можно было преобразовать и в нормальный ArrayList.

Выход здесь прост, чтобы можно было динамически изменять ListView нужно применять такой источник данных, который тоже можно изменять (добавлять, удалять элементы и т.п.). В данном случае, в качестве такого источника лучше всего подходит ArrayList.
Строковый массив нужно преобразовать в ArrayList и использовать его в конструкторе адаптера в качестве источника данных:

Код: Выделить всё

...
String[] strings = new String[]{"One", "Two", "Three"};
ArrayList<CharSequence> array= new ArrayList(Arrays.asList(itemList));
adapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_list_item_1, android.R.id.text1, array);
...
Последний раз редактировалось AndreyI 06 окт 2012, 11:53, всего редактировалось 1 раз.

dil_android
Сообщения: 103
Зарегистрирован: 10 сен 2012, 11:58

Re: Урок 44. События в ListView

Сообщение dil_android » 06 окт 2012, 07:35

Андрей,
ваше объяснение понял, но логику разработчиков понять не могу.
После предложенного вами преобразования в ArrayList выкидывается ошибка:
error: no suitable constructor found for ArrayAdapter(MainActivity,int,int,ArrayList<String>)
Посмотрел исходники, действительно ArrayList не поддерживается.

ArrayAdapter(Context context, int textViewResourceId)
Constructor
ArrayAdapter(Context context, int resource, int textViewResourceId)
Constructor
ArrayAdapter(Context context, int textViewResourceId, T[] objects)
Constructor
ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects)
Constructor
ArrayAdapter(Context context, int textViewResourceId, List<T> objects)
Constructor
ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects)
Constructor

Подскажите, что в этом случае делать.

И еще, получается, что каждый из адаптеров ущербен в определенном смысле этого слова, так как изначально писался под определенную логику разработчиков? Опять таки, возвращаясь к checkboxes, почему работа с ними требует написания отдельного метода для View?

P.S. Я не прошу Вас отвечать за разработчиков, и ответ: "мир не совершенен"; меня вполне устроит :)
Однако, если есть приемлемое решение по вопросу поднятому выше, буду признателен.

Спасибо.

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 44. События в ListView

Сообщение AndreyI » 06 окт 2012, 11:53

Исправил, попробуйте снова ;)

dil_android
Сообщения: 103
Зарегистрирован: 10 сен 2012, 11:58

Re: Урок 44. События в ListView

Сообщение dil_android » 06 окт 2012, 12:02

Где?

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 44. События в ListView

Сообщение AndreyI » 06 окт 2012, 12:05

В сообщении, блин
ArrayList<CharSequence> array= new ArrayList(Arrays.asList(itemList));

dil_android
Сообщения: 103
Зарегистрирован: 10 сен 2012, 11:58

Re: Урок 44. События в ListView

Сообщение dil_android » 06 окт 2012, 12:14

Работает. Спасибо, ваше объяснение оказалось не только правильным, но и практически реализованным.
В качестве рекомендации, мне кажется, автору следует дополнить уроки по адаптерам.
Такого же характера вопросы, какие возникают у меня, я видел у многих, посещающих этот форум.

Еще раз спасибо за разъяснение и реализацию.

Quqush
Сообщения: 6
Зарегистрирован: 09 авг 2012, 19:07

Re: Урок 44. События в ListView

Сообщение Quqush » 08 окт 2012, 21:16

damager82 писал(а):Возможно мало опыта работы с Java? Попробуйте что-нибудь прочесть из этой темы: viewtopic.php?f=17&t=147
Огромное спасибо за наводку (http://www.ibm.com/developerworks/ru/ed ... tion9.html). Я и слыхом не слыхивал про родовые типы в Java когда знакомился с языком в 2003 году. Поэтому конструкции типа "AdapterView<?> parent" вызывали недоумение.

arthur07
Сообщения: 6
Зарегистрирован: 04 ноя 2012, 20:06

Re: Урок 44. События в ListView

Сообщение arthur07 » 04 ноя 2012, 20:24

Здравствуйте. Используя код ваших примеров я попытался сделать список, по нажатию на который значения двух переменных передаются в другое активити.
Но после нажатия на item в другом окне значения не принимаются и возвращается null. Подскажите, пожалуйста, в чем дело
Вот первое активити

Код: Выделить всё

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    lvMain = (ListView) findViewById(R.id.lvMain);
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
        this, R.array.names,
        android.R.layout.simple_list_item_1);
    lvMain.setAdapter(adapter);    
    lvMain.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
          Log.d(LOG_TAG, "itemClick: position = " + position + ", id = " + id);
        
          Intent intent = new Intent(MainActivity.this, ViewActivity.class);
          intent.putExtra("position", position);
          intent.putExtra("id", id);
          startActivity(intent);
   
        }
      });

  }
код второго активити

Код: Выделить всё

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.view);
    
    tvView = (TextView) findViewById(R.id.tvView);
    
    Intent intent = getIntent();
    
    String fName = intent.getStringExtra("position");
    String lName = intent.getStringExtra("id");
    
    tvView.setText("Your name is: " + fName + " " + lName);
  }

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Урок 44. События в ListView

Сообщение rezak90 » 04 ноя 2012, 21:23

потому что кладёте int, a извлекаете String
R.id.team
Политика на форуме запрещена

arthur07
Сообщения: 6
Зарегистрирован: 04 ноя 2012, 20:06

Re: Урок 44. События в ListView

Сообщение arthur07 » 04 ноя 2012, 21:41

спасибо) исправил вот так)

Код: Выделить всё

intent.putExtra("position", Integer.toString(position));
intent.putExtra("id", Long.toString(id));
теперь передается)

xottabut
Сообщения: 5
Зарегистрирован: 12 ноя 2012, 22:48

Re: Урок 44. События в ListView

Сообщение xottabut » 21 ноя 2012, 01:59

Скажите пожалуйста, зачем в донном уроке TextView ?

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 44. События в ListView

Сообщение damager82 » 21 ноя 2012, 09:35

xottabut писал(а):Скажите пожалуйста, зачем в донном уроке TextView ?
Хороший вопрос! По ходу ошибка копипаста ... Пофиксю, спасибо!
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

dcbp
Сообщения: 24
Зарегистрирован: 26 ноя 2012, 10:34

Re: Урок 44. События в ListView

Сообщение dcbp » 03 фев 2013, 18:21

Друзья! Столкнулся с неожиданной трудностью.
Пишу код:

Код: Выделить всё

@Override
    public void onResume() {

    	setContentView(R.layout.main);
		

		filesList = (ListView) findViewById(R.id.filesList);
			
		filesList.setOnItemClickListener(new OnItemClickListener() {
		      public void onItemClick(AdapterView<?> parent, View view,
		              int position, long id) {
		            Log.d("myLogs", "itemClick: position = " + position + ", id = "
		                + id);
		          }
		        });
		
           String[] from = { "filename", "creationDate" , "id" };
           int[] to = { R.id.tvFileName, R.id.tvDate , R.id.bDelete };
		
		
	    files = new ArrayList<Map<String, Object>>();
	    adapter = new SimpleAdapter(Main.this, files, R.layout.files_item2, from, to);
	    
	    	mfiles = new HashMap<String, Object>();
	    	mfiles.put("filename", "dvsds");
	    	mfiles.put("creationDate", "svdvsdv");
	    	mfiles.put("id", 1);
	    	mfiles.put("file_id", 2);
		files.add(mfiles);
	    
	    filesList.setAdapter(adapter);
	    
		
    	super.onResume();
    }
а он не работает(
Просто никак не реагирует на клик по элементу списка. Порядок строк менял по разному. Что я упускаю?

На всякий случай вот вью элемента

Код: Выделить всё

<?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="wrap_content"
    android:layout_marginBottom="5dp"
    android:layout_marginTop="5dp"
    android:background="#ff6600"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvDate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginBottom="10dp"
        android:layout_marginRight="5dp"
        android:text="date"
        android:textColor="#000" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" >

        <TextView
            android:id="@+id/tvFileName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:text="FileName"
            android:textColor="#000"
            android:textSize="18sp" />

        <Button
            android:id="@+id/bDelete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:text="X" />

    </LinearLayout>

</LinearLayout>

Аватара пользователя
dens
Сообщения: 47
Зарегистрирован: 03 фев 2013, 00:14

Re: Урок 44. События в ListView

Сообщение dens » 03 фев 2013, 19:27

Может, попробовать родительский метод вызывать ДО своего кода?

dcbp
Сообщения: 24
Зарегистрирован: 26 ноя 2012, 10:34

Re: Урок 44. События в ListView

Сообщение dcbp » 03 фев 2013, 20:18

Не помогает.

Ответить