Problems with ListView inside PopupWindow
I have ListView
in PopupWindow
. PopupWindow
initialized like this
window.setContentView(root);
window.setTouchable(true);
window.setFocusable(true);
window.setOutsideTouchable(true);
window.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
Then ListView
:
fileList = (ListView) root.findViewById(R.id.explorer_list);
fileList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
fileList.setSelector(android.R.drawable.screen_background_light_transparent);
fileList.setOnItemClickListener(this);
[...]
@Override
public void onItemClick(AdapterView<?> adapter, View v, int pos, long id) {
selected = (File) fileList.getItemAtPosition(pos);
}
Likewise, everything works correctly, except that the selector will not appear on selection until ListView
it is scrolled (nothing is visually displayed as selected until the list is scrolled even though the item is correctly selected).
If I set the PopupWindow
non-customizable then the visual selection works correctly (the item is visually selected on the right when clicked), but it onItemClick()
never gets called and therefore I cannot get the selected item.
ListView.getSelectedItem()
always returns null
in both cases, even if there is a selected item.
Any idea on how to resolve this situation? Thanks in advance.
source to share
I finally used a custom adapter to store the selected value and use it from there to mark it:
public class FileExplorerAdapter extends ArrayAdapter<File> {
/** File names */
private List<File> values = new ArrayList<File>();
/** Currently selected position */
private int selected = -1;
public FileExplorerAdapter(Context context, List<File> values) {
super(context, R.layout.explorer_row, values);
this.values = values;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// I know that my layout is always a TextView
TextView row = (TextView) convertView;
if (row == null) {
row = (TextView) ViewHelper.inflateViewById(getContext(),
R.layout.explorer_row);
}
// More code...
// Set up the background for selected element
if (selected == position) {
row.setBackgroundColor(Color.LTGRAY);
// Override background selector
} else {
row.setBackgroundColor(Color.TRANSPARENT);
}
// More code...
return row;
}
/** This sets the selected position */
public void setSelected(int position) {
selected = position;
}
}
And in the class that implements OnItemClickListener
for the linked ListView
, I customize the currently selected item in the adapter.
@Override
public void onItemClick(AdapterView<?> adapter, View v, int pos, long id) {
FileExplorerAdapter fileadapter = (FileExplorerAdapter) fileList
.getAdapter();
fileadapter.setSelected(pos);
}
source to share
I had a similar problem, but it was required in my case PopupWindow.setFocusble(false)
(and using was ListPopupWindow
not a solution in my case, since the project was already using the basic functionality PopupWindow
, including the extension).
If anyone in the same situation there is some sort of workaround based on the abouton error here (post # 9)
The basic idea is that the hierarchy ListView
still receives touch events, so we can trigger manually onItemClick()
.
However, this approach is not 100% identical to actual touch handling ListView
(e.g. no selection glow when row is pressed), this is pretty good for me at the moment.
If anyone has a more accurate solution to this problem please share.
So, here is the complete code Adapter
that can be used from 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;
}
}
source to share
use this
fileList.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1,
int pos, long arg3) {
selected = (File) fileList.getItemAtPosition(pos);
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
} );
source to share