Unable to set spinner adapter on onItemSelected of first spinner - android

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.

Related

(android studio) Deleting listview items with checkboxes

I have spent at least a couple of hours looking at all the code online when this question is googled, yet still don't really understand how to implement this.
I have a listview populated by the database with a cursor adapter.
Every listview item has a checkbox next to it.
I want to delete all the listview items from the listview that have their checkbox selected.
What code do i need in my delete button to implement this?
Thanks and kind regards.
Before anyone mentions this has been asked before; every single question has their own implementation and code in the question, i haven't been able to find a step-by-step tutorial.
My Solution:
Here is my adapter:
public class TextCheckBoxAdapter extends ArrayAdapter {
private List<String> names;
private List<Boolean> checked;
public TextCheckBoxAdapter(Context context, List<String> names) {
super(context, R.layout.custom_row_text_checkbox, names);
this.names = names;
checked = new ArrayList<>();
for(String name : names) checked.add(false);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.custom_row_text_checkbox, parent, false);
TextView tv = (TextView) customView.findViewById(R.id.nameTv);
tv.setText(names.get(position));
final CheckBox checkBox = (CheckBox) customView.findViewById(R.id.checkbox);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checked.set(position, checkBox.isChecked());
}
});
return customView;
}
public String getName(int position){
return names.get(position);
}
public List<Boolean> getCheckList(){
return checked;
}
/**Anzahl selektierter Checkboxen*/
public int getCountSelectedCheckBoxes(){
int toReturn = 0;
for(boolean b : checked) if(b) toReturn++;
return toReturn;
}
public void delete(int i){
names.remove(i);
checked.remove(i);
notifyDataSetChanged();
}
public boolean isEmpty(){
return names.isEmpty();
}
}
layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginLeft="#dimen/custom_margin_left_and_right"
android:layout_marginStart="#dimen/custom_margin_left_and_right"
android:layout_marginRight="#dimen/custom_margin_left_and_right"
android:layout_marginEnd="#dimen/custom_margin_left_and_right">
<TextView
android:id="#+id/nameTv"
android:layout_weight="0.9"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="#string/unbenannt"
android:textColor="#color/grey"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
/>
<CheckBox
android:id="#+id/checkbox"
android:layout_weight="0.1"
android:layout_gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:focusable="false"
android:focusableInTouchMode="false"/>
</LinearLayout>
//Delete via icon in toolbar
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home){
onBackPressed();
}else if(id == R.id.action_loeschen){
if(adapter.getCountSelectedCheckBoxes() > 0){
List<Boolean> checked = adapter.getCheckList();
for(int i = checked.size() - 1; i >= 0; i--){ //Rueckwaerts ausfuehren!
if(checked.get(i)){
String name = adapter.getName(i);
//Loesche aus der Liste
adapter.delete(i);
//TODO: Delete from DB or whatever
//Checken ob Liste leer
checkIsListEmpty();
}
}
}else{
MyToast.showShort(this, getString(R.string.hinweis_keine_selektion));
}
}
return super.onOptionsItemSelected(item);
}

Remove items from a Custom ListView (Android)

How do I create a neverending listview of list items with checkboxes that can be removed with a delete item button? The answer is below.
In order to create a neverending listview the first thing you need to have is a set of two runnables. These threads will update the array of data in your adapter.
final int itemsPerPage = 100;
ArrayList<HashMap<String,String>> listItems = new ArrayList<HashMap<String,String>>();
boolean loadingMore = false;
int item = 0;
//Since we cant update our UI from a thread this Runnable takes care of that!
public Runnable returnRes = new Runnable() {
#Override
public void run() {
//Loop thru the new items and add them to the adapter
if(groceries.getGroceries().size() > 0){
for(int i=0;i < listItems.size();i++) {
HashMap<String,String> grocery = listItems.get(i);
adapter.add(grocery);
}
//Update the Application title
setTitle("Grocery List with " + String.valueOf(groceries.getGroceries().size()) + " items");
//Tell to the adapter that changes have been made, this will cause the list to refresh
adapter.notifyDataSetChanged();
//Done loading more.
loadingMore = false;
}
}
};
//Runnable to load the items
public Runnable loadMoreListItems = new Runnable() {
#Override
public void run() {
//Set flag so we cant load new items 2 at the same time
loadingMore = true;
//Reset the array that holds the new items
listItems = new ArrayList<HashMap<String,String>>();
//Get 8 new listitems
for (int i = 0; i < itemsPerPage; i++) {
if (i < groceries.getGroceries().size()) {
listItems.add(groceries.getGroceries().get(i));
item++;
}
}
//Done! now continue on the UI thread
runOnUiThread(returnRes);
}
};
Then your onCreate() method should look something like this with an array passed to your adapter:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_grocery_list);
//add the footer before adding the adapter, else the footer will not load!
View footerView = ((LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.activity_footer_view, null, false);
this.getListView().addFooterView(footerView);
adapter = new ListViewAdapter(this,groceries);
setListAdapter(adapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
//Here is where the magic happens
this.getListView().setOnScrollListener(new OnScrollListener(){
//useless here, skip!
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {}
//dumdumdum
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//what is the bottom iten that is visible
int lastInScreen = firstVisibleItem + visibleItemCount;
//is the bottom item visible & not loading more already ? Load more !
if((lastInScreen == totalItemCount) && !loadingMore && item < groceries.getGroceries().size()){
Thread thread = new Thread(null, loadMoreListItems);
thread.start();
}
}
});
}
You will also need a delete method to remove the items with checkboxes and a checkOff method as well. They look like this:
ArrayList<Integer> checkedBoxes = new ArrayList<Integer>();
ArrayList<HashMap<String,String>> checkedItems = new ArrayList<HashMap<String,String>>();
public void deleteItem(View view) {
if (checkedBoxes.size() > 1 || checkedBoxes.size() == 0) {
Toast.makeText(getApplicationContext(), "You can only delete one item at a time. Sorry :(", Toast.LENGTH_LONG).show();
return;
} else {
checkedItems.add(groceries.getGroceries().get(checkedBoxes.get(0)));
groceries.getGroceries().removeAll(checkedItems);
checkedBoxes.clear();
try {
groceries.serialize();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Intent intent = new Intent(getApplicationContext(),CreateGroceryList.class);
startActivity(intent);
}
}
public void checkOff(View view) {
CheckBox box = (CheckBox)view;
DataModel d = (DataModel)box.getTag();
if(!checkedBoxes.contains(d.index)) {
checkedBoxes.add(d.index);
} else {
checkedBoxes.remove((Integer)d.index);
}
}
In order to communicate with the adapter it is helpful to have a DataModel class that will model our information. My DataModel has an index variable to keep track of the selected item.
public class DataModel {
int index;
HashMap<String,String> data;
boolean selected;
public DataModel(int i) {
index = i;
data = new HashMap<String,String>();
selected = false;
}
public HashMap<String, String> getData() {
return data;
}
public void setData(HashMap<String, String> data) {
this.data = data;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
Finally, here is the code for the BaseAdapter:
public class ListViewAdapter extends BaseAdapter {//To create an adapter we have to extend BaseAdapter instead of Activity, or whatever.
private ListActivity activity;
private View vi;
private ArrayList<DataModel> data;
private static LayoutInflater inflater=null;
public ListViewAdapter(ListActivity a, GroceryList g) {
activity = a;
data = new ArrayList<DataModel>();
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
groceries = g;
}
public void add(HashMap<String,String> a){
DataModel d = new DataModel(data.size());
d.setData(a);
d.setSelected(false);
data.add(d);
}
public ArrayList<DataModel> getData() {
return data;
}
public int getCount() { //get the number of elements in the listview
return data.size();
}
public Object getItem(int position) { //this method returns on Object by position
return position;
}
public long getItemId(int position) { //get item id by position
return position;
}
public View getView() {
return vi;
}
public View getView(int position, View convertView, ViewGroup parent) { //getView method is the method which populates the listview with our personalized rows
vi=convertView;
final ViewHolder holder = new ViewHolder();
if(convertView==null) {
vi = inflater.inflate(R.layout.custom_row_view, null);
//every item in listview uses xml "listview_row"'s design
holder.name = (CheckBox)vi.findViewById(R.id.name);
holder.price = (TextView)vi.findViewById(R.id.price); // You can enter anything you want, buttons, radiobuttons, images, etc.
holder.quantity = (TextView)vi.findViewById(R.id.quantity);
holder.name
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
DataModel element = (DataModel) holder.name
.getTag();
element.setSelected(buttonView.isChecked());
}
});
vi.setTag(holder);
holder.name.setTag(data.get(position));
ViewHolder vholder = (ViewHolder) vi.getTag();
vholder.name.setChecked(data.get(position).isSelected());
HashMap<String, String> hash = new HashMap<String, String>(); //We need a HashMap to store our data for any item
hash = data.get(position).getData();
vholder.name.setText(hash.get("brand") + " " + hash.get("name")); //We personalize our row's items.
vholder.price.setText("$" + hash.get("price"));
vholder.quantity.setText("Quantity: " + hash.get("quantity"));
} else {
vi = convertView;
((ViewHolder) vi.getTag()).name.setTag(data.get(position));
}
if (holder.name == null) {
ViewHolder vholder = (ViewHolder) vi.getTag();
vholder.name.setChecked(data.get(position).isSelected());
HashMap<String, String> hash = new HashMap<String, String>(); //We need a HashMap to store our data for any item
hash = data.get(position).getData();
vholder.name.setText(hash.get("brand") + " " + hash.get("name")); //We personalize our row's items.
vholder.price.setText("$" + hash.get("price"));
vholder.quantity.setText("Quantity: " + hash.get("quantity"));
}
return vi;
}
}
class ViewHolder {
CheckBox name;
TextView price;
TextView quantity;
public CheckBox getName() {
return name;
}
public void setName(CheckBox name) {
this.name = name;
}
public TextView getPrice() {
return price;
}
public void setPrice(TextView price) {
this.price = price;
}
public TextView getQuantity() {
return quantity;
}
public void setQuantity(TextView quantity) {
this.quantity = quantity;
}
}
You also need a few xml files in your layout folder this is what they will look like:
You need a footerview that will tell your list when to load new items:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:gravity="center_horizontal"
android:padding="3dp"
android:layout_height="fill_parent">
<TextView
android:id="#id/android:empty"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center"
android:padding="5dp"
android:text="Add more grocery items..."/>
A custom row view that is populated by your BaseAdapter:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<CheckBox
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox"
android:focusable="false"
android:textSize="25dip"
android:onClick="checkOff"
/>
<TextView
android:id="#+id/quantity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="40dip"
android:text="Lastname"
android:textSize="15dip" />
<TextView
android:id="#+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="40dip"
android:text="Lastname"
android:textSize="15dip" />
</LinearLayout>
And a parent view, mine is called create_grocery_list because I'm writing a grocery list editor: This one must contain a ListView with the proper id.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="400dp" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
</ListView>
</LinearLayout>
<AbsoluteLayout
android:layout_width="match_parent"
android:layout_height="72dp" >
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="105dp"
android:layout_y="0dp"
android:onClick="deleteItem"
android:text="#string/deleteItem" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="8dp"
android:layout_y="0dp"
android:onClick="goToAddItemScreen"
android:text="#string/addItem" />
<Button
android:id="#+id/button3"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="221dp"
android:layout_y="0dp"
android:onClick="scanner"
android:text="#string/scanCode" />
</AbsoluteLayout>
</LinearLayout>
And that's about it... hope this helps anyone. It's the most complete tutorial you'll find.
I learned all this from this tutorial: http://www.vogella.com/articles/AndroidListView/article.html#androidlists_overview then added the two runnables to make a neverending grocery list :) have fun programming...

Android : getChild() EditText values on button click in ExpandableListView

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.

Expandable listview with selectall checkbox : group itemclick and scrolling bug

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();
}
});

android expandablelistview does not expand or receive click events

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.

Categories

Resources