In ExpandableListView if I only have one group. I want to hide that group, only the group's data show that. Please help me
1) Hide the Group indicator with:
android:groupIndicator="#android:color/transparent"
2) return an empty FrameLayout for the groups you want to be empty like this:
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
//By default the group is hidden
View view = new FrameLayout(context);
String groupTitle = getGroup(groupPosition).toString();
//in case there's more than one group and the group title is not empty then show a TextView within the group bar
if(getGroupCount() > 1 && !groupTitle.isEmpty()) {
view = getGenericView();
((TextView)view).setText(groupTitle);
}
return view;
}
3) Call expandGroup for the groups you are not showing the group bar:
expandableListView.expandGroup(GROUP_ID);
4) If you want to show a group indicator you have to add an ImageView programmatically from the getGroupView method. Check this blog post for more info on hiding/showing group indicator: Hiding group indicator for empty groups
I had the same problem and this solveed my issue.
In your Listview's adapter add the following to the getGroupView.
if (groupPosition == 0) {
convertView = layoutInflater.inflate(R.layout.blank_layout, null);
} else {
convertView = layoutInflater.inflate(R.layout.group_indicator_cell,null);
}
This will blank the 0th groupof the list.
Where blank layout is a layout with some view inside having layout_height=0dp.
It works!
Instead of returning a empty layout, I travel through all children in the layout and call view.setVisibility(View.Gone) when there is no data.
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
LinearLayout lo;
if (convertView != null) {
lo = (LinearLayout) convertView;
} else {
lo = (LinearLayout) mLayoutInflater.inflate(R.layout.list_item_group_header, parent, false);
}
int visibility = mData.size() == 0 ? View.GONE : View.VISIBLE;
for (int i = 0; i < lo.getChildCount(); i++) {
lo.getChildAt(i).setVisibility(visibility);
}
return lo;
}
Set the parent iew vlayout params hieght to zero in your BaseExpandableListAdapter so that you can hide you parent
Related
I'm facing some trouble with the navigation drawer adapter.
It's supposed to display items as follows: Favorito, Categorias, and small sub categories underneath categorias.
I programmed the navigation drawer adapter to use a big_layout.xml file by default, but if its position is greater than a certain value, then it uses a small_layout.xml file.
It works fine for the first few items, but the problem is when I scroll down to see the rest of the items, they use the big_layout.xml, and then when I scroll back up, the original big items change their view and use the small layout!
below is the code, and this is a screen shot of the bad results: http://i.stack.imgur.com/QWwts.jpg
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater laoutInflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (getItemId(position)>3)
view = laoutInflater.inflate(R.layout.drawer_list_item_small, null);
if (getItemId(position)<=3)
view = laoutInflater.inflate(R.layout.drawer_list_item, null);
}
ImageView icon = (ImageView) view.findViewById(R.id.icon);
icon.setImageResource(drawerItems.get(position).getIcon());
TextView title = (TextView) view.findViewById(R.id.title);
title.setText(drawerItems.get(position).getTitle());
return view;}
Is there anything wrong I'm doing ? , Is there something missing that might be responsible of making the view stable?
How can i fix this ?
Your issue is with recycling. When you scroll down and back up, the views using the small layout are no longer needed, and so are eligible for recycling - now, the view is not null, so the layout will not be reinitialised based on its position, but merely updated with the new content.
You can fix this by using ViewTypes in your list adapter class, overriding the following methods.
#Override
public int getItemViewType(int position) {
return (position > 3) ? 0 : 1;
}
#Override
public int getViewTypeCount() {
return 2;
}
Then, in your getView() you will not be given a view (for recycling) if it is of the wrong view type.
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
int layout = getLayoutForViewType(position);
view = LayoutInflater.from(parent.getContext()).inflate(layout, null);
}
...
return view;
}
private int getLayoutForViewType(int position) {
if (getItemViewType(position) == 0) {
return R.layout.blahblahblah;
}
return R.layout.bloobloobloo;
}
By default every group has a downward arrow that indicates to the user that the item can be expanded. However, I have one group that has no children; thus, I would like the arrow to not show on this item.
According to the documentation:
public void setGroupIndicator (Drawable groupIndicator)
Sets the indicator to be drawn next to a group.
Parameters
groupIndicator The drawable to be used as an indicator. If the group is empty, the state state_empty will be set. If the group is expanded, the state state_expanded will be set.
So hypothetically, this should already do the right thing... But, if you are using your own custom ExpandableListAdapter, with TextViews for example, you can use the following code:
// in your main file where the List is defined:
mExpandableList.setGroupIndicator(null); // this will remove the indicator
Then in your custom adapter you could do the following:
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
View v;
...
// code to retrieve convertView or inflate new one and assign to v
...
TextView tv = ((TextView) v);
int iconId; // assume we have an icon we want to have on the left of each group
int expandableGroupResId;
if (getChildrenCount(groupPosition) > 0) {
if (isExpanded) expandableGroupResId = R.drawable.expander_ic_maximized;
else expandableGroupResId = R.drawable.expander_ic_minimized;
}
tv.setCompoundDrawablesWithIntrinsicBounds(iconId, 0, expandableGroupResId, 0);
}
im blazilian so, my english is not good.
So.. i need get view of group in expandablelistview for get your object tag throught view.getTag() method.
follow me in this example:
ExpandableListView
--> group (i need this view)
----> child
----> child
----> child
--> group (i need this view)
----> child
----> child
My code:
#Override
public boolean onChildClick(final ExpandableListView parent, final View v,
final int groupPosition, final int childPosition, final long id) {
/* I NEED GET VIEW OF GROUP FOR GET YOUR TAG*/
View vParent = parent.getChildAt(groupPosition); // dont work after first group
Programa v2 = (Programa) parent.getTag(); // return null
// v parameter is a child of group
return true;
}
in my adapter:
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
TwoLineListItem view = (TwoLineListItem) LayoutInflater.from(contexto)
.inflate(android.R.layout.simple_expandable_list_item_2,
parent, false);
String programa = map.keySet().toArray(new String[map.keySet().size()])[groupPosition];
view.getText1().setText(programa);
view.getText2().setText("PROGRAMA LOCAL");
view.setTag(programas.get(groupPosition)); // i need get this in child click listener
return convertView = view;
}
any idea? thanks
To get the group view from an ExpandableListView, you do something as follows:
public View getGroupView(ExpandableListView listView, int groupPosition) {
long packedPosition = ExpandableListView.getPackedPositionForGroup(groupPosition);
int flatPosition = listView.getFlatListPosition(packedPosition);
int first = listView.getFirstVisiblePosition();
return listView.getChildAt(flatPosition - first);
}
If your code is correct, you want to get the group view for the child so that you can call getTag() on it, correct?
If so, why not just skip that step and access the value of the tag, set by programas.get(groupPosition) manually?
You can do this by calling:
programas.get(groupPosition) right on the top of your onChildClick method since you get the group position value there too.
Edit in response to your comment:
The issue here is that you're not going to be able to get the view of the group through the adapter since it might involve recreating the view due to recycling of views in lists. If this method doesn't work, I strongly suggest modifying your code to make it work.
If programas is one of the inputs to your adapter, then call getGroup(groupPosition) on your adapter to access it. Else, make a public method in your adapter class to allow retrieval of that value.
I tried AedonEtLIRA answer but it only obtained the first item in the list.
My solution was to set a tag in my adapter's getGroupView method.
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.listitem_group, null);
}
//This is your data object that you might be using for storage that can be returned by your getGroup(groupPosition) function
GroupDataDto groupDataDto = (GroupDataDto) getGroup(groupPosition);
String name = groupDataDto.getName();
convertView.setTag(name);
...
Now in your Fragment / Activity, in your onGroupExpand and onGroupCollapse:
GroupDataDto groupDataDto = (GroupDataDto) listAdapter.getGroup(groupPosition);
ImageView arrow = (ImageView) getView().findViewWithTag(groupDataDto.getName()).findViewById(R.id.expandable_arrow_down);
Then I can do my animation on the arrow, which is why I wanted to get that group view.
Well I used the following code to access a TextView in a group:
#Override
public boolean onChildClick(final ExpandableListView parent, final View v,
final int groupPosition, final int childPosition, final long id) {
View vParent = mAdapter.getGroupView(groupPosition, true, null, null);
Programa v2 = (Programa) vParent.getTag();
return true;
}
I hope it helps
I have AlertDialog with single choice list.
I want to put some 'fake' items inside - like labels of following items. I'm using different layout for regular item and for 'label' item. It it OK.
My problem is: How to make labels NON clickable?
Here is my getView code:
// #Override
public View getView(int position, View convertView, ViewGroup parent)
{
if (m_data.get(position).BaseElementType == ElementType.Divider)
{
convertView = m_li.inflate(this.m_groupResurceID, null);
TextView post = (TextView)convertView.findViewById(R.id.text1);
post.setText(m_data.get(position).TypeToString());
post.getClickable();
}
else
{
convertView = m_li.inflate(this.m_itemResurceID, null);
TextView post = (TextView)convertView.findViewById(R.id.text1);
post.setText(m_data.get(position).Header);
ImageView img = (ImageView)convertView.findViewById(R.id.image1);
Drawable dr = m_data.get(position).TypeToIconId();
dr.setColorFilter(BGMapsApp.IconColor, PorterDuff.Mode.SRC_ATOP);
img.setImageDrawable(dr);
}
The answer is so simple!
Just put this to adapter code:
public boolean isEnabled(int position)
{
//return super.isEnabled(position);
return (m_data.get(position).BaseElementType != ElementType.Divider);
}
Now some items become non clickable :)
I have custom groupViews that need to change state when they are expanded and collapsed.
If the same group view is expanded it toggles between two states.
The problem i'm having is that the expand method seems to be pulling up some cached version of the views because my updates aren't visible after calling expandGroup.
If my listener returns true (handles the whole event itself) without calling expandGroup the update does happen. So something is happening with expandGroup that only allows cached view to be drawn.
I have tried invalidating() just about everything. I've tried firing off data update events on the List View. i've tried all this other stuff as well:
expandableList.setGroupIndicator(null);
expandableList.setAlwaysDrawnWithCacheEnabled(false);
expandableList.setWillNotCacheDrawing(true);
expandableList.setItemsCanFocus(false);
no luck on any of those :(
Here's my onClick code:
expandableList.setOnGroupClickListener(new OnGroupClickListener() {
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
MusicTrackRow mt = (MusicTrackRow) v;
if (mt.isPlaying == true) {
mt.setPaused();
} else {
mt.setPlaying();
}
mt.invalidate();
parent.invalidate();
trackAdapter.notifyDataSetInvalidated();
//need to call expandGroup if the listener returns true.. if returning false expandGroup is //returned automatically
expandableList.expandGroup(groupPosition); //no view refresh
return true;
Found a solution finally!
When the expandable list is expanded a call to getGroupview in the adapter is made for every group on the list.
That is the place where you want to effect changes.
the isExpanded argument lets you determine which group view is expanded.
Then you can do stuff that looks like this:
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
View v;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) getBaseContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.expandablelistitem, null);
} else {
v = convertView;
}
int id = (!isExpanded) ? R.drawable.list_plus_selector
: R.drawable.list_minus_selector;
TextView textView = (TextView) v.findViewById(R.id.list_item_text);
textView.setText(getGroup(groupPosition).toString());
ImageView icon = (ImageView) v.findViewById(R.id.list_item_icon);
icon.setImageResource(id);
return v;
}