Android ListView with a Custom Adapter - getChildAt() returns null - android-widget

I have a ListView with a Custom Adapter, and I need to access the View of individual rows of this ListView. I am trying to do it using getChildAt(), but it is returning null.
Here's my ListView:
myListView = (ListView) findViewById (R.id.listViewLayout);
This is the custom adapter:
public class MyListAdapter extends BaseAdapter {
...
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row_layout, parent, false);
}
...
}
I create a List, and set it for the ListView:
List <String> myList = new ArrayList<String>();
myList.add("entry 1");
myList.add("entry 2");
myList.add("entry 3");
MyListAdapter myListAdapter = new MyListAdapter(getApplicationContext(), myList);
myListView.setAdapter(myListAdapter);
Now, I want to access the View for individual rows.
View v = myListView.getChildAt(myListView.getFirstVisiblePosition());
This v is null, no matter what. Additionally, myListView.getChildCount() always returns null.
What am I missing? Do I need to add the convertView to parent in getView()? Am I passing wrong parameters to inflate?
I have struggled a lot to figure this out. Please help me!
EDIT: I am posting the MyListAdapter class:
public class MyListAdapter extends BaseAdapter {
private Context context;
private List<String> myList;
public MyListAdapter(Context c, List<String> m) {
context = c;
myList = m;
}
#Override
public int getCount() {
return myList.size();
}
#Override
public Object getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int pos = position;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row_layout, parent, false);
}
TextView text = (TextView) convertView.findViewById(R.id.itemText);
text.setText(myList.get(pos));
// Set the onClick Listener on this button
Button rowButton = (Button) convertView.findViewById(R.id.itemButton);
//commenting next two lines makes the list row clickable
rowButton.setFocusableInTouchMode(false);
rowButton.setFocusable(false);
rowButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(context, myList.get(pos), Toast.LENGTH_SHORT).show();
}
});
convertView.setTag(pos);
return convertView;
}
}

In all probability you're doing all of this in onCreate(). Any view-related methods will return null (or empty) because the list has not been rendered yet. What do you need the child view for?

Try instead of extending the BaseAdapter, to use the ArrayAdapter class. With the BaseAdapter, I believe that you have to maintain both the list of objects and the views themselves. So something like this
public class MyAdapter extends ArrayAdapter<String>
{
...
}
Then you would create the class like this.
MyListAdapter myListAdapter = new MyListAdapter(getApplicationContext(), R.layout.list_row_layout, myList);
Updated
Also, in your constructor, you are not calling your base class constructor.

Related

ListFragment only showing first item in Fragment View with ExpandableListadpater

I have one fragment with parent and child items. But expandable list only shows the first item in parent list
The problem is that the list view only shows the first item.it contains 3 items, so the listview should show 3 list. Did I miss anything? thanks a lot.
My fragment is
public class FragmentChapters extends ListFragment {
ExpandableListAdapter listAdapter;
ExpandableListView expListView;
List<String> listDataHeader;
HashMap<String, List<String>> listDataChild;
View view;
Context context;
public FragmentChapters() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_chapters, container, false);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
expListView = (ExpandableListView) getListView();
prepareListData();
context=getActivity();
listAdapter = new ExpandableListAdapter(context, listDataHeader, listDataChild);
// setting list adapter
expListView.setAdapter(listAdapter);
}
private void prepareListData() {
listDataHeader = new ArrayList<String>();
listDataChild = new HashMap<String, List<String>>();
// Adding child data
listDataHeader.add("Top 250");
listDataHeader.add("Now Showing");
listDataHeader.add("Coming Soon..");
// Adding child data
List<String> top250 = new ArrayList<String>();
top250.add("The Shawshank Redemption");
top250.add("The Godfather");
top250.add("The Godfather: Part II");
top250.add("Pulp Fiction");
top250.add("The Good, the Bad and the Ugly");
top250.add("The Dark Knight");
top250.add("12 Angry Men");
List<String> nowShowing = new ArrayList<String>();
nowShowing.add("The Conjuring");
nowShowing.add("Despicable Me 2");
nowShowing.add("Turbo");
nowShowing.add("Grown Ups 2");
nowShowing.add("Red 2");
nowShowing.add("The Wolverine");
List<String> comingSoon = new ArrayList<String>();
comingSoon.add("2 Guns");
comingSoon.add("The Smurfs 2");
comingSoon.add("The Spectacular Now");
comingSoon.add("The Canyons");
comingSoon.add("Europa Report");
listDataChild.put(listDataHeader.get(0), top250); // Header, Child data
listDataChild.put(listDataHeader.get(1), nowShowing);
listDataChild.put(listDataHeader.get(2), comingSoon);
}
}
My Expandable lisAdpter is
[public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Context _context;
private List<String> _listDataHeader; // header titles
// child data in format of header title, child title
private HashMap<String, List<String>> _listDataChild;
public ExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listChildData) {
this._context = context;
this._listDataHeader = listDataHeader;
this._listDataChild = listChildData;
}
#Override
public Object getChild(int groupPosition, int childPosititon) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition))
.get(childPosititon);
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.list_item, null);
}
TextView txtListChild = (TextView) convertView
.findViewById(R.id.lblListItem);
txtListChild.setText(childText);
return convertView;
}
#Override
public int getChildrenCount(int groupPosition) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition))
.size();
}
#Override
public Object getGroup(int groupPosition) {
return this._listDataHeader.get(groupPosition);
}
#Override
public int getGroupCount() {
return this._listDataHeader.size();
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.list_group, null);
}
TextView lblListHeader = (TextView) convertView
.findViewById(R.id.lblListHeader);
lblListHeader.setTypeface(null, Typeface.BOLD);
lblListHeader.setText(headerTitle);
return convertView;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
My outupt show this Screen. Only one item listed in fragment.
[1]: https://i.stack.imgur.com/cUiQC.jpg
All is good , Data is actually loading to the expandable list view. Issue is with the layout. You can see the data if you give a fixed height to your Expandable list view. Adjust height of the parent layout (or NestedScrollView) of the view which you used to replace the fragment into your activity.

Delete listview items in custom adapter

I'm sorry for this question, but I'm a new in Android developing. I searched in internet, but I don't found any appropriate answer. I have a following code in my custom adapter:
public class ItemsAdapter extends CursorAdapter {
public ItemsAdapter(Context context, Cursor c) {
super(context, c, false);
}
#Override
public void bindView(View view, Context arg1, Cursor cursor) {
ViewHolder viewHolder = (ViewHolder) view.getTag();
viewHolder.title.setText(cursor.getString(cursor
.getColumnIndex("title")));
viewHolder.publishDate.setText(cursor.getString(cursor.getColumnIndex("date_time")));
viewHolder.rssNewsImage.setImageResource(R.drawable.rssnews);
}
#Override
public View newView(Context arg0, Cursor arg1, ViewGroup arg2) {
View view = LayoutInflater.from(mContext).inflate(
R.layout.listview_rssreaderactivity_row, arg2, false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.title = (TextView) view
.findViewById(R.id.tw_title_listview_row_main);
viewHolder.publishDate = (TextView) view.findViewById(R.id.tw_pubDate_listview_row_main);
viewHolder.rssNewsImage = (ImageView) view.findViewById(R.id.imageRssView);
view.setTag(viewHolder);
return view;
}
public class ViewHolder {
TextView title;
TextView publishDate;
ImageView rssNewsImage;
}
}
I want to delete listView item in my custom adapter. Here is my code for click events:
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
final int position, long id) {
AlertDialog.Builder itemLongClickdialog = new AlertDialog.Builder(
RssNewsActivity.this);
itemLongClickdialog.setItems(R.array.array_longclick_item,
new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
I can't delete given item.
How to resolve this problem? I will appreciate all answers.
Try This:
DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked OK button
ItemsAdapter dba = new ItemsAdapter (yourActivity);
dba.open();
dba.remove(_id);
Log.i("TAAG", "removed: "+_id);
dba.close();
cursor.requery();
listview.getadaper().notifyDataSetChanged();
}
});

setOnCheckedChangeListener

I want to expand the group item when I check on it, but for some reasons I can't collapse the group item after it expands.
Can someone please tell me what I am doing wrong?
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
final GroupHolder holder;
final ViewGroup viewGroup = parent;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.group_list, null);
holder = new GroupHolder();
holder.checkbox = (CheckBox) convertView.findViewById(R.id.cb);
holder.imageView = (ImageView) convertView.findViewById(R.id.label_indicator);
holder.title = (TextView) convertView.findViewById(R.id.group_title);
convertView.setTag(holder);
} else {
holder = (GroupHolder) convertView.getTag();
}
holder.imageView.setImageResource(groupStatus[groupPosition] == 0 ? R.drawable.group_down: R.drawable.group_up);
final Item groupItem = getGroup(groupPosition);
holder.title.setText(groupItem.name);
holder.checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!ALL_CHECKED) {
ArrayList<Item> childItem = getChild(groupItem);
for (Item children : childItem)
children.isChecked = isChecked;
}
groupItem.isChecked = isChecked;
// TODO Auto-generated method stub
if(groupItem.isChecked)
((ExpandableListView) viewGroup).expandGroup(groupPosition);
notifyDataSetChanged();
new Handler().postDelayed(new Runnable() {
public void run() {
// TODO Auto-generated method stub
if (ALL_CHECKED)
ALL_CHECKED = false;
}
}, 10);
}
});
holder.checkbox.setChecked(groupItem.isChecked);
return convertView;
}
//Below is the logcat for when I only put a check mark on group0:
08-19 07:49:08.860: D/group pos: 0
08-19 07:49:08.863: D/group pos: 0
08-19 07:49:08.887: D/group pos: 4
I noticed that it showed groupId0 & 4 when I ONLY clicked on group0
Edit: Re-wrote to make it clear for others to understand better
I have one idea.
First remove CheckBOx and try to collapse by this
lv.setOnGroupExpandListener(new OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
if (lastExpandedPosition != -1
&& groupPosition != lastExpandedPosition) {
lv.collapseGroup(lastExpandedPosition);
}
lastExpandedPosition = groupPosition;
}
});
If still getting any problem please ping me if not getting any problem then add view and view group
First of all, thanks a lot to Blue Green for trying to help. I figured it out after days of debugging. The reason that it didn't let me collapse the expanded group was
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
AND
public View getChildView(final int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
BOTH had final int groupPosition. This is why the expandablelistview doesn't know which groupPosition that I want to collapse. Furthermore, because of this, it printed out groupId0 & 4 when I ONLY clicked on group0.
ExpandalblelistView is very ^$^** hard to deal with for me. I hope this helps someone else.

Unable to load tab in PagerSlidingTabStrip when fragment is replaced

I'm trying to implement a viewpager with a PagerSlidingTabStrip instead of a TabView. The viewpager has three tabs in which each listview displays a list of events. The three tabs are called Past, Tonight and Future.
I've set up the slider as the github page suggests:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.all_events_main_strip, container, false);
// Set up the ViewPager, attaching the adapter and setting up a listener for when the
// user swipes between sections.
pager = (ViewPager) v .findViewById(R.id.pager_main);
tabs = (PagerSlidingTabStrip) v.findViewById(R.id.tabs);
adapter = new MyPagerAdapter(getFragmentManager());
pager.setAdapter(adapter);
tabs.setViewPager(pager);
// Set Present tab as default
pager.setCurrentItem(1);
return v;
}
When the app starts the Main Activity adds for the first time this fragment and everything works great. 3 swipeable tabs with 3 listviews. (c.f. code section)
Here is the problem:
I've noticed that when I press the back button and replace the fragment again, in order to reopen the viewpager, the tab in the middle doesn't show any listview. If I swype left or right the content in the other tabs is loaded and displayed but the Present Tab remains empty.
When I debug the ToNightEvents ListFragment isn't called at all.
Do you guys have any suggestions to solve the problem?
The code:
The code is structured as follows: After the onCreateView I've added an OnDestroyView method to remove the fragment but it didn't work... Then in the fragmentPagerAdapter each page is called as a fragment in the getItem method. Finally at the end of the code you can see the three ListFragment classes in which a listview is populated through an AsyncTask
public class FragmentAllEvents extends Fragment
{
private static final String TAG_UID = "uid";
private static final String TAG_LOGO = "logo";
private static final String TAG_POKUID = "pokuid";
static ArrayList<HashMap<String, String>> userList;
ArrayList<HashMap<String, String>> userListTotal;
private final Handler handler = new Handler();
HashMap<String, String> userSelected;
EventsFunctions eventsFunctions;
UserFunctions userFunctions;
static ListView lv;
ActionBar actionBar;
MyPagerAdapter adapter;
ViewPager pager;
PagerSlidingTabStrip tabs;
private Drawable oldBackground = null;
private int currentColor = 0xFF666666;
//Context context = this;
#Override public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Set up the action bar.
actionBar = getActivity().getActionBar();
actionBar.setHomeButtonEnabled(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.all_events_main_strip, container, false);
pager = (ViewPager) v .findViewById(R.id.pager_main);
tabs = (PagerSlidingTabStrip) v.findViewById(R.id.tabs);
adapter = new MyPagerAdapter(getFragmentManager());
pager.setAdapter(adapter);
tabs.setViewPager(pager);
pager.setCurrentItem(1);
return v;
}
#Override
public void onDestroyView()
{
super.onDestroyView();
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
}
public static class MyPagerAdapter extends FragmentPagerAdapter
{
public MyPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int i)
{
switch (i)
{
case 0:
return new PastEvents();
case 1:
return new ToNightEvents();
case 2:
return new FutureEvents();
/*default:
// The other sections of the app are dummy placeholders.
return new ToNightEvents();
*/
}
return null;
}
/**
* A fragment that launches past events list.
*/
public static class PastEvents extends ListFragment implements
PullToRefreshAttacher.OnRefreshListener
{
private ListView pastList;
private PullToRefreshAttacher mPullToRefreshAttacher;
ProgressBar progress;
String tabTime;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View pastView = inflater.inflate(R.layout.pastlist, container, false);
progress = (ProgressBar) pastView.findViewById(R.id.loading_spinner_past);
tabTime="past";
pastList = (ListView) pastView.findViewById(android.R.id.list);
// Now get the PullToRefresh attacher from the Activity. An exercise to the reader
// is to create an implicit interface instead of casting to the concrete Activity
mPullToRefreshAttacher = ((Home) getActivity()).getPullToRefreshAttacher();
// Now set the ScrollView as the refreshable view, and the refresh listener (this)
mPullToRefreshAttacher.addRefreshableView(pastList, this);
new AsyncLoadEvents(getActivity(), progress, pastList, mPullToRefreshAttacher).execute(tabTime);
return pastView;
}
#SuppressWarnings("unchecked")
#Override
public void onListItemClick(ListView listView, View view, int position, long id)
{
super.onListItemClick (listView, view, position, id);
HashMap<String, String> map = (HashMap<String, String>) getListView().getItemAtPosition(position);
//Log.e("AttendList Report", "Clicked list item: " + position +" Content: \n" + map.get(TAG_ID).toString());
Log.e("PastList Report", "Clicked list item: " + position +" Event's content: \n" + map.get(TAG_UID).toString());
Intent intent = new Intent(getActivity(), SingleEventActivity.class);
intent.putExtra("pokuid",map.get(TAG_POKUID)); // Maybe remove attribute toString();
intent.putExtra("uid", map.get(TAG_UID));
intent.putExtra("logo",map.get(TAG_LOGO));
getActivity().startActivity(intent);
}
#Override
public void onRefreshStarted(View view)
{
new AsyncLoadEvents(getActivity(), progress, pastList, mPullToRefreshAttacher).execute(tabTime);
}
}
/**
* A fragment that launches future event list.
*/
public static class FutureEvents extends ListFragment implements
PullToRefreshAttacher.OnRefreshListener
{
private ListView futureList;
private PullToRefreshAttacher mPullToRefreshAttacher;
ProgressBar progress;
String tabTime;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View futureView = inflater.inflate(R.layout.futurelist, container, false);
progress = (ProgressBar) futureView.findViewById(R.id.loading_spinner_future);
tabTime = "future";
futureList = (ListView) futureView.findViewById(android.R.id.list); //change to attendlist if needed
// Now get the PullToRefresh attacher from the Activity. An exercise to the reader
// is to create an implicit interface instead of casting to the concrete Activity
mPullToRefreshAttacher = ((Home) getActivity()).getPullToRefreshAttacher();
// Now set the ScrollView as the refreshable view, and the refresh listener (this)
mPullToRefreshAttacher.addRefreshableView(futureList, this);
new AsyncLoadEvents(getActivity(), progress, futureList, mPullToRefreshAttacher).execute(tabTime);
return futureView;
}
#SuppressWarnings("unchecked")
#Override
public void onListItemClick(ListView listView, View view, int position, long id)
{
super.onListItemClick (listView, view, position, id);
HashMap<String, String> map = (HashMap<String, String>) getListView().getItemAtPosition(position);
Log.e("PastList Report", "Clicked list item: " + position +" Event's content: \n" + map.get(TAG_UID).toString());
Intent intent = new Intent(getActivity(), SingleEventActivity.class);
intent.putExtra("pokuid",map.get(TAG_POKUID)); // Maybe remove attribute toString();
intent.putExtra("uid", map.get(TAG_UID));
intent.putExtra("logo",map.get(TAG_LOGO));
getActivity().startActivity(intent);
}
#Override
public void onRefreshStarted(View view)
{
new AsyncLoadEvents(getActivity(), progress, futureList, mPullToRefreshAttacher).execute(tabTime);
}
}
/**
* A fragment that launches future event list.
*/
public static class ToNightEvents extends ListFragment implements
PullToRefreshAttacher.OnRefreshListener
{
private ListView tonightList;
private PullToRefreshAttacher mPullToRefreshAttacher;
ProgressBar progress;
String tabTime;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View tonightView = inflater.inflate(R.layout.tonightlist, container, false);
progress = (ProgressBar) tonightView.findViewById(R.id.loading_spinner_tonight);
tabTime = "tonight";
tonightList = (ListView) tonightView.findViewById(android.R.id.list); //change to attendlist if needed
// Now get the PullToRefresh attacher from the Activity. An exercise to the reader
// is to create an implicit interface instead of casting to the concrete Activity
mPullToRefreshAttacher = ((Home) getActivity()).getPullToRefreshAttacher();
// Now set the ScrollView as the refreshable view, and the refresh listener (this)
mPullToRefreshAttacher.addRefreshableView(tonightList, this);
new AsyncLoadEvents(getActivity(), progress, tonightList, mPullToRefreshAttacher).execute(tabTime);
return tonightView;
}
#SuppressWarnings("unchecked")
#Override
public void onListItemClick(ListView listView, View view, int position, long id)
{
super.onListItemClick (listView, view, position, id);
HashMap<String, String> map = (HashMap<String, String>) getListView().getItemAtPosition(position);
Log.e("PastList Report", "Clicked list item: " + position +" Event's content: \n" + map.get(TAG_UID).toString());
Intent intent = new Intent(getActivity(), SingleEventActivity.class);
intent.putExtra("pokuid",map.get(TAG_POKUID)); // Maybe remove attribute toString();
intent.putExtra("uid", map.get(TAG_UID));
intent.putExtra("logo",map.get(TAG_LOGO));
getActivity().startActivity(intent);
}
#Override
public void onRefreshStarted(View view)
{
new AsyncLoadEvents(getActivity(), progress, tonightList, mPullToRefreshAttacher).execute(tabTime);
}
}
public String[] titles=
{
"Past",
"Tonight",
"Future"
};
#Override
public int getCount()
{
return titles.length;
}
#Override
public CharSequence getPageTitle(int position)
{
return titles[position];
}
}
}
This would normally work if you were in an Activity, however I guess you are in a Fragment since the code you posted is the method onCreateView(). The problem is that you are trying to use the FragmentManager of the Activity and you should be using the Fragment's FragmentManager. This FragmentManager is not what you need. Try this instead:
adapter = new MyPagerAdapter(getChildFragmentManager());
I think I'm a little bit late but if anyone happens to have the same error here is the solution =)
Q.
The following fixed it for me:
Add an OnBackStackChangedListener to the fragment manager.
In the onBackStackChanged method, get references to both the ViewPager and the PagerSlidingTabStrip (pager and tabs in your example). If the appropriate fragment is currently active, do the following:
pager.invalidate();
tabs.invalidate();
pager.setAdapter(new MyPagerAdapter(getFragmentManager()));
tabs.setViewPager(pager);

How to set the color of the first column of a Listview item?

I have a Listview (shown in an AlertDialog) that is composed by two columns, made with a HashMap (got the idea somewhere here).
Each column is a TextView. It works well.
Now I want to change the textcolor of the first column of a given row, but I have no idea on how to pick and set this... I googled for hours! Any clues??
This is my code (lists is a SortedSet):
public void showlistdesc () {
ListView listview = new ListView(this);
listview.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
listview.setSoundEffectsEnabled(true);
listview.setSelector(R.drawable.selector);
Integer i=0, pos = 0;
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map;
for (String l : lists) {
if (l.equals(currlist)) pos = i;
i++;
map = new HashMap<String, String>();
map.put("list", l);
map.put("desc", getlistdesc(l, false));
mylist.add(map);
}
listview.setAdapter(new SimpleAdapter(this, mylist, R.layout.lists_row,
new String[] {"list", "desc"}, new int[] {R.id.list1, R.id.desc1}));
AlertDialog.Builder builder = new AlertDialog.Builder(AveActivity.this)
.setView(listview)
.setIcon(R.drawable.ic_launcher)
.setTitle(lists.size() + " bird lists in databases");
final AlertDialog dial = builder.create();
//Scrolls the listview to this position at top
listview.setSelection(pos);
dial.show();
}
Thanks!
EDIT
Tried to extend SimpleAdapter with the following code, and all I can see are solid black rows:
public class MySimpleAdapter extends SimpleAdapter {
private Context context;
public MySimpleAdapter(Context context,List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.lists_row, null);
}
TextView list1 = ((TextView) v.findViewById(R.id.list1));
TextView desc1 = ((TextView) v.findViewById(R.id.desc1));
if (v.isPressed()) {
v.setBackgroundColor(context.getResources().getColor(R.color.pressed));
list1.setTypeface(null, 1);
list1.setTextColor(context.getResources().getColor(R.color.selected));
} else {
v.setBackgroundColor(context.getResources().getColor(R.color.black));
if (v.isSelected()) {
list1.setTypeface(null, 1);
list1.setTextColor(context.getResources().getColor(R.color.checked));
desc1.setTextColor(context.getResources().getColor(R.color.white));
} else {
list1.setTypeface(null, 0);
list1.setTextColor(context.getResources().getColor(R.color.normal));
desc1.setTextColor(context.getResources().getColor(R.color.lesswhite));
}
}
return v;
}
}
Now you have special requirement, it is no longer simple, you can't use SimpleAdapter to achieve the effect you are asking. You will have to extend BaseAdapter and in the getView() method you can do the following:
if (position == 0) {
convertView.setBackground(color1);
} else {
convertView.setBackground(color2);
}
Or if what you want is a Header, you can use ListView.addHeaderView() without much hassle.
I found a solution, essentially contained in several posts here.
What I did was to use listview.setItemChecked(pos, true);, something that I tried before and failed, because it showed nothing. The problem was that LinearLayout does not implement Checkable. So I implemented it (code found essentially somewhere here also) with this:
public class CheckableLinearLayout extends LinearLayout implements Checkable {
private boolean isChecked;
public CheckableLinearLayout(Context context) {
super(context);
}
public CheckableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
TextView list1 = ((TextView) findViewById(R.id.list1));
TextView desc1 = ((TextView) findViewById(R.id.desc1));
if (isPressed()) {
list1.setTextColor(getResources().getColor(R.color.selected));
setBackgroundColor(getResources().getColor(R.color.pressed));
} else {
setBackgroundColor(getResources().getColor(R.color.black));
if (isChecked) {
list1.setTextColor(getResources().getColor(R.color.checked));
desc1.setTextColor(getResources().getColor(R.color.white));
} else {
list1.setTextColor(getResources().getColor(R.color.normal));
desc1.setTextColor(getResources().getColor(R.color.lesswhite));
}
}
}
public boolean isChecked() {
return isChecked;
}
public void toggle() {
setChecked(!isChecked);
}
}
And that's it. No need to use selector, nor to touch the adapter. To make this work, in the row layout, use <com.[yourpackage].CheckableLinearLayout instead of the usual LinearLayout.