I'm developing Expandablelistview in Android.
In the GroupView has only a title and every group has different ChildView.
This code is working fine and i'm able to see different ChildView's in every Group item.
In ChildView i have an EditText and when i click on done button i want to get all EditText and Spinner values which are inputs by user.
When i click on done button at that time, i want to get details which is filled by user in Group items Customer Location etc.
For a example : the image shown in question. I want to get the input details which is filled by user in vehicle and TEST group item.
Please, I need help, i want to get values which is filled by user in every group item child's EditText.
Here is my code :
MainActivity.java
public class MainActivity extends Activity {
Context mContext;
private ExpandableListView mExpandableListView;
CustomAdapter mCustomAdapter;
ArrayList<String> newCalibration = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContext = MainActivity.this;
newCalibration.add("CUSTOMER");
newCalibration.add("LOCATION");
newCalibration.add("VEHICLE");
newCalibration.add("TEST");
newCalibration.add("ABC");
/* genarate data for list view */
// genarateData();
/* instantiate adapter with our item list */
mCustomAdapter = new CustomAdapter(mContext, newCalibration);
/* we get list view */
mExpandableListView = (ExpandableListView) findViewById(R.id.explist_tools);
/* set adapter to list view */
mExpandableListView.setAdapter(mCustomAdapter);
mExpandableListView
.setOnGroupExpandListener(new OnGroupExpandListener() {
int previousGroup = -1;
#Override
public void onGroupExpand(int groupPosition) {
// TODO Auto-generated method stub
if (groupPosition != previousGroup) {
mExpandableListView.collapseGroup(previousGroup);
previousGroup = groupPosition;
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
CustomAdapter.java
public class CustomAdapter extends BaseExpandableListAdapter {
private LayoutInflater layoutInflater;
/* list of parent */
private ArrayList<String> mParents;
public CustomAdapter(Context context, ArrayList<String> parents) {
super();
this.mParents = parents;
layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public Object getChild(int parentPosition, int childPosition) {
return null;
}
#Override
public long getChildId(int parentPosition, int childPosition) {
// TODO Auto-generated method stub
return childPosition;
}
#Override
public View getChildView(int parentPosition, int childPosition, boolean b,
View convertView, ViewGroup viewGroup) {
if (convertView == null) {
convertView = layoutInflater
.inflate(R.layout.list_item_child, null);
}
EditText mEdTxt_1 = (EditText) convertView.findViewById(R.id.edtxt_1);
EditText mEdTxt_2 = (EditText) convertView.findViewById(R.id.edtxt_2);
EditText mEdTxt_3 = (EditText) convertView.findViewById(R.id.edtxt_3);
EditText mEdTxt_4 = (EditText) convertView.findViewById(R.id.edtxt_4);
EditText mEdTxt_5 = (EditText) convertView.findViewById(R.id.edtxt_5);
RelativeLayout relativeLayout = (RelativeLayout) convertView
.findViewById(R.id.relativeLayout);
mEdTxt_1.setVisibility(View.VISIBLE);
mEdTxt_2.setVisibility(View.VISIBLE);
mEdTxt_3.setVisibility(View.VISIBLE);
mEdTxt_4.setVisibility(View.VISIBLE);
mEdTxt_5.setVisibility(View.VISIBLE);
relativeLayout.setVisibility(View.VISIBLE);
if (mParents.get(parentPosition).equals("CUSTOMER")) {
mEdTxt_4.setVisibility(View.GONE);
mEdTxt_5.setVisibility(View.GONE);
relativeLayout.setVisibility(View.GONE);
} else if (mParents.get(parentPosition).equals("LOCATION")) {
mEdTxt_4.setVisibility(View.GONE);
mEdTxt_5.setVisibility(View.GONE);
relativeLayout.setVisibility(View.GONE);
} else if (mParents.get(parentPosition).equals("VEHICLE")) {
relativeLayout.setVisibility(View.GONE);
} else if (mParents.get(parentPosition).equals("TAXIMETER/BCT")) {
mEdTxt_3.setVisibility(View.GONE);
mEdTxt_4.setVisibility(View.GONE);
mEdTxt_5.setVisibility(View.GONE);
} else if (mParents.get(parentPosition).equals("TIRE SPECS")) {
mEdTxt_4.setVisibility(View.GONE);
mEdTxt_5.setVisibility(View.GONE);
relativeLayout.setVisibility(View.GONE);
}
return convertView;
}
#Override
public int getChildrenCount(int parentPosition) {
return 1;
}
#Override
public Object getGroup(int parentPosition) {
// TODO Auto-generated method stub
return mParents.get(parentPosition);
}
#Override
public int getGroupCount() {
// TODO Auto-generated method stub
return mParents.size();
}
#Override
public long getGroupId(int parentPosition) {
// TODO Auto-generated method stub
return parentPosition;
}
#Override
public View getGroupView(int parentPosition, boolean isExpanded,
View convertView, ViewGroup viewGroup) {
TextView groupName = null;
String parent = (String) getGroup(parentPosition);
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.list_item_parent,
null);
}
groupName = (TextView) convertView.findViewById(R.id.txt_parentname);
groupName.setText(parent);
return convertView;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public boolean isChildSelectable(int i, int i1) {
return true;
}
}
list_item_child.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item_child"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/edtxt_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:inputType="text" />
<EditText
android:id="#+id/edtxt_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:inputType="text" />
<EditText
android:id="#+id/edtxt_3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:inputType="text" />
<EditText
android:id="#+id/edtxt_4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:inputType="text" />
<EditText
android:id="#+id/edtxt_5"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:inputType="text" />
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<RadioGroup
android:id="#+id/radio_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Radio 1" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Radio 2" />
</RadioGroup>
<TextView
android:id="#+id/txt_childname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/radio_group"
android:text="TaxiMeter ?"
android:textAppearance="?android:attr/textAppearanceSmall" />
<Switch
android:id="#+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#+id/radio_group"
android:text="Switch" />
</RelativeLayout>
</LinearLayout>
Images :
Thanks!
You aren't going to be able to go through the list and get the values from the views directly, which is probably what you were planning on doing.
Instead, just keep track of the values as the user enters them. You can keep a hash map of field name -> value in your adapter or activity. Every time the user changes a value in a field, update that field with the new value in the hashmap. When they press done, you can iterate over the map to get a list of all the fields the user changed and the values they changed them to.
To get the values of the fields as the user changes them, use a TextWatcher:
myEditText.addTextChangedListener(new TextWatcher() {
...
#Override
onTextChanged(CharSequence newText, int start, int before, int count) {
myMapOfFieldsToValues.set(myFieldName, newText);
}
}
You can add that to getChildView in your adapter. You can derive myFieldName from the position of the parent and child.
Related
I'm trying to make a custom listview with multiple values, which have buttons for sorting. This way the listview can be sorted for different values, like year, name and price etc.
I'm still pretty new to Android Studio and coding in general, so if anything is just plain off, then i apologize!
Problem is, nothing is sorted when i press any of the buttons. I tried using a comparable, for sorting in ascending order numerically, but that doesn't seem to work (not getting any errors, just nothing happens).
Here is what i've tried, showing my custom rows first, and then custom list adapter:
My Custom Row Layout:
<TextView
android:layout_width="40dp"
android:layout_height="35dp"
android:layout_marginLeft="10dp"
android:text="Time:"
android:id="#+id/time_label_row"
android:gravity="center"
android:layout_weight="1"/>
<TextView
android:layout_width="40dp"
android:layout_height="35dp"
android:text="time"
android:id="#+id/time_row"
android:gravity="center"
android:layout_weight="1"/>
<TextView
android:layout_width="40dp"
android:layout_height="35dp"
android:layout_marginLeft="10dp"
android:text="Price:"
android:id="#+id/price_label_row"
android:gravity="center"
android:layout_weight="1"/>
<TextView
android:layout_width="40dp"
android:layout_height="35dp"
android:text="price"
android:id="#+id/price_row"
android:gravity="center"
android:layout_weight="1"/>
<TextView
android:layout_width="40dp"
android:layout_height="35dp"
android:layout_marginLeft="10dp"
android:text="Year:"
android:id="#+id/year_label_row"
android:gravity="center"
android:layout_weight="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="35dp"
android:text="year"
android:id="#+id/year_row"
android:gravity="center"
android:layout_weight="1"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/colorPrimaryDark"
/>
My Custom Listview (only the buttons insteresting here):
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp">
<Button
android:text="Time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sort_time"
android:layout_weight="1"
android:onClick="TimeSortClick"/>
<Button
android:text="Price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sort_price"
android:layout_weight="1"
android:onClick="PriceSortClick"/>
<Button
android:text="Year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sort_year"
android:layout_weight="1"
android:onClick="YearSortClick"/>
</LinearLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/list_view"
android:smoothScrollbar="true"/>
My Custom Adapter:
public class CustomAdapter extends BaseAdapter {
String [] result1;
String [] result2;
String [] result3;
Context context;
private static LayoutInflater inflater=null;
public CustomAdapter(ListViewActivity mainActivity, String[] priceOrderList, String [] timeOrderList, String [] yearOrderList) {
// TODO Auto-generated constructor stub
result1=priceOrderList;
result2=timeOrderList;
result3=yearOrderList;
context=mainActivity;
inflater = ( LayoutInflater )context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return result1.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public class Holder
{
TextView tv;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Holder holder=new Holder();
View rowView;
rowView = inflater.inflate(R.layout.row_layout, null);
holder.tv=(TextView) rowView.findViewById(R.id.price_row);
holder.tv.setText(result1[position]);
holder.tv=(TextView) rowView.findViewById(R.id.time_row);
holder.tv.setText(result2[position]);
holder.tv=(TextView) rowView.findViewById(R.id.year_row);
holder.tv.setText(result3[position]);
rowView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "You Clicked "+result1[position], Toast.LENGTH_LONG).show();
}
});
return rowView;
}
My ListView Activitiy(or activity where i inflate my custom listview):
public class ListViewActivity extends Activity implements View.OnClickListener {
ListView view_list;
Context context;
ArrayList priceOrder;
public static String [] priceOrderList={"50$","100$","120$","40$"};
public static String [] timeOrderList={"10min","12min","5min","4min"};
public static String [] yearOrderList={"2010","2011","2012","2004"};
private Button mTimeButton;
private Button mPriceButton;
private Button mYearButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
context=this;
mTimeButton = (Button) findViewById(R.id.sort_time);
mPriceButton = (Button) findViewById(R.id.sort_price);
mYearButton = (Button) findViewById(R.id.sort_year);
view_list = (ListView) findViewById(R.id.list_view);
view_list.setAdapter(new CustomAdapter(this, priceOrderList, timeOrderList, yearOrderList));
mTimeButton.setOnClickListener(this);
mPriceButton.setOnClickListener(this);
mYearButton.setOnClickListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onClick(View v) {
if (v == mPriceButton){
String pricesort = ("Sorting for Price");
Toast.makeText(ListViewActivity.this, pricesort, Toast.LENGTH_SHORT).show();
Comparator<String> StringAscComparator = new Comparator<String>() {
public int compare(String app1, String app2) {
String stringName1 = app1;
String stringName2 = app2;
return stringName1.compareToIgnoreCase(stringName2);
}
};
Collections.sort(Arrays.asList(priceOrderList), StringAscComparator);
} else if (v == mTimeButton){
String timesort = ("Sorting for Time");
Toast.makeText(ListViewActivity.this, timesort, Toast.LENGTH_SHORT).show();
Comparator<String> StringAscComparator = new Comparator<String>() {
public int compare(String app1, String app2) {
String stringName1 = app1;
String stringName2 = app2;
return stringName1.compareToIgnoreCase(stringName2);
}
};
Collections.sort(Arrays.asList(timeOrderList), StringAscComparator);
} else if (v == mYearButton){
String yearsort = ("Sorting for Year");
Toast.makeText(ListViewActivity.this, yearsort, Toast.LENGTH_SHORT).show();
Comparator<String> StringAscComparator = new Comparator<String>() {
public int compare(String app1, String app2) {
String stringName1 = app1;
String stringName2 = app2;
return stringName1.compareToIgnoreCase(stringName2);
}
};
Collections.sort(Arrays.asList(yearOrderList), StringAscComparator);
}
}
Anyways, thanks for the help! It's much appreciated!
In his comment, #Selvin suggests using a POJO to associate your data, and that's a great idea. It's best to find appropriate data types for your data:
public class Item {
public BigDecimal price; // why BigDecimal? http://stackoverflow.com/a/8148773/4504191
public Duration time; // this is from the new java.time API in v8
public int year; // java.time also has a Year class
}
A proper class would have private fields with setters and getters (left as an exercise for the reader).
Now you just have a List<Item> in your adapter.
These data types will also make your comparison logic a little easier.
There's so many different ways you could do this. I think what I would do is create a method on the adapter to sort the list, specifying a comparator:
public void sortUsing(Comparator<Item> comparator) {
Collections.sort(list, comparator);
notifyDataSetChanged();
}
Then I would create three different comparators — one for each field — and pass the appropriate comparator when the corresponding sort button is pressed. Here's the time version:
Comparator<Item> timeComparator = new Comparator<Item> {
#Override
int compare(Item lhs, Item rhs) {
return lhs.time.compareTo(rhs.time);
}
}
Write a method to sort your array. Add one more parameter to your adapter constructor .onClick of btn assign the adapter again like
view_list.setAdapter(new CustomAdapter(this, priceOrderList, sortArray(timeOrderList), yearOrderList,2));
based on the the new param assign the values into listview from adapter.
ps: sorry for writing comment this here , low rep :)
i have two spinners, say categories and subcategories. OnItemSelected of categories spinner i need to set the adapter for sub_categories spinner.I am able to set spinner for categories. But sub_categories spinner is creating trouble.
These arraylist are coming from servers, i made it static.
Looking into my code will give you proper idea that where i am mistaken.
This is my categories List:
public static ArrayList<String> categories=new ArrayList<String>();
public static ArrayAdapter<String> mArryAdtSpnnr;
and in the response.success, i am trying to do the following:
for(int i=0;i<mArray.length;i++){categories.add(mArray[i].getName());}
Here in this activity, where i need 2 spinners:
private void initializeWidgets() {
mspinner_categories=(Spinner)findViewById(R.id.spinner_categories);
mspinner_categories.setOnItemSelectedListener(this);
mspinner_subcategories=(Spinner)findViewById(R.id.spinner_subcategories);
ProfessionalListActivity.mArryAdtSpnnr = new ArrayAdapter<String>( EditProfileActivity.this,
android.R.layout.simple_spinner_item,ProfessionalListActivity.categories);
mspinner_categories.setAdapter(ProfessionalListActivity.mArryAdtSpnnr);
}
and on its item selected:
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String item = parent.getItemAtPosition(position).toString();
Toast.makeText(EditProfileActivity.this,"Selected Item is: "+item,Toast.LENGTH_LONG).show();
// mspinner_subcategories.setSelection(position);
SubListProActivity.mArrySpnnr=new ArrayAdapter<String>
(EditProfileActivity.this,android.R.layout.simple_spinner_item,
SubListProActivity.subcategories);
mspinner_subcategories.setAdapter(SubListProActivity.mArrySpnnr);
}
I am setting second spinner adapter on click of first spinner. But nothing is displayed on this spinner. I did similar code to the other activity.
I am confused, this may be because in ProfessionalListActivity i am getting a category_id also, so that corresponding sublist gets opened. But in spinners i am adding it directly.
Edit:
Sublist class:
public static ArrayList<String> subcategories=new ArrayList<String>();
public static ArrayAdapter<String> mArrySpnnr;
in its response.success
for(int i=0;i<mArray.length;i++){
subcategories.add(mArray[i].getName());
}
Please help
This code approaches your problem as an ExpandableList and is from a working app. First is the listener for a button that calls the activity which:
displays a list of clickable first level options, which, when activated,
display drop down lists of clickable second-level options, when activated
display groups of 3 option radio buttons (only 1 selected button per radio group)
The original application is an (agri) inspection system - the user selects from groups of problems (1st level: insects, funghi, weeds), which problems are occuring (2nd level: insects[army worms, ladybugs, ants], funghi[stem rot, rust, mildew], weeds[common grass, african grass, morning glory]).
For each selected 2nd level option a radio button group to select the severity of problem pops up and the user must choose levels 1 (default), 2 OR 3.
Data is stored to be consumed elsewhere.
Calling the activity which displays a layout dedicated to INSPECTION, sending along the data that will populate the expandable lists.
private final OnClickListener btnDoneOnClick = new OnClickListener() {
public void onClick(View v) {
String input = areaName.getText().toString();
// english version
//String[] groupName = {"INSECTS", "WEEDS", "FUNGHI", "CLIMATE", "VARIOUS"};
String[] groupName = {"INSETOS", "ERVAS INVASORAS", "FUNGOS", "CLIMA", "VARIOS"};
String[][] childName = { { "Cigarrinha","Falsa medideira","Lagarta cartucho","Lagarta rosca","Percevejo (geral)"},
{ "Argentino","Buva","Capim colchao","Carrapicho","Corda viola","Falso Argentino","Leiteiro","Picao","Tiguera Milho","Tiguera Soja"},
{ "Antracnose","Cercospora","DFC","Ferrugem"},
{ "Erosao","Geada","Granizo","Incendio","Inundacao","Raio","Seca","Vento" },
{ "Furto","Fuga","Picada cobra" }
};
Intent intent00 = new Intent(getApplicationContext(), com.xxx.yyy.zzz.AgrInspectActivity.class);
intent00.putExtra("groupName", groupName);
int maxLength = 0;
for (int i=0;i<groupName.length;i++) {
intent00.putExtra(groupName[i], childName[i]);
maxLength = Math.max(childName[i].length, maxLength);
}
intent00.putExtra("arrayLength", maxLength);
// count childrenRows and put values in ARRAY
// to be used by CustomList to inflate layouts
// with proper number of lines
int[] countChild = new int[groupName.length];
for (int j=0;j<groupName.length;j++) {
countChild[j] = childName[j].length;
}
intent00.putExtra("countChild", countChild);
startActivity(intent00);
}
};
The activity proper:
public class AgrInspectActivity extends Activity {
ExpandableListAdapter mAdapter;
LayoutInflater mInflater;
int arrayLength;
String[] groups;
String[][] children;
int[][] array_output_data;
String[][] array_output_data_quantity;
int[] countChild;
public int[][] getArray_output_data() {
return array_output_data;
}
public String[][] getArray_output_data_quantity() {
return array_output_data_quantity;
}
int choice = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inspection);
ExpandableListView list = (ExpandableListView) findViewById(R.id.expandableListView1);
Bundle extras = getIntent().getExtras();
if(extras !=null) {
groups = extras.getStringArray("groupName");
arrayLength = extras.getInt("arrayLength");
countChild = extras.getIntArray("countChild");
String[] tempArray = new String[arrayLength];
children = new String[groups.length][arrayLength];
for (int i=0;i<groups.length;i++) {
children[i] = extras.getStringArray(groups[i]);
// TODO delete this block debug ONLY
Log.i("data", groups[i]+groups.length+" get array loop "+i+" / "+ tempArray.length+"/ countChild: "+countChild[i]);
for (int j=0;j<children[i].length;j++) {
Log.d("data", j+" counter:temparray "+children[i][j]);
}
}
}
mAdapter = new InspectionMenu(this);
list.setAdapter(mAdapter);
}
public class InspectionMenu extends BaseExpandableListAdapter {
private Context myContext;
public InspectionMenu(Context context) {
myContext = context;
Log.i("data", "InspectionActivity InspectionMenu children length "+groups.length);
array_output_data = new int[groups.length][arrayLength];
array_output_data_quantity = new String[groups.length][arrayLength];
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
#Override
public View getChildView(final int groupPosition,final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.inspection_row, null);
TextView childtext = (TextView) convertView.findViewById(R.id.textView1);
childtext.setText(children[groupPosition][childPosition]);
final RadioGroup rdg = (RadioGroup) convertView.findViewById(R.id.radioGroup1);
final RadioButton r1 = (RadioButton) convertView.findViewById(R.id.radio1);
final RadioButton r2 = (RadioButton) convertView.findViewById(R.id.radio2);
final RadioButton r3 = (RadioButton) convertView.findViewById(R.id.radio3);
final EditText inspectQuantity = (EditText) convertView.findViewById(R.id.inspection_quant);
if (array_output_data[groupPosition][childPosition] >0) {
//switch (Integer.parseInt(array_output_data[groupPosition][childPosition])) {
switch (array_output_data[groupPosition][childPosition]) {
case 1:
r1.setChecked(true);
break;
case 2:
r2.setChecked(true);
break;
case 3:
r3.setChecked(true);
break;
}
}
CheckBox cb = (CheckBox) convertView.findViewById(R.id.checkBox1);
if (array_output_data[groupPosition][childPosition] > 0) {
cb.setChecked(true);
rdg.setVisibility(View.VISIBLE);
inspectQuantity.setVisibility(View.VISIBLE);
}
rdg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.radio1) {
choice = 1;
} else if (checkedId == R.id.radio2) {
choice = 2;
} else if (checkedId == R.id.radio3) {
choice = 3;
} else {
Log.e("TGTG", "radio button selection invalid in InspectionActivityOld");
}
array_output_data[groupPosition][childPosition] = (choice);
}
});
cb.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked == true) { // display LEVEL (1,2,3) RADIO BUTTONS for this line
rdg.setVisibility(View.VISIBLE); // redundant?
try {
inspectQuantity.setVisibility(View.VISIBLE);
} catch (Exception except) {
Log.e("TGTG", "no open inspectQUantity "+except.getMessage()+" group "+groupPosition+" child "+childPosition);
}
r1.setChecked(true);
} else { // hide LEVEL RADIO BUTTONS for this line
rdg.setVisibility(View.GONE);
inspectQuantity.setVisibility(View.GONE);
rdg.clearCheck();
array_output_data[groupPosition][childPosition] = 0;
array_output_data_quantity[groupPosition][childPosition] = "";
}
}
});
if (array_output_data_quantity[groupPosition][childPosition] != null) {
inspectQuantity.setText(array_output_data_quantity[groupPosition][childPosition]);
}
try {
inspectQuantity.addTextChangedListener(new TextWatcher(){
#Override
public void afterTextChanged(Editable arg0) {
array_output_data_quantity[groupPosition][childPosition] = arg0.toString();
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {}
});
} catch (Exception except) {
Log.e("TGTG", "did not add listener QUANTITY in inspection");
}
return convertView;
}
#Override
public int getChildrenCount(int groupPosition) {
return countChild[groupPosition];
}
#Override
public Object getGroup(int groupPosition) {
return null;
}
#Override
public int getGroupCount() {
return groups.length;
}
#Override
public long getGroupId(int groupPosition) {
return 0;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.group, null);
TextView grouptext = (TextView) convertView.findViewById(R.id.textView2);
grouptext.setText(groups[groupPosition]);
return convertView;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
}
These are the layout files:
group.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/textView2"
android:layout_width="fill_parent"
android:layout_height="64px"
android:text="TextView" android:textSize="40px" android:paddingLeft="100px" android:paddingTop="10px"/>
</LinearLayout>
inspection_row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:id="#+id/ln">
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center_vertical"/>
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="weeds"
android:textSize="20dip"
android:paddingLeft="20px"
android:gravity="center_vertical"/>
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-30px"
>
<RadioGroup
android:id="#+id/radioGroup1"
android:layout_width="wrap_content"
android:orientation="horizontal" android:visibility="gone" android:layout_height="wrap_content" android:layout_marginLeft="72px" android:layout_marginBottom="-10px">
<RadioButton
android:id="#+id/radio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false" android:visibility="visible" android:text="1"/>
<RadioButton
android:id="#+id/radio2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:checked="false" android:visibility="visible" android:text="2"/>
<RadioButton
android:id="#+id/radio3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:checked="false" android:visibility="visible" android:text="3"/>
</RadioGroup>
<EditText
android:id="#+id/inspection_quant"
android:visibility="gone"
android:layout_width="100px"
android:layout_height="wrap_content"
android:inputType="number"
android:layout_marginLeft="30px"
android:layout_marginBottom="-10px"/>
</LinearLayout>
</LinearLayout>
This should get your ball rolling in the correct direction.
I have an ExpandableListView with a checkbox next to group name and when expanded, child items with checkbox as well.
Let's suppose I have 4 groups with 50 childs. When a group is expanded, and I click on select all checkbox, everything works fine, all checkbox are selected and keep their state if I scroll.
But if I scroll untill the last child of the list, scrolling gets buggy after that ( scrolling to the top and then touching the screen to stop the scrolling doesn't work anymore), clicking on group doesn't work anymore too, untill I click on selectall checkbox again.
Clicking on a child checkbox does nothing, I must click on selectall checkbox for everything to work.
I changed Focusable state of the child checkbox, group checkbox and tried many ways, but I can not find a solution to this. Do you have an idea of where it is coming from?
public class ExpandableListAdapter extends BaseExpandableListAdapter {
LayoutInflater cinflater;
LayoutInflater ginflater;
ArrayList<Group> array;
Context context;
public ExpandableListAdapter(Context context, ArrayList<Group> array) {
super();
cinflater = LayoutInflater.from(context);
ginflater = LayoutInflater.from(context);
this.array = array;
this.context = context;
}
public class ChildViewHolder {
CheckBox contactcheckbox;
TextView name;
}
#Override
public int getChildrenCount(int groupPosition) {
// TODO Auto-generated method stub
return array.get(groupPosition).getContacts().size();
}
private OnCheckedChangeListener contactchecklistener = new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton checkboxView, boolean isChecked) {
Contact contact = (Contact) checkboxView.getTag();
contact.setCheck(isChecked);
}
};
#Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
ChildViewHolder cholder;
if(convertView == null){
cholder = new ChildViewHolder();
convertView = cinflater.inflate(R.layout.childsitems, null);
cholder.name = (TextView) convertView.findViewById(R.id.childnametextview);
cholder.contactcheckbox = (CheckBox) convertView.findViewById(R.id.childcheckbox);
cholder.contactcheckbox.setOnCheckedChangeListener(contactchecklistener);
convertView.setTag(cholder);
}else{
cholder = (ChildViewHolder) convertView.getTag();
}
cholder.contactcheckbox.setTag(array.get(groupPosition).getContacts().get(childPosition));
cholder.contactcheckbox.setChecked(array.get(groupPosition).getContacts().get(childPosition).isCheck());
cholder.name.setText(array.get(groupPosition).getContacts().get(childPosition).getName());
return convertView;
}
public class GroupViewHolder {
TextView groupname;
CheckBox groupcheck;
}
#Override
public int getGroupCount() {
// TODO Auto-generated method stub
return array.size();
}
private OnCheckedChangeListener groupchecklistener = new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int index = (Integer) buttonView.getTag();
for(int i = 0;i<array.get(index).getContacts().size();i++){
array.get(index).getContacts().get(i).setCheck(isChecked);
}
array.get(index).setCheck(isChecked);
notifyDataSetChanged();
}
};
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
GroupViewHolder gholder;
if(convertView==null){
gholder = new GroupViewHolder();
convertView = ginflater.inflate(R.layout.groupsitems,null);
gholder.groupname = (TextView)convertView.findViewById(R.id.groupnametextview);
gholder.groupcheckbox = (CheckBox)convertView.findViewById(R.id.groupcheckbox);
gholder.groupcheckbox.setOnCheckedChangeListener(groupchecklistener);
convertView.setTag(gholder);
}else{
gholder = (GroupViewHolder)convertView.getTag();
}
gholder.groupname.setText(array.get(groupPosition).getGroupname());
gholder.groupname.setTextSize(24);
gholder.groupname.setTextColor(Color.parseColor("#FF858585"));
gholder.groupname.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
int paddingleft = 48; // 38 dps
final float scale = getResources().getDisplayMetrics().density;
int dpvalue = (int) (paddingleft * scale + 0.5f);
gholder.groupname.setPadding(dpvalue, 16, 0, 16);
gholder.groupcheckbox.setTag(groupPosition);
gholder.groupcheckbox.setChecked(array.get(groupPosition).isCheck());
if(isExpanded == true){
convertView.setBackgroundDrawable(getResources().getDrawable(R.drawable.expandedbackground));
}else{
convertView.setBackgroundColor(Color.TRANSPARENT);
}
return convertView;
}
#Override
public Object getChild(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return 0;
}
#Override
public Object getGroup(int groupPosition) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getGroupId(int groupPosition) {
// TODO Auto-generated method stub
return 0;
}
#Override
public boolean hasStableIds() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return false;
}
}
groupsitems.xml :
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<CheckBox
android:id="#+id/groupcheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="12dp"
android:focusable="false"
android:gravity="right|center"
android:paddingRight="10dp" />
<TextView
android:id="#+id/groupnametextview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/groupcheckbox"
android:focusableInTouchMode="false"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FF858585"
android:textStyle="bold" />
</RelativeLayout>
childitems.xml :
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:paddingLeft="8dp" >
<TextView
android:id="#+id/childnametextview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/childcheckbox"
android:gravity="right|center"
android:paddingLeft="16dp"
android:textColor="#FFAFAFAF"
android:textSize="16sp"
android:textStyle="bold" />
<CheckBox
android:id="#+id/childcheckbox"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" />
</RelativeLayout>
I've found the solution. Instead of using OnCheckedChangeListener on the groupcheckbox, I used OnClickListener and it solved everything like this :
gholder.groupcheckbox.setChecked(array.get(groupPosition).isCheck());
gholder.groupcheckbox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
for(int i = 0;i<array.get(groupPosition).getContacts().size();i++){
array.get(groupPosition).getContacts().get(i).setCheck(gholder.groupcheckbox.isChecked());
}
array.get(groupPosition).setCheck(gholder.groupcheck.isChecked());
notifyDataSetChanged();
}
});
I have an expandable listview. I have put some dummy data and evrything seems ok but when I run the application all groups are in collapse mode and they don't take effect when I click on each of them. This is the screenshot:
XML of Group is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/bg_slider"
android:orientation="horizontal" >
<TextView
android:id="#+id/tvRecipeName"
style="#style/normal_text.bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="50dp"
android:layout_marginRight="5dp"
android:focusable="false"
android:lines="1"
android:maxLines="1"
android:text="#string/dd_title" />
<ImageButton
android:id="#+id/ibDeleteRecipe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:background="#color/transparent"
android:contentDescription="#string/cd"
android:focusable="false"
android:src="#android:drawable/ic_menu_delete" />
<View
android:layout_width="1dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/tvRecipeName"
android:focusable="false" />
</RelativeLayout>
XML of child is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/White"
android:gravity="left|center_vertical" >
<View
android:layout_width="1dp"
android:layout_height="35dp"
android:layout_toLeftOf="#+id/tvIngredient"
android:focusable="false" />
<TextView
android:id="#+id/tvIngredient"
style="#style/normal_text_black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp"
android:layout_marginRight="5dp"
android:lines="1"
android:maxLines="1"
android:text="#string/dd_title"
android:focusable="false" />
<ImageButton
android:id="#+id/ibDeleteIngredient"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:background="#color/transparent"
android:contentDescription="#string/cd"
android:focusable="false"
android:src="#android:drawable/btn_dialog" />
</RelativeLayout>
and in main.xml, definition of expandable list is:
<ExpandableListView
android:id="#+id/elv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I have an adapter that I have written this code for that:
public class ExpAdapter extends BaseExpandableListAdapter {
private final String TAG = "ExpAdapter";
private Context context;
static final String arrGroupelements[] = {"India", "Australia", "England", "South Africa"};
static final String arrChildelements[][] = { {"Sachin Tendulkar", "Raina", "Dhoni", "Yuvi" },
{"Ponting", "Adam Gilchrist", "Michael Clarke"},
{"Andrew Strauss", "kevin Peterson", "Nasser Hussain"},
{"Graeme Smith", "AB de villiers", "Jacques Kallis"} };
public ExpAdapter(Context context) {
this.context = context;
Log.i(TAG, "Adapter created.");
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.elv_child, null);
}
TextView tvItem = (TextView) convertView.findViewById(R.id.tvIngredient);
ImageButton ibDelete = (ImageButton) convertView.findViewById(R.id.ibDeleteIngredient);
ibDelete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "******");
}
});
tvItem.setText(arrChildelements[groupPosition][childPosition]);
return convertView;
}
#Override
public int getChildrenCount(int groupPosition) {
return arrChildelements[groupPosition].length;
}
#Override
public Object getGroup(int groupPosition) {
return null;
}
#Override
public int getGroupCount() {
return arrGroupelements.length;
}
#Override
public long getGroupId(int groupPosition) {
return 0;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.elv_group, null);
}
TextView tvItem = (TextView) convertView.findViewById(R.id.tvRecipeName);
ImageButton ibDeleteRcipe = (ImageButton) convertView.findViewById(R.id.ibDeleteRecipe);
ibDeleteRcipe.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "%%%%%%");
}
});
tvItem.setText(arrGroupelements[groupPosition]);
return convertView;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
and finally, in code of fragment activity i have:
public class ShoppingList extends FragmentActivity {
ExpAdapter adapter = new ExpAdapter(this);
//Linking expnadable list view
expListView = (ExpandableListView) findViewById(R.id.elv);
expListView.setAdapter(adapter);
expListView.setOnGroupExpandListener(new OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
Log.i(TAG, "Group " + groupPosition + " expanded.");
}
});
expListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {
#Override
public void onGroupCollapse(int groupPosition) {
Log.i(TAG, "Group " + groupPosition + " collapsed.");
}
});
expListView.setOnChildClickListener(new OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Log.i(TAG, "item " + childPosition + " of group " + groupPosition + " clicked.");
return false;
}
});
}
When I run the application and click on parents, nothing happens. I tried to add following lines of code at the end of shopping class:
int count = adapter.getGroupCount();
for (int position = 1; position <= count; position++)
expListView.expandGroup(position - 1);
Now when I run the application result is like this screenshot:
If I click on delete buttons (parent or child), I can see they take effect (as I check logcat), however when I click on child or parent nothing happens. So, I have no idea why callbacks doesn't work. Based on my research I found that I need to set Focussable of image buttons to false. As you can see in XML files I did it but still when I click on parent and child rows I can't see any response.
Finally I found the solution :)
I have no idea is it bug or disease or ...
As mentioned above based on my research I found that we need to set focus-ability of image view/box to "false". I did it in XML file and it didn't work. I set focus-ability to "true" in XML and in code set it to false. like this:
#Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.elv_group, null);
}
TextView tvItem = (TextView) convertView.findViewById(R.id.tvRecipeName);
ImageButton ibDeleteRcipe = (ImageButton) convertView.findViewById(R.id.ibDeleteRecipe);
ibDeleteRcipe.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
...
}
});
ibDeleteRcipe.setFocusable(false);
tvItem.setText(arrGroupElements[groupPosition]);
return convertView;
}
Therefore based of my achievement! it should be set to "false" in code not in XML! Now the question is What is difference? -I have no idea.
It is necessary to define android:focusable="false" in the layout xml for focusable views within the expandable list view item but not in the "ExpandableListView" attribute.
Eg: if a custom parent list item includes a checkbox (it will automatically get the focus) it should be like below.
<CheckBox
android:id="#+id/cbkSelectDownload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"/>
I can't for the life of me figure out why my ExpandableListView doesn't expand... I have used log statements in just about every click listener I can find for the ExpandableListView and it doesnt look like any of them get called.
I know there are many posts on this topic but I have read through them all and tried many things and am having no luck, hopefully I'm missing some tiny error that will be easy to spot for someone else.
Main Activity:
public class ForumListActivity extends Activity {
private static ArrayList<Forum> forumList;
private static ArrayList<ArrayList<SubForum>> subForumList;
private ExpandableListView forumListView;
private ForumListAdapter forumListAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main_page);
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
forumListView = (ExpandableListView) this.findViewById(R.id.main_page_forum_list);
forumList = new ArrayList<Forum>();
subForumList = new ArrayList<ArrayList<SubForum>>();
setUpForums(this);
forumListAdapter = new ForumListAdapter(this, forumList, subForumList);
forumListView.setAdapter(forumListAdapter);
forumListView.setOnGroupExpandListener(new OnGroupExpandListener(){
#Override
public void onGroupExpand(int groupPosition) {
Log.d("onGroupExpand", "this works?");
for(int i=0; i<forumListAdapter.getGroupCount(); i++) {
if(i != groupPosition)
forumListView.collapseGroup(groupPosition);
}
}
});
forumListView.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
Log.d("onGroupClick:", "worked");
parent.expandGroup(groupPosition);
return true;
}
});
}
Note: the method setUpForums() just takes system arrays and puts them into forumList and subForumList
ListViewAdapter:
public class ForumListAdapter extends BaseExpandableListAdapter {
private ArrayList<Forum> groups;
private ArrayList<ArrayList<SubForum>> children;
private Context ctx;
public ForumListAdapter(Context ctx, ArrayList<Forum> groups, ArrayList<ArrayList<SubForum>> children) {
this.ctx = ctx;
this.groups = groups;
this.children = children;
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return children.get(groupPosition).get(childPosition);
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(ctx);
convertView = inflater.inflate(R.layout.forum_list_child_item_row, null);
}
SubForum currentSubForum = children.get(groupPosition).get(childPosition);
TextView name = (TextView)convertView.findViewById(R.id.child_row_forum_title);
TextView desc = (TextView)convertView.findViewById(R.id.child_row_forum_description);
if (name != null)
name.setText(currentSubForum.getName());
if (desc != null)
desc.setText(currentSubForum.getDescription());
convertView.setFocusableInTouchMode(true);
return convertView;
}
#Override
public int getChildrenCount(int groupPosition) {
return children.get(groupPosition).size();
}
#Override
public Object getGroup(int groupPosition) {
return groups.get(groupPosition);
}
#Override
public int getGroupCount() {
return groups.size();
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater inflater = LayoutInflater.from(ctx);
convertView = inflater.inflate(R.layout.forum_list_group_item_row, null);
}
Forum currentForum = (Forum) groups.get(groupPosition);
TextView name = (TextView) convertView.findViewById(R.id.group_item_forum_title);
//ImageView image = (ImageView) convertView.findViewById(R.id.group_item_expander_image);
if(name != null)
name.setText(currentForum.getName());
/*
if(image != null) {
int[][] group_state_sets = {{}, {android.R.attr.state_expanded}};
image.setVisibility(View.VISIBLE);
int stateSetIndex = (isExpanded ? 1 : 0) ;
Drawable drawable = image.getDrawable();
drawable.setState(group_state_sets[stateSetIndex]);
}
*/
return convertView;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
Group Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/turquoise_gradient"
android:orientation="horizontal"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingLeft="6dip" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/turquoise_gradient"
android:orientation="vertical"
android:padding="2dip" >
<TextView
android:id="#+id/group_item_forum_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|left"
android:gravity="left"
android:paddingLeft="5dip"
android:textColor="#color/white"
android:textSize="16dip" />
</LinearLayout>
<!--
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center|right">
<ImageView
android:id="#+id/group_item_expander_image"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/collapse_down" />
</LinearLayout> -->
</LinearLayout>
child layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/turquoise_gradient"
android:orientation="horizontal"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingLeft="6dip" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="2dip"
android:background="#drawable/turquoise_gradient" >
<TextView
android:id="#+id/child_row_forum_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_gravity="center_vertical"
android:paddingLeft="5dip"
android:textColor="#color/white"
android:maxLines="1"
android:textSize="11dip" />
<TextView
android:id="#+id/child_row_forum_description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_gravity="center_vertical"
android:paddingLeft="15dip"
android:textColor="#color/white"
android:maxLines="2"
android:textSize="11dip" />
</LinearLayout>
</LinearLayout>
main page layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/black"
android:orientation="vertical" >
<ExpandableListView
android:id="#+id/main_page_forum_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/black"
android:divider="#color/black"
android:dividerHeight="1dip"
android:clickable="true" />
</LinearLayout>
Any help you can provide is greatly appreciated!
I've also encountered similar problem like you. After a couple of days of investigation, I found that I did something wrong. So I fixed it to work correctly by making small change.
Let's look at the body of boolean onGroupClick(...) in setOnGroupClickListener. You've returned true that means "the click was handled"
You should return false if you want to expand. So I suggest you to do like this :
forumListView.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
Log.d("onGroupClick:", "worked");
parent.expandGroup(groupPosition);
return false;
}
});
in android.widget.ExpandableListView class, there is a method named boolean handleItemClick(View v, int position, long id) which is responsible for expanding/collapsing groups or passing on the click to the proper child.
/* It's a group click, so pass on event */
if (mOnGroupClickListener != null) {
if (mOnGroupClickListener.onGroupClick(this, v,
posMetadata.position.groupPos, id)) {
posMetadata.recycle();
return true;
}
}
/* expanding/collapsing/other tasks... */
if you implement onGroupClick to return true, the the code below 8th line will never be executed. (that means, groups will never be collapsed, expanded)
Hope my answer helped you :-) good luck!
In case you have a widget on your list item, such as a Button, you may have to add android:focusable="false" to it. The Button was not allowing my list item to be clicked. That was the issue in my case.
There are probably three things u need to check,
check if u have any data available for the chid, cos if u dont have any data the child will not appear at all.
2.try removing if condition check while you using layout inflaters
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(ctx);
convertView = inflater.inflate(R.layout.forum_list_child_item_row, null);
}
you need to also pass Viewgroup here
convertView = inflater.inflate(R.layout.forum_list_child_item_row,parent, false);
I know this was already answered, but try setting the base layout of whatever you're inflating to have the attribute:
android:descendantFocusability="blocksDescendants"
If your expandable listview parent has button or switch it doesn't get called i wasted whole day in this.
So just use below code
android:focusable="false"
android:focusableInTouchMode="false"
Add this code inside toggle button,switch button or any which is on expandable listview
Make sure your custom group layout does not have android:textIsSelectable="false" as "true", if the text in textview is set to selectable, the expandable listview would expand in gingerbread but not in jellybean and might not work in ICS too.
I had a similar problem and it was solved by removing the android:clickable="true" property from ExpandableListView on xml.
When you are working with expandable lists then group expand is default functionality in it . means that group will expand itself only when you click on it you donot need to overrirde onGroupExpand(int groupPosition) or any other method just simply populate your data into your list somthing like this:
public class MyActivity extends Activity {
private ExpandableListView forumListView;
private ForumListAdapter forumListAdapter;
String[] forumList={"group 1","group 2","group 3"};
String[][] subForumList={{"group 1 child1","group 1 child1","group 1 child3"},
{"group 2 child1","group 2 child2","group 2 child3"},
{"group 3 child1","group 3 child2","group 3 child3"},
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
forumListView = (ExpandableListView) this.findViewById(R.id.main_page_forum_list);
forumListAdapter = new ForumListAdapter(this, forumList, subForumList);
forumListView.setAdapter(forumListAdapter);
/* forumListView.setOnGroupExpandListener(new OnGroupExpandListener(){
public void onGroupExpand(int groupPosition) {
Log.d("onGroupExpand", "this shit works?");
for(int i=0; i<forumListAdapter.getGroupCount(); i++) {
if(i != groupPosition)
forumListView.collapseGroup(groupPosition);
}
}
});
forumListView.setOnGroupClickListener(new OnGroupClickListener() {
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
Log.d("onGroupClick:", "worked");
parent.expandGroup(groupPosition);
return true;
}
});*/
}
public class ForumListAdapter extends BaseExpandableListAdapter {
String[] groups;
String[][] children;
private Context ctx;
public ForumListAdapter(Context ctx, String[] groups, String[][] children) {
this.ctx = ctx;
this.groups = groups;
this.children = children;
}
public Object getChild(int arg0, int arg1) {
// TODO Auto-generated method stub
return children[arg0][arg1];
}
public long getChildId(int arg0, int arg1) {
// TODO Auto-generated method stub
return arg1;
}
public View getChildView(int arg0, int arg1, boolean arg2, View arg3,
ViewGroup arg4) {
if (arg3 == null) {
LayoutInflater inflater = LayoutInflater.from(ctx);
arg3 = inflater.inflate(R.layout.child, null);
}
String childData = children[arg0][arg1];
TextView name = (TextView)arg3.findViewById(R.id.child_row_forum_title);
TextView desc = (TextView)arg3.findViewById(R.id.child_row_forum_description);
if (name != null)
name.setText(childData);
if (desc != null)
// desc.setText(currentSubForum.getDescription());
arg3.setFocusableInTouchMode(true);
return arg3;}
public int getChildrenCount(int arg0) {
// TODO Auto-generated method stub
return children[arg0].length;
}
public Object getGroup(int arg0) {
// TODO Auto-generated method stub
return groups[arg0];
}
public int getGroupCount() {
// TODO Auto-generated method stub
return groups.length;
}
public long getGroupId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
public View getGroupView(int arg0, boolean arg1, View arg2, ViewGroup arg3) {
if (arg2 == null)
{
LayoutInflater inflater = LayoutInflater.from(ctx);
arg2 = inflater.inflate(R.layout.group, null);
}
TextView name = (TextView) arg2.findViewById(R.id.group_item_forum_title);
//ImageView image = (ImageView) arg2.findViewById(R.id.group_item_expander_image);
if(name != null)
name.setText(groups[arg0]);
/*
if(image != null) {
int[][] group_state_sets = {{}, {android.R.attr.state_expanded}};
image.setVisibility(View.VISIBLE);
int stateSetIndex = (isExpanded ? 1 : 0) ;
Drawable drawable = image.getDrawable();
drawable.setState(group_state_sets[stateSetIndex]);
}
*/
return arg2;}
public boolean hasStableIds() {
// TODO Auto-generated method stub
return false;
}
public boolean isChildSelectable(int arg0, int arg1) {
// TODO Auto-generated method stub
return false;
}
}
}
forumListView.collapseGroup(groupPosition);
should be
forumListView.collapseGroup(i);
Add implements OnGroupExpandListener to your Activity. Then It will works. I am Using same it works fine.
In my case I had buttons in group and child views and even setting android:focusable="false"
android:focusableInTouchMode="false" on both it didn't work.
So I had to change them from ImageButton to ImageView. The listeners for the clicks are the same. You might need to create a custom background to give the touch animation for the ImageView.