Урок 54. Кастомизация списка. Создаем свой адаптер

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

Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение damager82 » 06 фев 2012, 03:00

В этом уроке:

- создаем свой адаптер на основе BaseAdapter

[url=http://www.startandroid.ru/ru/uroki/vse ... l:2q1sy4xu]Click here to read this article![/url:2q1sy4xu]
Последний раз редактировалось damager82 08 май 2017, 16:01, всего редактировалось 8 раз.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

NobodyCallMeChicken
Сообщения: 17
Зарегистрирован: 27 фев 2012, 10:53

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение NobodyCallMeChicken » 03 мар 2012, 23:28

Вы бы не могли объяснить один момент.
((TextView) view.findViewById(R.id.tvPrice)).setText(p.price + "");

а конкретно вот это: + "", зачем в методе setText к строке с ценой прибавлять еще пустую строку? И почему без этого приложение падает с ошибкой? Спасибо.

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

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение damager82 » 05 мар 2012, 09:53

NobodyCallMeChicken писал(а):Вы бы не могли объяснить один момент.
((TextView) view.findViewById(R.id.tvPrice)).setText(p.price + "");

а конкретно вот это: + "", зачем в методе setText к строке с ценой прибавлять еще пустую строку? И почему без этого приложение падает с ошибкой? Спасибо.
Метод setText рассчитан на то,что в него подадут текст. p.price - число, поэтому ошибка.
А если дорисуем + "", то все выражение в скобках превратится в строку (так устроена java) и метод setText отработает без проблем.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

NobodyCallMeChicken
Сообщения: 17
Зарегистрирован: 27 фев 2012, 10:53

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение NobodyCallMeChicken » 05 мар 2012, 09:56

А, ок, я пока плохо знаю Java, всю жизнь на с++ писал, и подумал что передав в метод число он его неявно преобразует в объект String. Спасибо, буду знать.

Аватара пользователя
Vlady
Сообщения: 7
Зарегистрирован: 04 мар 2012, 07:41
Контактная информация:

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение Vlady » 05 мар 2012, 12:01

Может создать раздел на форуме Java? А то часть вопросов в чистом виде про неё.

NobodyCallMeChicken
Сообщения: 17
Зарегистрирован: 27 фев 2012, 10:53

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение NobodyCallMeChicken » 05 мар 2012, 12:06

Может создать раздел на форуме Java? А то часть вопросов в чистом виде про неё.
Есть же вроде бы такой раздел.

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

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение damager82 » 06 мар 2012, 13:50

Угу, есть
viewforum.php?f=47
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
MeTeOpA
Сообщения: 85
Зарегистрирован: 07 мар 2012, 12:50

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение MeTeOpA » 12 май 2012, 22:31

Скажите, такой вопрос...
Если поменять местами check boх и Image Приложение падает с ошибкой.

05-12 19:29:03.848: E/AndroidRuntime(5278): FATAL EXCEPTION: main
05-12 19:29:03.848: E/AndroidRuntime(5278): java.lang.ClassCastException: android.widget.LinearLayout
05-12 19:29:03.848: E/AndroidRuntime(5278): at ua.m.BoxAdapter.getView(BoxAdapter.java:54)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.AbsListView.obtainView(AbsListView.java:1430)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.ListView.measureHeightOfChildren(ListView.java:1216)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.ListView.onMeasure(ListView.java:1127)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.View.measure(View.java:8313)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1017)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.LinearLayout.measureVertical(LinearLayout.java:386)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.View.measure(View.java:8313)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.View.measure(View.java:8313)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.LinearLayout.measureVertical(LinearLayout.java:531)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.View.measure(View.java:8313)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.View.measure(View.java:8313)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.ViewRoot.performTraversals(ViewRoot.java:839)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.os.Handler.dispatchMessage(Handler.java:99)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.os.Looper.loop(Looper.java:123)
05-12 19:29:03.848: E/AndroidRuntime(5278): at android.app.ActivityThread.main(ActivityThread.java:3683)
05-12 19:29:03.848: E/AndroidRuntime(5278): at java.lang.reflect.Method.invokeNative(Native Method)
05-12 19:29:03.848: E/AndroidRuntime(5278): at java.lang.reflect.Method.invoke(Method.java:507)
05-12 19:29:03.848: E/AndroidRuntime(5278): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
05-12 19:29:03.848: E/AndroidRuntime(5278): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
05-12 19:29:03.848: E/AndroidRuntime(5278): at dalvik.system.NativeStart.main(Native Method)

Не могли бы вы помочь?

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

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение damager82 » 14 май 2012, 11:55

MeTeOpA писал(а):Скажите, такой вопрос...
Если поменять местами check boх и Image Приложение падает с ошибкой.
Не могли бы вы помочь?
Какая-то мутная ошибка ... то есть, то нет. Чет я ее вообще не понимаю ...
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Katran
Сообщения: 1
Зарегистрирован: 10 май 2012, 10:17

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение Katran » 14 июн 2012, 04:03

Подскажите, пожалуйста, как сделать одиночный выбор в списке?

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

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение damager82 » 15 июн 2012, 11:52

Katran писал(а):Подскажите, пожалуйста, как сделать одиночный выбор в списке?
Урок 43. Или вам в своем адаптере это сделать надо?
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
Xroft
Сообщения: 38
Зарегистрирован: 10 май 2012, 10:11

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение Xroft » 04 сен 2012, 17:10

Доброго времени суток!
Господа, такой вопрос...
Есть адаптер, в который загоняется массивы данных

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

ProjectListOrderAdapter ord = new ProjectListOrderAdapter(ListOrder.this, 
				_id, company, name, summa, type, date_time, confirm);
			lv.setAdapter(ord);
			registerForContextMenu(lv);
Далее в контекстном меню надо выбрать позицию, и запуская другое Acvtivity передать в него именно _id записи, не его id в списке а именно _id.

Код такой

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

AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
					Intent intentAddOrder = new Intent(this, AddOrderActivity.class);
					intentAddOrder.putExtra(ProjectDbAdapter.db_id, info.id);
					startActivity(intentAddOrder);
В итоге info.id у меня получается равно 0.
В другом куске кода (где я использую SimpleCursorAdapter) такой способ передачи id работает ...а тут нет ....

что я делаю не так, а главное КАК передать ID выбранной записи в другое Activity?

Прошу не ругаться, если откровенно туплю - я только учусь:)
Заранее спасибо

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

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение rezak90 » 04 сен 2012, 17:22

если я не ошибаюсь то в 52 уроке то что вам надо, там реализовано контекстное меню по нажатию которого получаем id из бд.
R.id.team
Политика на форуме запрещена

Аватара пользователя
Xroft
Сообщения: 38
Зарегистрирован: 10 май 2012, 10:11

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение Xroft » 04 сен 2012, 17:37

rezak90 писал(а):если я не ошибаюсь то в 52 уроке то что вам надо, там реализовано контекстное меню по нажатию которого получаем id из бд.
Спасибо, посмотрел. но тут используется SimpleCursorAdapter,

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

AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) item.getMenuInfo();
      // извлекаем id записи и удаляем соответствующую запись в БД
      db.delRec(acmi.id);
а у меня используется свой Адаптер ....

вот кусок адаптера

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

public ProjectListOrderAdapter(Context context, Integer[]_id, String[]company, String[]name, Float[]summa, 
			String[]type, String[]date_time, Integer[]confirm) {
				this.Order__id=_id;
				this.Order_company=company;
				this.Order_name=name;
				this.Order_summa=summa;
				this.Order_type=type;
				this.Order_date_time=date_time;
				this.Order_confirm=confirm;
				this.Context=context;
					lInflater = (LayoutInflater)Context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

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

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение rezak90 » 04 сен 2012, 17:47

Ну вот когда кастомизируешь адаптер то в методе getView строится "ячейка":

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

	public View getView(final int position, View convertView, ViewGroup parent) {
		View view = convertView;
		if(view == null)
			view = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.children_item_listview, parent, false);
		//строиь свои компоненты и т.д.
		
		view.setOnClickListener(new View.OnClickListener() {
			Log.i("MyTag", "Order__id = " + Order__id); // что делать с Order__id уже разберёшся
		});
				
		return view;
	}
Суть в том что тебе нужно повесить обработчик OnClickListener на "ячейку" списка, а в обработчике передавать уже айди в своё активити.
R.id.team
Политика на форуме запрещена

Аватара пользователя
Xroft
Сообщения: 38
Зарегистрирован: 10 май 2012, 10:11

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение Xroft » 04 сен 2012, 18:35

rezak90 писал(а):Ну вот когда кастомизируешь адаптер то в методе getView строится "ячейка":
Суть в том что тебе нужно повесить обработчик OnClickListener на "ячейку" списка, а в обработчике передавать уже айди в своё активити.
Эм ... в моем адаптере метод getView выглядит так

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

public View getView(int position, View convertView, ViewGroup parent) {
		View view = convertView;
	    if (view == null) {
	      view = ((LayoutInflater) Context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.list_order_row, parent, false);

		    // Находим  TextView ..........
        return view;
Если я после view = ((LayoutInflater) Context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.list_order_row, parent, false);

добавляю

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

view.setOnClickListener(new View.OnClickListener() {

		    	//   Log.i("MyTag", "Order__id = " + Order__id); // что делать с Order__id уже разберёшся
		   });
На меня матерится ошибкой и просит создать абстрактный метод

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

public void onClick(View v) {
					// TODO Auto-generated method stub
					
				}
... после добавления которого в эмуляторе список вообще никак не реагирует :) .... что то я совсем запутался)

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

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение rezak90 » 04 сен 2012, 18:42

правильно, добавил абстрактный метод и в нём уже реализовывай что нужно, хочешь получить айди - определи паблик статик переменную и присвой ей, или же в адаптере определи переменную private idx, в методе onClick idx = Order__id; потом построй метод public int getIdx() { return idx; } где в активити уже сможешь выполнить int id = adapter.getIdx(); .
В общем это костыли. Имхо для таких целей лучше использовать курсорадаптер в связки с дбхелпером, и код будет красивей и меньше извращений.
R.id.team
Политика на форуме запрещена

Аватара пользователя
Xroft
Сообщения: 38
Зарегистрирован: 10 май 2012, 10:11

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение Xroft » 04 сен 2012, 19:54

rezak90 писал(а):Имхо для таких целей лучше использовать курсорадаптер в связки с дбхелпером, и код будет красивей и меньше извращений.
Воот, а как его правильно написать то?

1 шаг Получаю курсор записей

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

Cursor cursor = mDbHelper.fatchAllOrderHd();
		startManagingCursor(cursor);
		cursor.moveToFirst();
		int cntOrderHd = cursor.getCount(); //получаем кол-во для инициализации массивов
2 шаг Загоняю все это дело в массивы

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

_id = new Integer[cntOrderHd];
		company = new String[cntOrderHd];
		name = new String[cntOrderHd];
		summa = new Float[cntOrderHd];
		type = new String[cntOrderHd];
		date_time = new String[cntOrderHd];
		confirm = new Integer[cntOrderHd];
		
		cursor.moveToFirst();
		for (int i = 0; i < cntOrderHd; i++) {
			_id[i] = cursor.getInt(0);
			company[i] = cursor.getString(1);
			name[i] = cursor.getString(2);
			summa[i] = cursor.getFloat(3);
			type[i] = cursor.getString(4);
			date_time[i] = cursor.getString(5);
			confirm[i]= cursor.getInt(6); 
			
			cursor.moveToNext();
		}
3 шаг тулю это все в свой адаптер

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

            ListView lv = (ListView) findViewById(R.id.listView1);
		
		ProjectListOrderAdapter ord = new ProjectListOrderAdapter(ListOrder.this, 
				_id, company, name, summa, type, date_time, confirm);
			lv.setAdapter(ord);
			registerForContextMenu(lv);
и вот далее следует

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

public boolean onContextItemSelected(MenuItem item) {
		    	switch(item.getItemId()) {
		    	case R.id.open_order:
		    		
		    		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
					Intent intentAddOrder = new Intent(this, AddOrderActivity.class);
					intentAddOrder.putExtra(ProjectDbAdapter.EXT_ID_HD, info.id);
					startActivity(intentAddOrder);
		    		///
		    		return true;
В ИТОГЕ у меня info.id получается не id записи (с курсора), а просто порядковый номер позиции в ListView.

вооот:)

ну и в виде "контрольного" выкладываю свой Адаптер

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

public class ProjectListOrderAdapter extends BaseAdapter{
	
	//public Long curId = null;
	
	private Integer[] Order__id;
	private String[] Order_company;
	private String[] Order_name;
	private Float[] Order_summa;
	private String[] Order_type;
	private String[] Order_date_time;
	private Integer[] Order_confirm;
	
	
	private Context Context;
	private LayoutInflater lInflater;
	
	public ProjectListOrderAdapter(Context context, Integer[]_id, String[]company, String[]name, Float[]summa, 
			String[]type, String[]date_time, Integer[]confirm) {
				this.Order__id=_id;
				this.Order_company=company;
				this.Order_name=name;
				this.Order_summa=summa;
				this.Order_type=type;
				this.Order_date_time=date_time;
				this.Order_confirm=confirm;
				this.Context=context;
					lInflater = (LayoutInflater)Context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}


	public int getCount() {
		// TODO Auto-generated method stub
		return Order__id.length;
	}

	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		View view = convertView;
	    if (view == null) {
	      //view = lInflater.inflate(R.layout.list_order_row, parent, false);
	      
	      view = ((LayoutInflater) Context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.list_order_row, parent, false);

	    }
	    TextView company = (TextView) view.findViewById(R.id.tvCompany);
	    TextView name = (TextView) view.findViewById(R.id.tvName);
	    TextView summa = (TextView) view.findViewById(R.id.tvSumma);
	    TextView type = (TextView) view.findViewById(R.id.tvType);
	    TextView date_time = (TextView) view.findViewById(R.id.tvDate);
	    TextView confirm = (TextView) view.findViewById(R.id.tvConfirm);

	    company.setText(Order_company[position]+"");
	    name.setText(Order_name[position]);
	    summa.setText(Order_summa[position]+"");
	    type.setText(Order_type[position]+"");
	    date_time.setText(Order_date_time[position]+"");
	    confirm.setText(Order_confirm[position]+"");

	return view;
	}

}
P.S. приветствуется любая критика по коду, я только учусь и толковые пожелания - на вес золота. Но основная проблема - это как раз передать именно ID из базы а не позицию в списке.

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

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение KamiSempai » 05 сен 2012, 07:04

Нужно правильно переопределить метод getItemId

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

public long getItemId(int position) {
    return (long) Order__id[position];
}
PS: Так как у Вас данные изначально сидят в курсоре, я бы посоветовал использовать SimpleCursorAdapter.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

Re: Урок 54. Кастомизация списка. Создаем свой адаптер

Сообщение neoksi » 05 сен 2012, 07:16

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

п.с. Позиция в листе равна позиции в массиве.

Ответить