Dialog containing ListView whose items do not get touch events - android

I have a custom dialog which extends Dialog and has a ListView inside its layout. I populate my ListView via a custom adapter which extends ArrayAdapter. Here is my adapter which contains the onClick event for a given list item:
public class PendingTimeslotArrayAdapter extends ArrayAdapter<PendingTimeslot> {
private final Context context;
private final PendingTimeslot[] values;
private final View[] views;
public PendingTimeslotArrayAdapter(Context context, PendingTimeslot[] values) {
super(context, R.layout.mystuff_timeslot_picker_dialog_list_item, values);
this.context = context;
this.values = values;
this.views = new View[values.length];
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(views[position] == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.mystuff_timeslot_picker_dialog_list_item, parent, false);
rowView.setTag((Integer)position);
((TextView)rowView.findViewById(R.id.mystuff_timeslot_picker_list_item_date_time)).setText(values[position].getDateTime());
((TextView)rowView.findViewById(R.id.mystuff_timeslot_picker_list_item_stage_name)).setText(values[position].getStageName());
rowView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("getting touch event");
PendingTimeslot t = values[(Integer)(v.getTag())];
CheckBox checkBox = (CheckBox) v.findViewById(R.id.mystuff_timeslot_picker_list_item_checkbox);
checkBox.setChecked(!checkBox.isChecked());
t.toggle();
}
});
views[position] = rowView;
return rowView;
}
else
return views[position];
}
}
My problem is that when list items are clicked, they do not get touch events, hence my onClick does not get called. Funny thing is, the ListView is fully scrollable and when an item goes out of the visible region and comes back, it becomes touchable and the onClick event is fired.
I tried overriding the ListView and its onTouchEvent method; when an item is clicked, the onTouchEvent on the ListView is really not fired. I also tried overriding the dispatchTouchEvent method and it works correctly, getting all touch events as it is supposed to.
I have used a similar custom ArrayAdapter elsewhere (but not within a Dialog) and it works flawlessly. I am now considering this to be a bug. Am I missing something or should I do this (ListView with clickable items inside a Dialog) another way?
Edit:
Adding
rowView.setClickable(true);
rowView.setFocusable(true);
does absolutely nothing.
Edit2:
Setting an onItemClickListener for my ListView does not work either, even for the items which are scrolled out of and back into the visible region.
Edit3:
I also noticed that when there are 16 items (not a special number) in the ListView, the last 5 items do not get the height I specified (e.g 100px) in the layout I inflate, they behave like wrap_content instead. All in all, I'm starting to believe that a ListView should not be used in a Dialog.

One possible solution I found is to quit trying to use a ListView and instead use a ScrollView with a vertical LinearLayout inside. The layout of this ScrollView is like this:
<ScrollView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" >
<LinearLayout
android:id="#+id/mystuff_timeslot_picker_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
After I get the list data, I inflate a row for each of them and add them to the LinearLayout manually:
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for(PendingTimeslot p : timeslots){
View rowView = inflater.inflate(R.layout.mystuff_timeslot_picker_dialog_list_item, timeslotList, false);
//((TextView)rowView.findViewById(R.id.mystuff_timeslot_picker_list_item_date_time)).setText(values[position].getDateTime());
((TextView)rowView.findViewById(R.id.mystuff_timeslot_picker_list_item_date_time)).setText("just testing");
//((TextView)rowView.findViewById(R.id.mystuff_timeslot_picker_list_item_stage_name)).setText(values[position].getStageName());
rowView.setClickable(true);
rowView.setFocusable(true);
rowView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("just testing");
//PendingTimeslot t = values[(Integer)(v.getTag())];
CheckBox checkBox = (CheckBox) v.findViewById(R.id.mystuff_timeslot_picker_list_item_checkbox);
checkBox.setChecked(!checkBox.isChecked());
}
});
timeslotList.addView(rowView);
}
timeslotList is the LinearLayout I mentioned. This workaround works as expected. Still, I'm feeling very stupid having to use ScrollViews instead of ListViews when they are perfect for the job.

Related

onClickListener for custom ListView item with multiple Buttons

In my program, I have a Fragment which dynamically adds custom items to a ListView. These items each have 2 Buttons, which are supposed to have a certain functionality (like removing the specific item from the list). I would like to set an OnClickListener for them, calling a function within my Fragment Class.
Simple xml onClick attributes cannot find the function and when I try to add the onClickListener within the onCreateView() method (like with Listeners for static Buttons). But when the fragment is created, a NullPointerException is called, because the referenced Buttons are not part of the Fragment (?).
How can I call a function from my Fragment after pressing a dynamically added Button (or Checkbox)?
this is easier if you post some code
In my code I have something similar, I have one listview with a Array Adapter, and in some line I have one imageButton with a funtion.
I solve my problem with a class to work on my adapter and in that that I apply the functionaly to the Button.
Main_Class code :
ListViewResources listViewResources = new ListViewResources(this, resourcesName);
listView = (ListView) popupView.findViewById(R.id.listView1);
listView.setAdapter(listViewResources);
ListViewResouces_Class:
public class ListViewResources extends ArrayAdapter<String>{
Activity context;
String[] resourcesName;
public ListViewResources(Activity context, String[] resourcesName) {
super(context, R.layout.popup_listitem_resources, resourcesName);
this.context = context;
this.resourcesName = resourcesName;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.popup_listitem_resources, null, true);
TextView resourceName = (TextView)rowView.findViewById(R.id.textViewResourceName);
ImageView openResource = (ImageView)rowView.findViewById(R.id.buttonOpenResource);
openResource.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//code for happen on Button Click
}
});
resourceName.setText(resourcesName[position]);
return rowView;
}

Multi-touch in ListView containing EditText and CheckBox on each row item (Android)

I have a ListView where each row item has EditText and CheckBox elements. You can see the sample image below.
What I intend to do is
I want to implement both OnItemClickListener (for ListView) and OnClickListener (for EditText and CheckBox) i.e. I want Task A to be done on clicking the ListView items (outside EditText and CheckBox) and I also want to do individual tasks on clicking EditText and CheckBox respectively.
My Problem
If no attribute is set on ListView, EditText or CheckBox to control the focus, then the default behaviour is that ListView row items won't listen to item click, but EditText and CheckBox are getting the focus
On playing around with these attributes and there values (eg - )
// to ListView
android:descendantFocusability="blocksDescendants"
// to EditText and CheckBox
android:focusable="false"
android:focusableInTouchMode="true"
Listeners are working either for ListView or for the EditText. CheckBox click listener seems to work in all cases (strange). I am new to this and any kind of help would be appreciated. I cannot post the source right now, for that please bear with me. Any solution, suggestion or explanation would do a great help.
I am glad that I happen to solve this problem. What I wanted to do was (let me clear it out again) I wanted the EditText to be focusable and additionally I should be able to click on each row of the ListView to perform some specific task. Well we won't be needing these attributes:
android:focusable=""
android:focusableInTouchMode=""
android:descendantFocusability=""
What simple needed to be done is
In you custom ListAdapter class implement OnClickListener for each items (say EditText, CheckBox, etc.) and implement OnClickListener of rootView (i.e. for ListView row item) too.
For Example:
public class CustomListAdapter extends ArrayAdapter<YOUR_OBJECT> {
Context context;
ArrayList<YOUR_OBJECT> itemlist = new ArrayList<YOUR_OBJECT>();
Integer resourceID;
ViewHolder holder;
public ServicesListAdapter(Context context, int resourceId, ArrayList<YOUR_OBJECT> itemlist) {
super(context, resourceId, itemlist);
this.itemlist.addAll(itemlist);
this.context = context;
this.resourceID = resourceId;
}
public class ViewHolder {
TextView name;
EditText editText;
CheckBox checkBox;
}
public View getView(final int position, View rootView, ViewGroup parent) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (rootView == null) {
rootView = mInflater.inflate(resourceID, null);
holder = new ViewHolder();
holder.name = (TextView) rootView.findViewById(R.id.name);
holder.editText = (EditText) rootView.findViewById(R.id.port);
holder.checkBox = (CheckBox) rootView.findViewById(R.id.check_box);
// Add Listeners for EditText and CheckBox here
rootView.setTag(holder);
} else {
holder = (ViewHolder) rootView.getTag();
}
// Click Listener for the ListView row item
rootView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "Clicked" + position, Toast.LENGTH_SHORT).show();
}
});
// Do what rest you need to do with your ViewHolder
}
}

HorizontalScrollView in ListView items

I'm using a LinearLayout which contains an ImageView and a HorizontalScrollView as ListView items.
The problem is OnItemClickListener of the ListView doesn't work. After adding android:descendantFocusability="blocksDescendants" on LinearLayout it works when ImageView is clicked but it doesn't work when HorizontalScrollView is clicked.
android:focusable="false" and android:focusableInTouchMode="false" doesn't work too.
I want regular clicks on HorizontalScrollView also fires OnItemClickListener of ListView.
I'm testing on android 4.2.2
I had the same problem and did not find any better solution than just to assign View.onClickListener to descendant of HorizontalScrollView. In my case I needed to know the position value from ArrayAdapter belonging to the clicked listview item, which I passed to the view during the getView execution as a view tag.
RelativeLayout -> HorizontalScrollView -> Relative Layout #+id/clickit ...
public View getView(int position, View convertView, ViewGroup parent)
{
layoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(resourceID, parent, false);
MyType mt = getItem(position);
RelativeLayout rl = (RelativeLayout) rowView.findViewById(R.id.clickit);
rl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
m_menuEventsListener.onActionsMenuClick(getItem((Integer) view.getTag()));
}
});
rl.setTag(position);
}
Note that the same m_menuEventsListener.onActionsMenuClick is called from the onItemClickListener attached to the listview. m_menuEventsListener is my own listener implemented in the Activity.

Android:ListView in PopupWindow cannot be selected

I set the layout which has a listview to a popupwindow,and then I set the popupwindow.setFocusale(false);,and add "android:focusable="true"" attribute to listview,
after that I click the listview in the popupwindow ,the item in listview cannot be selected,
can anyone tell the solution?
Thanks in advance!
I had the same problem, and in my case PopupWindow.setFocusble(false) was required (and using ListPopupWindow was not a solution in my case as a lot of stuff in the project already used base PopupWindow's functionality including extending).
If someone in the same situation there is a kind of workaround based on bug discusson here (post #9)
The main idea is that ListView's hierarchy is still receives touch events so we can manually trigger onItemClick().
However this approach is not 100% identical to real ListView's touch handling (like there is no glow of selection while tapping a row) this done pretty well for me for the moment.
If someone has more precise solution of this problem, please share.
So, here is complete Adapter's code which can be used with ListView inside PopupWindow which is setFocusable(false):
private class CustomAdapter extends ArrayAdapter {
private LayoutInflater mInflater;
private ListView mOwningListView;
public CustomAdapter(Context context, List<String> objects, ListView listView) {
super(context, android.R.layout.simple_list_item_1, objects);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mOwningListView = listView;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.font_pick_row, null);
}
// this is the key point of workaround
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
/*
* as every row is still receiving their touches
* we can use this to manually trigger onItemClick
* since it doesn't firing in popupWindow.setFocusable(false)
*/
mOwningListView.getOnItemClickListener().onItemClick(mOwningListView, v, position, getItemId(position));
}
});
//... other stuff
return convertView;
}
}
why are u making popupwindow focus false..does it affect your UI if it left focussable.i guess thats the reason ListView is not getting focus.

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