It got me wondering on how to implement an "onChildChildClickListener" into this three level expandable list view after answering the question of how to populate three level expandable list view (Populate different arrays in third layer of expandableListView).
How does one implement the third level being Clickable?
Example code by BKN is published on githube here:
https://github.com/ngocchung/ThreeLevelExpListView
Does anybody have an idea?
Help would be gladly appreciated as I would like to implement this into an showcase app as a part of my Masterthesis.
Found the solution after reading the comments in this How to add Three Level ListView in ExpandableListView in android
this needs to be implemented in the ParentLevelAdapter in the public View getChildView part.
#Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final CustomExpListView secondLevelExpListView = new CustomExpListView(this.mContext);
String parentNode = (String) getGroup(groupPosition);
secondLevelExpListView.setAdapter(new SecondLevelAdapter(this.mContext, mListData_SecondLevel_Map.get(parentNode), mListData_ThirdLevel_Map));
secondLevelExpListView.setGroupIndicator(null);
//newcode
secondLevelExpListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener(){
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition,long id)
{ String selectText = ((TextView) v).getText().toString();
switch (selectText){
case "ItemName you want to do something with":
//Actions you want to do when clicking this item
break;
case "ItemName2 you want to do something with":
//Actions you want to do when clicking this second item
break;
default:
//default actions on all other items
}
return false;}
});
return secondLevelExpListView;
}
Related
First of all, I'm new to programming. Is it possible to create custom expandable list in each child that has a different layout? If yes, please help me out!
There are three parents, each having a textview and a switch.
The child of first parent has:
textview
Seekbar
edittext
The child of second parent has:
textview
timepicker
textview
edittext
The child of third parent has:
textview
edittext
Please check this photoshop mockup, which is want I'd like to impliment:
Should I create three different XML for each child, or is it the adapter who plays a role here?
If not possible with expandable list, HOW can I implement this ?
Any suggestion to guide, tutorial is appreciated. :)
You can in a custom adapter but you have to create the respective layouts. Use something like the following in your getView() method.
switch (groupPosition) {
case 0:
convertView = inflater.inflate(R.layout.group1, null);
break;
case 1:
convertView = inflater.inflate(R.layout.group2, null);
break;
}
As you are using two types of views of children items of the group. So you have to override the following two methods
final int CHILDVIEW_ONE = 0;
final int CHILDVIEW_TWO = 1;
final int CHILDVIEW_TYPE_COUNT = CHILDVIEW_TWO + 1;
#Override
public int getChildTypeCount() {
return CHILDVIEW_TYPE_COUNT;
}
#Override
public int getChildType(int groupPosition, int childPosition)
{
if(childObject instanceOf item1)
return CHILDVIEW_ONE;
else if (childObject instance item2)
return CHILDVIEW_TWO;
return super.getChildType(int groupPosition, int childPosition);
}
Then in your getChildView() Do the following:
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
....
if(childObject instanceOf item1){
//handle the first child view
}else if (childObject instanceOf item2){
//handle the second child view
}
....
}
You have to override both getChildType and getChildTypeCount in order to use the concept of viewholders which optimizes the Memory peroformance drawing a scrollview
I have subclassed BaseExpandableListAdapter in the rows for the BaseExpandableListView I'm having a CheckedTextView. What I want to achieve is that there can only be checked items in one of the groups in the BaseExpandableListView.
So if there is already checked items in group 0 and the user tries to check any items in group 1 then a toast message should display saying something that he has to uncheck the items in group 0 or something like that.
So far my code looks like this:
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
ViewGroup parent) {
...
holder.checkedTextView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
((CheckedTextView) v).toggle();
}
});
holder.checkedTextView.setText(person.getName());
holder.checkedTextView.setChecked(person.isTracked());
return convertView;
}
I suppose I need to get a reference or something to BaseExpandableListView inside the onClick method to find out which group the currently toggled CheckedTextView is inside?
I'm not sure if my terminology is correct since I just started coding on Android.
I figured out how to do it with the int groupPosition, int childPosition variables.
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
Hi guys I am trying to change the value of the parent by clicking a child in a expandable list. I have looked for a solution but cant find anything.
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id){
ExpandableListAdapter itemAdapter = parent.getExpandableListAdapter();
String selectedItem = (String)itemAdapter.getChild(groupPosition, childPosition);
groupHeader(selectedItem);
if(parent.isGroupExpanded(groupPosition)){
parent.collapseGroup(groupPosition);
}
return true;
}
});
An ExpandableListView depends on an adapter to obtain its values. Those values come from some sort of data structure, often an ArrayList or even a simple array. In your onChildClick(), pass a reference to the data structure used to build your ExpandableListAdapter and modify the data structure directly, followed by a call to notifyDataSetChanged().
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)
{
ExpandableListAdapter itemAdapter = parent.getExpandableListAdapter();
String selectedItem = (String)itemAdapter.getChild(groupPosition, childPosition);
groupHeader(selectedItem);
if(parent.isGroupExpanded(groupPosition))
{
parent.collapseGroup(groupPosition);
}
// your logic here
// expandableListArrayList.add() or expandableListArrayList.remove()
// or whatever
itemAdapter.notifyDataSetChanged();
return true;
}
});
You probably have to extend the adapter to create the functionality you need. Your question is a bit nebulous because I can't see the overall structure of your code, but this should give you a running start.
I have an ExpandableListView view and I've implemented OnChildClickListener, but I need to get the group of that child, more specifically - the text staying as a label of that group.
How can I do that?
Should I implement OnGroupClickListener?
Can somebody show me how to use getPackedPositionGroup() or any of the getPacked<somethingf>() methods to get to the text on the group element of expandable list view?
[Edit - addition]
the called is in Map class, which is something like this:
public class MapCommand extends Activity implements OnChildClickListener {
.....
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
firstStepSwitcher(v, childPosition);
///HERE IS WHERE I WANT TO FIND THE GROUP!!!
return true;
}
}
The view itself is in the layout XML. I do not manage its display manually.
And it has separate class for adapter.
What I did wrong was that I used to take the adapter for that ExpandableListView like this:
in (public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id))
parent.getAdapter();
But after looking into detail in the specification I found that I should take it like this:
ExpandableListAdapter mAdapter = parent.getExandableListAdapter();
from there on I do not have problem to get my group by calling:
String groupName = (String) mAdapter.getGroup(groupPosition);