Android:ListView in PopupWindow cannot be selected - android

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.

Related

I have a ListView with ViewFlippers as rows. I need a list of slideshow of images on each row. Read details

I am a newbie to android programming.
I somehow managed to load the images and set them to auto flipping. What I need is two things.
Each image inside each ViewFLipper is a link to another activity. So I need to set an onClick listener for the ViewFlipper that opens the corresponding activity for each image. I can't seem to get that to work. Code attached below.
I also need for the user to be manually able to scroll (swipe right and left) through each ViewFlipper and see any image she likes (in addition to the auto flipping). I can't understand how to get that done.
Any help will be greatly appreciated!
CustomAdapter.java
public class CustomAdapter extends ArrayAdapter<Integer[]> {
public CustomAdapter(Context context, Integer[][] resource) {
super(context,R.layout.custom_row_main ,resource);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
View view = layoutInflater.inflate(R.layout.custom_row_main, parent, false);
View view1 = layoutInflater.inflate(R.layout.content_main, parent, false);
Integer[] resIds = getItem(position);
final ViewFlipper viewFlipper1 = (ViewFlipper) view.findViewById(R.id.viewFlipper);
for(int i=0;i<resIds.length;i++)
{
ImageButton imageButton = new ImageButton(getContext());
imageButton.setBackgroundResource(resIds[i]);
viewFlipper1.addView(imageButton);
}
viewFlipper1.setFlipInterval(5000);
viewFlipper1.startFlipping();
viewFlipper1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Intent to open the required activity
}
});
return view;
}
}
I found a solution.
Using viewflippers for this was like reinventing the wheel. Just used viewpagers inside a listview. Worked like a charm.
Still can't get the auto scrolling to work, though.
Will update when I do.

How to change the background of a listview in android based on it's position in the list?

I have a listview that is populated via an adapter. I need one of the items (which are just bits of text) in the listview to have a different background compared to the others (to mark it as the currently selected one).
I have all of the background logic, I just need a way to say listview.setBackgroundById(int position)
or something like that.
How do I do this?
This needs to be as simple as possible, 'cause all of the other things done in the Activity are currently working perfectly. :)
As asked, this is my Adapter that I'm using:
public class SampleAdapter extends ArrayAdapter<SampleItem> {
private String title;
public SampleAdapter(Context context) {
super(context, 0);
}
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_station, null);
}
TextView title = (TextView)convertView.findViewById(R.id.station_name);
font.setFont(title, 2, getActivity());
title.setText(getItem(position).title);
RelativeLayout info = (RelativeLayout)convertView.findViewById(R.id.info_relative_button);
info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
MainActivity.setCurrentTab(41);
MainActivity.setBackDisabled(true);
Log.e("current tab:",String.valueOf(MainActivity.getCurrentTab()));
Fragment fragment = new StationInfo();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
UserManager.getInstance().setStationId(getItem(position).id);
}
});
return convertView;
}
}
The SampleItem has 2 String fields, title and id, it's very simple.
You need to use a custom list adapter and have it return views with your desired background. Create a class extending ListAdapter or any of the existing SimpleAdapter etc and override getView to inflate a suitable view for your element, and add any logic you need to set the background of that view.
There is no way to tell the listview itself to decorate some of its elements by id or position.
Update: I just noticed you added the list adapter code.
Since you are already implementing getView, to change the background of your element simply call convertView.setBackgroundColor, or have two different views inflated depending on the situation.
(BTW it's really bad practice to call static methods on your activity like in your onClickListener.)
In ListView adapter:
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
if(view==null)
....
//for example every even list item to be grey, every odd to be white
if(((position+1)%2)==0)
view.setBackgroundColor(mContext.getResources().getColor(R.color.grey));
else view.setBackgroundColor(mContext.getResources().getColor(android.R.color.white));
Hope you get an idea...

ArrayAdapter has strange results - Android

I have an ArrayAdapter class that creates comment boxes. There is a button within the comment box that will be either blue or black. The color of the button is dependent on an array which is received through JSON. If the array looks like this "NO","NO","YES","NO","NO","NO" the third button will have blue text. My JSON and ArrayAdapter class create 7 comment boxes at a time. The problem is once the code changes a button to blue it continuously changes the button blue. By this I mean if an array is received that looks like this "NO","NO","YES","NO","NO","NO" the third button will be blue, then I receive another set of comments so this time the array looks like this "NO","NO","NO","NO","NO","NO" according to this code no button should be blue, but for some reason the third button is still blue. I could load multiple more sets of comments and the third button will always be blue even though the code clearly says it should be black. Strangely the button will be blue but will act as if it were a black button. Here is my ArrayAdapter,
class ListAdapter extends ArrayAdapter<Item> {
public ListAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
private List<Item> items;
public ListAdapter(Context context, int resource, List<Item> items) {
super(context, resource, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.list_item_layout, null);
}
final Item p = items.get(position);
if (p != null) {
//set xml objects
//must be done inside of class
ButtonListViewItem = (TextView) v.findViewById(R.id.button_listview_item);
if(p.getJSONArray().equals("NO")){
ButtonListViewItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ButtonListViewItem.setTextColor(0xff000000);
new AsyncTask().execute();
}//end on click
});
}//end if equals NO
if(p.getJSONArray().equals("YES")){
ButtonListViewItem.setClickable(false);
ButtonListViewItem.setTextColor(0xff3399FF);
}//end if equals yes
}//end if null
return v;
}//end getView
}//end ListAdapter class
The text color is wrong because you're not correctly handling recycled views.
The shortest and simplest solution is to remove this check:
if (v == null)
and inflate a new view every time. This is less efficient, but will make your code easier to work with.
The solution if you opt to continue using recycled views is to explicitly set the text color and clickability of the button every time:
if (p.getJSONArray().equals("YES")) {
ButtonListViewItem.setClickable(false);
ButtonListViewItem.setTextColor(0xff3399FF);
} else {
ButtonListViewItem.setClickable(true);
ButtonListViewItem.setTextColor(0xff000000);
}
The reason you need to do that is because recycled views are handed over just as you left them, changed attributes and all. They will no longer match your XML layout. So when a view that was previously tied to a "YES" is recycled, the changes you made to the text color will still be in place: the text will be blue and the button won't be clickable.
Inflating a new view allows you start in a known state every time---you'll always have something that starts off matching your XML. The tradeoff is efficiency, inflating views is relatively expensive. If your apps needs to be more efficient you should look into the view holder pattern as well, as finding views is also an expense that can be avoided.

Dialog containing ListView whose items do not get touch events

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.

HTC Hero Mouse BOll click not working on Custom ListView?

i have created custom list view using
class EfficientAdapter extends BaseAdapter implements
{
private LayoutInflater mInflater;
private Context context;
public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);
this.context = context;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
ViewHolder holder;
convertView = mInflater.inflate(R.layout.adaptor_content, null);
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
and other necessary methods... also
}
using touch screen when i click on list item OnClickListener of list item is called.
but when i use Mouse Boll / Track Boll (Phone Hardware) to click on ListItem OnClickListener of list item is not called.
can any one guide me is this Phone bug or My Fault?
any help would be appriciated.
but when i use Mouse Boll / Track Boll
(Phone Hardware) to click on ListItem
OnClickListener of list item is not
called.
Press the track ball to register a click. Roll the trackball to change the selection.
You can find information about this topic here:
http://groups.google.com/group/android-developers/browse_thread/thread/5696833388d162fd?pli=1
and here:
link to htp:/developer.android.com/reference/android/view/View.html
to analyze onTrackballEvent(MotionEvent)
i hope that it is useful
bye

Categories

Resources