Страница 1 из 14

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

Добавлено: 06 фев 2012, 03:00
damager82
В этом уроке:

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

[url=http://www.startandroid.ru/ru/uroki/vse ... l:2q1sy4xu]Click here to read this article![/url:2q1sy4xu]

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

Добавлено: 03 мар 2012, 23:28
NobodyCallMeChicken
Вы бы не могли объяснить один момент.
((TextView) view.findViewById(R.id.tvPrice)).setText(p.price + "");

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

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

Добавлено: 05 мар 2012, 09:53
damager82
NobodyCallMeChicken писал(а):Вы бы не могли объяснить один момент.
((TextView) view.findViewById(R.id.tvPrice)).setText(p.price + "");

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

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

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

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

Добавлено: 05 мар 2012, 12:01
Vlady
Может создать раздел на форуме Java? А то часть вопросов в чистом виде про неё.

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

Добавлено: 05 мар 2012, 12:06
NobodyCallMeChicken
Может создать раздел на форуме Java? А то часть вопросов в чистом виде про неё.
Есть же вроде бы такой раздел.

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

Добавлено: 06 мар 2012, 13:50
damager82
Угу, есть
viewforum.php?f=47

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

Добавлено: 12 май 2012, 22:31
MeTeOpA
Скажите, такой вопрос...
Если поменять местами 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)

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

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

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

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

Добавлено: 14 июн 2012, 04:03
Katran
Подскажите, пожалуйста, как сделать одиночный выбор в списке?

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

Добавлено: 15 июн 2012, 11:52
damager82
Katran писал(а):Подскажите, пожалуйста, как сделать одиночный выбор в списке?
Урок 43. Или вам в своем адаптере это сделать надо?

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

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

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

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?

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

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

Добавлено: 04 сен 2012, 17:22
rezak90
если я не ошибаюсь то в 52 уроке то что вам надо, там реализовано контекстное меню по нажатию которого получаем id из бд.

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

Добавлено: 04 сен 2012, 17:37
Xroft
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);

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

Добавлено: 04 сен 2012, 17:47
rezak90
Ну вот когда кастомизируешь адаптер то в методе 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 на "ячейку" списка, а в обработчике передавать уже айди в своё активити.

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

Добавлено: 04 сен 2012, 18:35
Xroft
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
					
				}
... после добавления которого в эмуляторе список вообще никак не реагирует :) .... что то я совсем запутался)

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

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

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

Добавлено: 04 сен 2012, 19:54
Xroft
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 из базы а не позицию в списке.

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

Добавлено: 05 сен 2012, 07:04
KamiSempai
Нужно правильно переопределить метод getItemId

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

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

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

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

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