Dynamically adding custom row to listview - android

By referring this, I created following:
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/addBtn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="addItems"
android:text="Add New Item" />
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false" />
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
ListView list;
ArrayList<String> listItems = new ArrayList<String>();
ArrayAdapter<String> adapter;
int clickCounter = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
list = (ListView) findViewById(R.id.list);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, listItems);
list.setAdapter(adapter);
list.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String item = list.getItemAtPosition(position).toString();
Log.i("MainActivity", "Selected = " + item);
}
});
}
public void addItems(View v) {
listItems.add("Clicked : " + clickCounter++);
adapter.notifyDataSetChanged();
}
}
And it's working perfectly. But as per requirements, my each listview row won't just be a single string. Instead, it'll be collection of views consisting of imageview and textviews stored in row.xml.
Now my queries are:
What will replace adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, listItems); ? Will it be adapter = new ArrayAdapter<String>(this,R.layout.row, listItems); ??
How do I refer to imageview and textviews of each row? How do I set and get data from them? How do I recognize their click events?
Is use of Adapter must? or can I get away with it?
Any help appreciated.

But as per requirements, my each listview row won't just be a single
string. Instead, it'll be collection of views consisting of imageview
and textviews stored in row.xml.
=> The ListView you are displaying is using normal adapter. If you want your item contains multiple views like Imageview, Textview or any view, then you have to define Custom adapter class by extending either BaseAdapter or ArrayAdapter.
What will replace adapter = new
ArrayAdapter(this,android.R.layout.simple_list_item_1,
listItems); ? Will it be adapter = new
ArrayAdapter(this,R.layout.row, listItems); ??
=> Here ArrayAdapter will not work because your row xml layout may contains different views like ImageView, TextView, Button or any other widget. So I would suggest you to define your own adapter class where you have to override getView() method.
How do I refer to imageview and textviews of each row? How do I set
and get data from them? How do I recognize their click events?
=> As I said above, once you define custom adapter class, you will have to override getView() method where you can find any views of your row xml layout file, reference it and set/display whatever data you want.
Is use of Adapter must? or can I get away with it?
=> Yes its must, without adapter you won't be able to display in data-binded widgets like GridView, ListView, Spinner, Gallery, etc.
Example for defining custom adapter:
My talk on ListView
http://www.vogella.com/articles/AndroidListView/article.html

These are the basic steps:
Create a custom layout for your row (maybe with an ImageView and TextView in it). You used android.R.layout.simple_list_item_1 in your example which if you look into the Android source is just a layout with a single TextView.
Create a class that extends BaseAdapter. This will be your list adapter. You can pass the data to your adapter through the constructor or a method. Create a field where you will store the data.
Now to answer your questions:
How do I refer to imageview and textviews of each row?
How do I set and get data from them?
How do I recognize their click events?
When you extend BaseAdapter you will implement the method public View getView (int position, View convertView, ViewGroup parent). In this method you have to inflate your custom row layout to create the view. Then find the ImageView and TextView using the findViewById method. When you have the ImageView and TextView you call setText or setImageSource to set your data and setOnClickListener for the click events.

Here is code from my project
Consider your list have two text field and one ImageView as following "row.xml" file. Copy this to your res folder
<?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:orientation="vertical">
<TextView
android:id="#+id/row_q"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="Solve[{x^2==4,x+y^2==6},{x,y}]"
android:textAppearance="#android:style/TextAppearance.Small"
android:textStyle="bold|italic" />
<TextView
android:id="#+id/row_a"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/AliceBlue"
android:gravity="center_vertical"
android:paddingLeft="10dp"
android:textAppearance="#android:style/TextAppearance.Small" />
<ImageView
android:id="#+id/row_a_math"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"/>
<LinearLayout
android:id="#+id/graph_layout"
android:layout_width="match_parent"
android:layout_height="200dp"
android:visibility="gone" >
</LinearLayout>
Create following class in your activity to store this data
private class QuesSolnInfo {
public String ques;
public String ans;
public Bitmap ans_b;
public QuesSolnInfo(String ques, String ans, Bitmap ans_b) {
this.ques = ques;
this.ans = ans;
this.ans_b = ans_b;
}
}
//Make following as class members
OutputStringArrayAdapter _outputArrayAdapter = null;
ArrayList<QuesSolnInfo> _outputArrayList = null;
//Initialize them in onCreate Method
_outputArrayAdapter = new OutputStringArrayAdapter(getActivity(), _outputArrayList);
_outputListView.setAdapter(_outputArrayAdapter);
Definitition of ArrayAdapter
protected class OutputStringArrayAdapter extends ArrayAdapter<QuesSolnInfo> {
OutputStringArrayAdapter(Context context, ArrayList<QuesSolnInfo> stringArrayList) {
super(context, R.layout.list, stringArrayList);
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.row, null);
}
TextView t_ques = (TextView) convertView.findViewById(R.id.row_q);
t_ques.setText(getItem(position).ques);
boolean debug = true;
TextView t_ans = (TextView) convertView.findViewById(R.id.row_a);
String texx = getItem(position).ans;
t_ans.setText(texx);
final ImageView w = (ImageView) convertView.findViewById(R.id.row_a_math);
w.setImageBitmap(getItem(position).ans_b);
// Show answer in webview
return convertView;
}
}
Now to add any element to your list do following
_outputArrayList.add(0, new QuesSolnInfo(string1.string2, bitmap0));
_outputArrayAdapter.notifyDataSetChanged();

Related

What view(s) can I use in order to create something like the about screen of the phone?

I want to write an activity that is similar to the about screen of android phones. I want it to display some information in the style of the about screen of android phones.
Like this
title1
info
-----------------
title2
info
-----------------
etc.
Is there a special view that I can use or is it just a result of multiple views placed in a specific way? Or is there an activity template in android studio that I can use?
Use ListView. You can create a custom layout for cells and then use an array or a cursor to fill the data.
ListView: A view that shows items in a vertically scrolling list. The
items come from the ListAdapter associated with this view.
ListAdapter can receive data as input. The adapter would inflate the layout for each cell in its getView() method and assign the data to the individual views in the cell.
Read more about ListView here: http://developer.android.com/reference/android/widget/ListView.html
See PreferenceActivity or PreferenceFragment. They are special list views populated either from code or from a xml file. There are many different preference types to choose from (checkbox, switch, list etc)
An example preference fragment:
You can use ListView and a custom ArrayAdapter to create a screen like that. If you need any help about how to create a custom ArrayAdapter check this useful tutorial here.
If you want to create a simple list, then ListView is probably the simplest option. You may also want to look into ListActivity and/or ListFragment as well to further simplify the process.
If you intend to use complex animations, or have the list update dynamically with animations, you may be better served with RecyclerView, although using it is more complex.
An straightforward implementation of ListActivity could look something like this:
public class MainActivity extends ListActivity {
String[] titles = { "title one", "title two" };
String[] descriptions = { "desc 1", "desc 2" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ListAdapter() {
leave everything the same, except for getCount() and getView()
#Override
public int getCount() {
return titles.length;
}
This will ensure you list is always the correct length as your array.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) parent.getContext().
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.row, parent, false);
} else {
view = convertView;
}
TextView title = (TextView) view.findViewById(R.id.title);
TextView description = (TextView) view.findViewById(R.id.description);
title.setText(titles[position]);
description.setText(descriptions[position]);
return view;
}
And row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/title"
android:textSize="24sp"
android:textStyle="bold"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/description"
android:textSize="20sp"/>
</LinearLayout>

ListView id not valid

i've got a problem with an activity with root element ListView. I've followed this tutorial to load items into listview and all work. But i've tried to change the id of the listview and now, when the activity is loading, i receive this problem:
Your content must have a ListView whose id attribute is "android.R.id.list"
I retried to change id to "list" but i've got the same problem. I don't have problems in compiling but in run-time. This is the code of the activity when i load the listview.
public class StartActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
//Section inflating
adapter.addSection(getString(R.string.equationmenu), new ArrayAdapter<Object>(this,
android.R.layout.simple_list_item_1, new String[] {getString(R.string.eq1title), getString(R.string.eq2title), getString(R.string.eqfractitle)}));
setListAdapter(adapter);
}
SectionedAdapter adapter = new SectionedAdapter() {
protected View getHeaderView(String caption, int index,
View convertView, ViewGroup parent) {
TextView result = (TextView) convertView;
if (convertView == null) {
result = (TextView) getLayoutInflater().inflate(
R.layout.header, null);
}
result.setText(caption);
return (result);
}
};
}
And this is the xml of the activity:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="true" />
Anyone can help me? :)
If you extend from ListActivity you have to let the id of the ListView in your xml
(android:id="#android:id/list")
If you want to change the Id or use more than one ListView in your Activity than you have to
extend from Activity and inflate a ListView yourself..
For example like below:
ListView list1 = (ListView) findViewById(R.id.myList1);
list1.setAdapter(...);
ListView list2 = (ListView) findViewById(R.id.myList2);
list2.setAdapter(...);

Android ListView with delete button

I am trying to bind a list view to a List. This works ok when I create an activity that extends ListActivity and I have a text view in my layout file (i.e. the activity is binding to the default listview in the activity). However, what I would like to do is have a ListView that contains an image button (to further perform the deeltion of the row) and the text view to illustrate the name of the item being bound.
Can anyone point me in the direction that would show how to do this that contains:
The layout file
The activity class
I have played around and cant seem to get it to work, as soon as I add a ListView / image button to the layout file my code crashes. I've also found a few examples through google, but none seem to work!
You can get List functionality even if you do not extend ListActivity, but also via extending Activity. To achieve that, you need layout file with explicitly named ListView element, as illustrated below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/Details_RelativeLayout01">
<ImageView android:layout_centerHorizontal="true"
android:layout_alignParentTop="true" android:id="#+id/Details_ImageView01"
android:layout_marginTop="10dip" android:layout_width="60dip"
android:layout_height="60dip"></ImageView>
<ListView android:layout_width="fill_parent"
android:drawSelectorOnTop="false" android:clipChildren="true"
android:fitsSystemWindows="true" android:layout_height="fill_parent"
android:layout_below="#+id/Details_ImageView01" android:id="#+id/Details_ListView01">
</ListView>
</RelativeLayout>
Here I have list of results below some image. In your Activity class you must extend ArrayAdapter. Also, you need to define the look of one list row. In example below it is done in the R.layout.one_result_details_row.
public class ListOfDetails extends Activity {
private DetailsListAdapter mDetailsListAdapter;
private Vector<String> mDetailsTimeStringsList;
private Vector<String> mDetailsDateStringsList;
private ListView mDetailsListView;
private int mSelectedPosition;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.detailed_results_list);
ListView mDetailsListView = (ListView) findViewById(R.id.Details_ListView01);
ImageView mSelectedPuzzleIcon = (ImageView) findViewById(R.id.Details_ImageView01);
mDetailsListAdapter = new DetailsListAdapter();
mDetailsListView.setAdapter(mDetailsListAdapter);
mDetailsTimeStringsList = new Vector<String>();
mDetailsDateStringsList = new Vector<String>();
updateTheList();
}
class DetailsListAdapter extends ArrayAdapter<String> {
DetailsListAdapter() {
super(ListOfDetails.this, R.layout.one_result_details_row);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row = null;
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.one_result_details_row, parent, false);
TextView result = (TextView) row.findViewById(R.id.Details_Row_TextView01);
TextView date = (TextView) row.findViewById(R.id.Details_Row_TextView02);
Button deleteButton = (Button) row.findViewById(R.id.Details_Button01);
deleteButton.setOnClickListener(
new Button.OnClickListener() {
#Override
public void onClick(View v) {
confirmDelete();
}
}
);
return(row);
}
}
}
Delete button onClickListener() calls some function to confirm deletion. Of course, it has to be done in respect to the current position in the list.
This code snippet is just illustration, but I hope it will be useful to solve your issue.
Found this in the end which was the most complete example:
http://techdroid.kbeanie.com/2009/07/custom-listview-for-android.html

Multiple choice list with custom view?

I've seen example com.example.android.apis.view.List11 from ApiDemos. In that example, each row takes the view android.R.simple_list_item_multiple_choice. Each such view has a TextView and a CheckBox.
Now I want each view to have 2 TextViews and 1 CheckBox, somewhat similar to the List3 example. I tried creating a custom layout file row.xml like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<CheckBox
android:id="#+id/checkbox"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="fill_parent" />
<TextView
android:id="#+id/text_name"
android:textSize="13px"
android:textStyle="bold"
android:layout_toLeftOf="#id/checkbox"
android:layout_alignParentLeft="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/text_phone"
android:textSize="9px"
android:layout_toLeftOf="#id/checkbox"
android:layout_below="#id/text_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
Then in Activity's onCreate(), I do like this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Query the contacts
mCursor = getContentResolver().query(Phones.CONTENT_URI, null, null, null, null);
startManagingCursor(mCursor);
ListAdapter adapter = new SimpleCursorAdapter(this,
R.layout.row,
mCursor,
new String[] { Phones.NAME, Phones.NUMBER},
new int[] { R.id.text_name, R.id.text_phone });
setListAdapter(adapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
The result kind of looks like what I want, but it looks like the list doesn't know which item of it is selected. Also, I need to click exactly on the CheckBox. In the List11 example, I only need to click on the item row.
So what do I need to do to make a multiple choice list with my custom view for each row? Many thanks.
You have to make your own RelativeLayout that implements the Checkable interface and have a reference to the CheckBox or to the CheckedTextView (or a list if it's multiple choice mode).
Look at this post:
http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/
The answer of Rahul Garg is good for the first time the list is loaded, if you want some rows to be checked depending on the model data, but after that you have to handle the check/uncheck events by yourself.
You can override the onListItemCLick() of the ListActivity to check/uncheck the rows
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
ViewGroup row = (ViewGroup)v;
CheckBox check = (CheckBox) row.findViewById(R.id.checkbox);
check.toggle();
}
If you do so, do not set the ListView to CHOICE_MODE_MULTIPLE, because it makes strange things when calling the function.
To retrieve the list of checked rows, you have to implement a method yourself, calling getCheckItemIds() on the ListView does not work:
ListView l = getListView();
int count = l.getCount();
for(int i=0; i<count; ++i) {
ViewGroup row = (ViewGroup)l.getChildAt(i);
CheckBox check = (Checked) row.findViewById(R.id.ck1);
if( check.isChecked() ) {
// do something
}
}
Each such view has a TextView and a
CheckBox.
No, it doesn't. It has a CheckedTextView.
So what do I need to do to make a
multiple choice list with my custom
view for each row?
Try making the CheckBox android:id value be "#android:id/text1" and see if that helps. That is the ID used by Android for the CheckedTextView in simple_list_item_multiple_choice.
The solution is to create a custom View that implements the Clickable interface.
public class OneLineCheckableListItem extends LinearLayout implements Checkable {
public OneLineCheckableListItem(Context context, AttributeSet attrs) {
super(context, attrs);
}
private boolean checked;
#Override
public boolean isChecked() {
return checked;
}
#Override
public void setChecked(boolean checked) {
this.checked = checked;
ImageView iv = (ImageView) findViewById(R.id.SelectImageView);
iv.setImageResource(checked ? R.drawable.button_up : R.drawable.button_down);
}
#Override
public void toggle() {
this.checked = !this.checked;
}
}
And create a custom layout for the list items using the new widget.
<?xml version="1.0" encoding="utf-8"?>
<ax.wordster.OneLineCheckableListItem xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:background="#drawable/selector_listitem"
android:orientation="horizontal" >
<ImageView
android:id="#+id/SelectImageView"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="#drawable/button_friends_down" />
<TextView
android:id="#+id/ItemTextView"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:gravity="center"
android:text="#string/___"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/text_item" />
</ax.wordster.OneLineCheckableListItem>
Then create a new custom Adapter using the layout above.
It is possible by some trick
in your ListActivtyClass in method
protected void onListItemClick(ListView l, View v, int position, long id) {
//just set
<your_model>.setSelected(true);
}
now in you custom Adapter
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(textViewResourceId, parent, false);
}
if (<your_model>.isSelected()) {
convertView.setBackgroundColor(Color.BLUE);
} else {
convertView.setBackgroundColor(Color.BLACK);
}
return convertView;
}
this way you can customize the view in adapter when the item is selected in the list.
Simple example how to get a custom layout to work as custom checkbox:
private class FriendsAdapter extends ArrayAdapter<WordsterUser> {
private Context context;
public FriendsAdapter(Context context) {
super(context, R.layout.listitem_oneline);
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int pos = position;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rv = inflater.inflate(R.layout.listitem_oneline, parent, false);
rv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
boolean checked = friendsListView.isItemChecked(pos);
friendsListView.setItemChecked(pos, !checked);
}
});
WordsterUser u = getItem(position);
TextView itw = (TextView) rv.findViewById(R.id.ItemTextView);
itw.setText(u.userName + " (" + u.loginName + ")");
ImageView iv = (ImageView) rv.findViewById(R.id.SelectButton);
if (friendsListView.isItemChecked(position)) {
iv.setImageResource(R.drawable.downbutton);
} else {
iv.setImageResource(R.drawable.upbutton);
}
return rv;
}
}
I found it very useful this little code: http://alvinalexander.com/java/jwarehouse/apps-for-android/RingsExtended/src/com/example/android/rings_extended/CheckableRelativeLayout.java.shtml
It is a great addition to #ferdy182 's http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/ content.
Got the solution ... You can get the clicks on the views (like checkboxes in custom layouts of row) by adding listener to each of them in the adapter itself while you return the converted view in getView(). You may possibly have to pass a reference of list object if you intent to get any list specific info. like row id.
I want to confirm that the Pritam's answer is correct. You need an onClickListener on each list's item (define it in the adapter's getView()).
You can create a new onClickListener() for each item, or have the adapter implement onClickListener() - in this case the items must be tagged for the listener to know, which item it is operating on.
Relying on the list onItemClickListener() - as someone advised in another thread - will not work as the CheckBox will intercept the click event so the list will not get it.
And finally #Rahul and JVitella:
The situation is that the CheckBox on a list item must be clickable and checkable independently from the list item itself. Therefore the solution is as I just described above.

How to fire onListItemClick in Listactivity with buttons in list?

I have a simple ListActivity that uses a custom ListAdapter to generate the views in the list. Normally the ListAdapter would just fill the views with TextViews, but now I want to put a button there as well.
It is my understanding and experience however that putting a focusable view in the list item prevents the firing of onListItemClick() in the ListActivity when the list item is clicked. The button still functions normally within the list item, but when something besides the button is pressed, I want onListItemClick to be triggered.
How can I make this work?
as I wrote in previous comment solution is to setFocusable(false) on ImageButton.
There is even more elegant solution try to add android:descendantFocusability="blocksDescendants" in root layout of list element. That will make clicks onListItem possible and separately u can handle Button or ImageButton clicks
Hope it helps ;)
Cheers
I hope I can help here. I assume that you have custom layout for listView items, and this layout consists of button and some other views - like TextView, ImageView or whatever. Now you want to have different event fired on button click and different event fired on everything else clicked.
You can achieve that without using onListItemClick() of your ListActivity. Here is what you have to do:
You are using custom layout, so probably you are overriding getView() method from your custom adapter. The trick is to set the different listeners for your button and different for the whole view (your row). Take a look at the example:
private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {
public MyAdapter(Context context, int resource, int textViewResourceId,
List<String> objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String text = getItem(position);
if (null == convertView) {
convertView = mInflater.inflate(R.layout.custom_row, null);
}
//take the Button and set listener. It will be invoked when you click the button.
Button btn = (Button) convertView.findViewById(R.id.button);
btn.setOnClickListener(this);
//set the text... not important
TextView tv = (TextView) convertView.findViewById(R.id.text);
tv.setText(text);
//!!! and this is the most important part: you are settin listener for the whole row
convertView.setOnClickListener(new OnItemClickListener(position));
return convertView;
}
#Override
public void onClick(View v) {
Log.v(TAG, "Row button clicked");
}
}
Your OnItemClickListener class could be declared like here:
private class OnItemClickListener implements OnClickListener{
private int mPosition;
OnItemClickListener(int position){
mPosition = position;
}
#Override
public void onClick(View arg0) {
Log.v(TAG, "onItemClick at position" + mPosition);
}
}
Of course you will probably add some more parameters to OnItemClickListener constructor. And one important thing - implementation of getView shown above is pretty ugly, normally you should use ViewHolder pattern to avoid findViewById calls.. but you probably already know that.
My custom_row.xml file is RelativeLayout with Button of id "button", TextView of id "text" and ImageView of id "image" - just to make things clear.
Regards!
When a custom ListView contains focusable elements, onListItemClick won't work (I think it's the expected behavior). Just remove the focus from the custom view, it will do the trick:
For example:
public class ExtendedCheckBoxListView extends LinearLayout {
private TextView mText;
private CheckBox mCheckBox;
public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
super(context);
…
mText.setFocusable(false);
mText.setFocusableInTouchMode(false);
mCheckBox.setFocusable(false);
mCheckBox.setFocusableInTouchMode(false);
…
}
}
I have the same problem: OnListItemClick not fired ! [SOLVED]
That's happen on class that extend ListActivity,
with a layout for ListActivity that content TextBox and ListView nested into LinearLayout
and another layout for the rows (a CheckBox and TextBox nested into LineraLayout).
That's code:
res/layout/configpage.xml (main for ListActivity)
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/selection"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="pippo" />
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false"
android:background="#aaFFaa" >
</ListView>
<LinearLayout>
res/layout/row.xml (layout for single row)
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="#+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
**android:focusable="false"**
**android:focusableInTouchMode="false"** />
<TextView
android:id="#+id/testo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
**android:focusable="false"**
**android:focusableInTouchMode="false"** />
</LinearLayout>
src/.../.../ConfigPage.java
public class ConfigPage extends ListActivity
{
TextView selection;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.configpage);
// loaded from res/value/strings
String[] azioni = getResources().getStringArray(R.array.ACTIONS);
setListAdapter(new ArrayAdapter<String>(this, R.layout.row,
R.id.testo, azioni));
selection = (TextView) findViewById(R.id.selection);
}
public void onListItemClick(ListView parent, View view, int position, long id)
{
selection.setText(" " + position);
}
}
This begin to work when I added on row.xml
android:focusable="false"
android:focusableInTouchMode="false"
I use Eclipse 3.5.2
Android SDK 10.0.1
min SDK version: 3
I hope this is helpful
... and sorry for my english :(
just add android:focusable="false" as one of the attributes of your button
I've had the same problem with ToggleButton. After half a day of banging my head against a wall I finally solved it.
It's as simple as making the focusable view un-focusable, using 'android:focusable'. You should also avoid playing with the focusability and clickability (I just made up words) of the list row, just leave them with the default value.
Of course, now that your focusable views in the list row are un-focusable, users using the keyboard might have problems, well, focusing them. It's not likely to be a problem, but just in case you want to write 100% flawless apps, you could use the onItemSelected event to make the elements of the selected row focusable and the elements of the previously selected row un-focusable.
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
Toast.LENGTH_SHORT).show();
}
});
I used the getListAdapter().getItem(position) instantiating an Object that holds my values within the item
MyPojo myPojo = getListAdapter().getItem(position);
then used the getter method from the myPojo it will call its proper values within the item .

Categories

Resources