Состояние CheckBox в дочерних элементах ExpandableListView

Я прочитал около 30 страниц из SO, а также учебные пособия по отслеживанию состояний проверки в списках, но информации (особенно рабочей информации) недостаточно для этого в расширяемом ListView.

У меня есть дети, заполненные флажками, но когда я устанавливаю флажок для ребенка из 1 группы, случайные дети в других группах также проверяют. Мне нужно остановить это. Лучшая информация, которую я прочитал, заключалась в том, чтобы установить флажок как отдельный тег, но я не знаю, как установить несколько тегов, когда я попытался, я получил ошибку несоответствия класса, сравнивая флажок с convertview.

Кто-нибудь сталкивался с хорошим способом отслеживать состояния флажков в дочерних элементах расширяемого списка?

Я внес несколько изменений, поэтому добавляю весь код адаптера. Пожалуйста, проверьте первые несколько строк getGroupView и getChildView целиком и помогите мне понять, что я делаю неправильно.

РЕДАКТИРОВАТЬ: сейчас происходит то, что когда я устанавливаю флажок, а затем расширяю другую группу, все отмеченные флажки снимаются:

public class MyExpandableListAdapter extends BaseExpandableListAdapter
    implements OnCheckedChangeListener {

private Context mContext;

private ArrayList<ContactNameItems> mListDataHeader;
private HashMap<String, List<ContactPhoneItems>> mListDataChild;

private boolean[] mGetChecked;
private HashMap<String, boolean[]> mChildCheckStates;

private ArrayList<String> selectedNumbers;

private ChildViewHolder childViewHolder;
private GroupViewHolder groupViewHolder;

private String numberText;

public MyExpandableListAdapter(Context context,
        ArrayList<ContactNameItems> listDataHeader,
        HashMap<String, List<ContactPhoneItems>> listDataChild,
        ArrayList<String> listOfNumbers) {

    mContext = context;
    mListDataHeader = listDataHeader;
    mListDataChild = listDataChild;
    selectedNumbers = listOfNumbers;

    mChildCheckStates = new HashMap<String, boolean[]>();
}

@Override
public int getGroupCount() {
    return mListDataHeader.size();
}

@Override
public ContactNameItems getGroup(int groupPosition) {
    return mListDataHeader.get(groupPosition);
}

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
        View convertView, ViewGroup parent) {

    String contactName = getGroup(groupPosition).getName();
    Bitmap contactImage = getGroup(groupPosition).getImage();

    mGetChecked = new boolean[getChildrenCount(groupPosition)];
    mChildCheckStates.put(contactName, mGetChecked);

    if (convertView == null) {

        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.contact_name_item, null);

        groupViewHolder = new GroupViewHolder();

        groupViewHolder.mContactName = (TextView) convertView
                .findViewById(R.id.lblListHeader);

        groupViewHolder.mContactImage = (ImageView) convertView
                .findViewById(R.id.ivContactPhoto);

        convertView.setTag(groupViewHolder);
    } else {

        groupViewHolder = (GroupViewHolder) convertView.getTag();
    }

    if (contactImage != null) {
        groupViewHolder.mContactImage.setImageBitmap(contactImage);

    } else {
        groupViewHolder.mContactImage
                .setImageResource(R.drawable.default_contact);
    }

    groupViewHolder.mContactName.setText(contactName);

    return convertView;
}

@Override
public int getChildrenCount(int groupPosition) {
    return mListDataChild.get(mListDataHeader.get(groupPosition).getName())
            .size();
}

@Override
public ContactPhoneItems getChild(int groupPosition, int childPosition) {
    return mListDataChild.get(mListDataHeader.get(groupPosition).getName())
            .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) {

    final String contactName = getGroup(groupPosition).getName();
    final int mChildPosition = childPosition;

    numberText = getChild(groupPosition, childPosition).getNumber();
    String typeText = getChild(groupPosition, childPosition).getPhoneType();

    mGetChecked = mChildCheckStates.get(contactName);

    if (convertView == null) {

        LayoutInflater inflater = (LayoutInflater) this.mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.contact_detail_item, null);

        childViewHolder = new ChildViewHolder();

        childViewHolder.mPhoneNumber = (TextView) convertView
                .findViewById(R.id.tv_phone_number);

        childViewHolder.mPhoneType = (TextView) convertView
                .findViewById(R.id.tv_phone_type);

        childViewHolder.mCheckBox = (CheckBox) convertView
                .findViewById(R.id.checkBox);

        convertView.setTag(R.layout.contact_detail_item, childViewHolder);

    } else {

        childViewHolder = (ChildViewHolder) convertView
                .getTag(R.layout.contact_detail_item);
    }

    childViewHolder.mPhoneNumber.setText(numberText);
    childViewHolder.mPhoneType.setText(typeText);

    childViewHolder.mCheckBox.setChecked(mGetChecked[mChildPosition]);
    childViewHolder.mCheckBox.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            boolean isChecked = childViewHolder.mCheckBox.isChecked();

            Log.d("Debug", "isChecked = " + String.valueOf(isChecked));

            if (isChecked) {

                selectedNumbers.add(numberText);

            } else {

                selectedNumbers.remove(numberText);
            }

            childViewHolder.mCheckBox.setChecked(isChecked);

            mGetChecked[mChildPosition] = isChecked;
            mChildCheckStates.put(contactName, mGetChecked);
        }
    });

    return convertView;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return false;
}

@Override
public boolean hasStableIds() {
    return false;
}

public ArrayList<String> getSelectedNumbers() {

    return selectedNumbers;

}

public final class GroupViewHolder {

    TextView mContactName;
    ImageView mContactImage;
}

public final class ChildViewHolder {

    TextView mPhoneNumber;
    TextView mPhoneType;
    CheckBox mCheckBox;
}

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    // TODO Auto-generated method stub
    Log.d("Debug", "onCheckChangedListener : " + String.valueOf(isChecked));
}

}


person Psest328    schedule 01.02.2014    source источник


Ответы (5)


Я вижу, у вас есть объект selectedNumbers, что это за коллекция? Возможно, имеет смысл иметь карту или список или некоторую коллекцию, основанную на чем-то более уникальном, например, на позиции группы и дочернего элемента. Тогда вы можете сделать это:

(EDIT: отредактировал код, чтобы убедиться, что checkedChangedListener не срабатывает) (EDIT 2 на основе обновления OP): вам, вероятно, не следует использовать карту строк для логических массивов. Вместо этого попробуйте это. Он довольно похож, но использует целые числа, которые будут более надежными для сравнения, чем строки.

...
HashMap<Integer, Integer> mCheckedStates; // assume initialized as you did
...

childViewHolder.mPhoneNumber.setText(numberText);
childViewHolder.mPhoneType.setText(typeText);
childViewHolder.mCheckBox.setOnCheckedChangeListener(null);
if (mCheckedStates.contains(groupPosition)) {
    int checkedChildren = mCheckedStates.get(groupPosition);
    if ((checkedChildren & (1 << childPosition)) ==  1) {
        childViewHolder.mCheckBox.setChecked(true);
    } else {
        //Edit: Cannot rely on checkbox being false on Recycle,
        childViewHolder.mCheckBox.setChecked(false);
    }
}
childViewHolder.mCheckBox.setOnCheckedChangeListener(this);

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

    // get group and child positions
    if (isChecked) {

        if (mCheckedStates.contains(groupPosition)) {
            // I'm using a bitmap to keep resources low, but it's not necessary to do it this way
            int childmap = mCheckedStates.get(groupPosition);
            childmap += (1 << childPosition);
            mCheckedStates.put(groupPosition, childmap);
        } else {
            mCheckedStates.put(groupPosition, (1 << childPosition));
        }
    } else {
        if (mCheckedStates.contains(groupPosition)) {
            int childmap = mCheckedStates.get(groupPosition);
            if (childmap == (1 << childPosition)) {
                mCheckedStates.remove(groupPosition);
            } else {
                childmap &= ~(1 << childPosition);
                mCheckedStates.put(groupPosition, childmap);
            }
        }
    }
}

}

person anddev84    schedule 01.02.2014
comment
Я обновил ОП. selectedNumbers — это массив целых чисел, представляющий собой набор отмеченных чисел. - person Psest328; 01.02.2014
comment
Я пробовал использовать HashMap‹String, boolean[]› (String = groupPosition, booelan = check state), но когда я расширяю группу и устанавливаю флажок, а затем разворачиваю другую группу, первый флажок снимается - person Psest328; 01.02.2014
comment
Я не вижу никакого кода в вашей функции getChildView для установки правильного проверенного состояния при повторном использовании представлений. Вы устанавливаете Text, но не проверяете состояние. - person NameSpace; 01.02.2014
comment
Как @user3126670 и я уже упоминал, попробуйте сохранить фактическое значение проверенного состояния, соблюдая осторожность при повторном запуске прослушивателя проверки изменений. - person anddev84; 01.02.2014
comment
Просто внес некоторые изменения на основе того, что вы сказали. Тестирую сейчас. Обновит OP с результатом через 2 или 3 минуты... OP обновлен - person Psest328; 01.02.2014
comment
У меня есть одна критика вышеупомянутого решения, однако оно устанавливает состояние проверки только тогда, когда (true). Его необходимо установить в любом случае, так как мы не можем полагаться на то, что повторно используемое состояние будет ложным. - person NameSpace; 01.02.2014
comment
@ user3126670 спасибо, я обновил свое решение с помощью этого предложения. - person anddev84; 01.02.2014
comment
@ anddev84 anddev84 Я так и не получил уведомления о том, что вы обновили свой ответ. Это решение выглядит очень интересно. Я собираюсь попробовать это сейчас, но мне скоро нужно уйти на работу, поэтому, возможно, я не смогу обновить до сегодняшнего вечера. - person Psest328; 01.02.2014
comment
@ anddev84 anddev84 Мне очень жаль, но это не так. по-прежнему проверяются случайные другие флажки, когда я получаю один - person Psest328; 01.02.2014
comment
@ anddev84 anddev84 Я даю вам чек, потому что, хотя ваш ответ не сработал для меня, он указал направление, которое в конечном итоге привело к трюку, который я публикую ниже. Благодаря тонну! - person Psest328; 02.02.2014

ВОТ РАБОЧЕЕ РЕШЕНИЕ

Хорошо, хотя в Интернете есть много предложений о флажках в расширяемых списках, ни одно из них не сработало для меня. Мне удалось заставить его работать с помощью группы людей, особенно anddev84. Теперь я не собираюсь утверждать, что это идеально или надежно. Я просто утверждаю, что это работает для меня. Я тестировал на 2 устройствах, и я очень доволен этим.

Итак, я взял свой рабочий код, сократил его до основных частей и добавил кучу полезных комментариев, чтобы любой, кому он нужен, мог его использовать. Надеюсь, это работает так же хорошо для вас, как и для меня. Наслаждаться

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;

// Eclipse wanted me to use a sparse array instead of my hashmaps, I just suppressed that suggestion
@SuppressLint("UseSparseArrays")
public class MyExpandableListAdapter extends BaseExpandableListAdapter {

    // Define activity context
    private Context mContext;

    /*
     * Here we have a Hashmap containing a String key 
     * (can be Integer or other type but I was testing 
     * with contacts so I used contact name as the key)
    */ 
    private HashMap<String, List<ExpListChildItems>> mListDataChild;

    // ArrayList that is what each key in the above 
    // hashmap points to
    private ArrayList<ExpListGroupItems> mListDataGroup;

    // Hashmap for keeping track of our checkbox check states
    private HashMap<Integer, boolean[]> mChildCheckStates;

    // Our getChildView & getGroupView use the viewholder patter
    // Here are the viewholders defined, the inner classes are
    // at the bottom
    private ChildViewHolder childViewHolder;
    private GroupViewHolder groupViewHolder;

    /*  
     *  For the purpose of this document, I'm only using a single
     *  textview in the group (parent) and child, but you're limited only
     *  by your XML view for each group item :)
    */ 
    private String groupText;
    private String childText

    /*  Here's the constructor we'll use to pass in our calling
     *  activity's context, group items, and child items
    */ 
    public MyExpandableListAdapter(Context context,
            ArrayList<ExpListGroupItems> listDataGroup, HashMap<String, List<ExpListChildItems>> listDataChild) {

        mContext = context;
        mListDataGroup = listDataGroup;
        mListDataChild = listDataChild;

        // Initialize our hashmap containing our check states here
        mChildCheckStates = new HashMap<Integer, boolean[]>();
    }

    @Override
    public int getGroupCount() {
        return mListDataGroup.size();
    }

    /*  
     * This defaults to "public object getGroup" if you auto import the methods
     * I always make a point to change it from "object" to whatever item
     * I passed through the constructor
    */ 
    @Override
    public ExpListGroupItems getGroup(int groupPosition) {
        return mListDataGroup.get(groupPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {

        //  I passed a text string into an activity holding a getter/setter
        //  which I passed in through "ExpListGroupItems".
        //  Here is where I call the getter to get that text
        groupText = getGroup(groupPosition).getGroupText();

        if (convertView == null) {

            LayoutInflater inflater = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.group_item, null);

            // Initialize the GroupViewHolder defined at the bottom of this document
            groupViewHolder = new GroupViewHolder();

            groupViewHolder.mGroupText = (TextView) convertView.findViewById(R.id.groupTextView);

            convertView.setTag(groupViewHolder);
        } else {

            groupViewHolder = (GroupViewHolder) convertView.getTag();
        }

        groupViewHolder.mGroupText.setText(groupText);

        return convertView;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return mListDataChild.get(mListDataGroup.get(groupPosition).getMyText()).size();
    }

    /*  
     * This defaults to "public object getChild" if you auto import the methods
     * I always make a point to change it from "object" to whatever item
     * I passed through the constructor
    */ 
    @Override
    public ExpListChildItems getChild(int groupPosition, int childPosition) {
        return mListDataChild.get(mListDataGroup.get(groupPosition).getMyText()).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) {

        final int mGroupPosition = groupPosition;
        final int mChildPosition = childPosition;

        //  I passed a text string into an activity holding a getter/setter
        //  which I passed in through "ExpListChildItems".
        //  Here is where I call the getter to get that text
        childText = getChild(mGroupPosition, mChildPosition).getChildText();

        if (convertView == null) {

            LayoutInflater inflater = (LayoutInflater) this.mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.child_item, null);

            childViewHolder = new ChildViewHolder();

            childViewHolder.mChildText = (TextView) convertView
                    .findViewById(R.id.childTextView);

            childViewHolder.mCheckBox = (CheckBox) convertView
                    .findViewById(R.id.checkBox);

            convertView.setTag(R.layout.child_item, childViewHolder);

        } else {

            childViewHolder = (ChildViewHolder) convertView
                    .getTag(R.layout.child_item);
        }

        childViewHolder.mChildText.setText(childText);
            /* 
         * You have to set the onCheckChangedListener to null
         * before restoring check states because each call to 
         * "setChecked" is accompanied by a call to the 
         * onCheckChangedListener
        */ 
        childViewHolder.mCheckBox.setOnCheckedChangeListener(null);

        if (mChildCheckStates.containsKey(mGroupPosition)) {
            /*
             * if the hashmap mChildCheckStates<Integer, Boolean[]> contains
             * the value of the parent view (group) of this child (aka, the key),
             * then retrive the boolean array getChecked[]
            */
            boolean getChecked[] = mChildCheckStates.get(mGroupPosition);

            // set the check state of this position's checkbox based on the 
            // boolean value of getChecked[position]
            childViewHolder.mCheckBox.setChecked(getChecked[mChildPosition]);

        } else {

            /*
            * if the hashmap mChildCheckStates<Integer, Boolean[]> does not
            * contain the value of the parent view (group) of this child (aka, the key),
            * (aka, the key), then initialize getChecked[] as a new boolean array
            *  and set it's size to the total number of children associated with 
            *  the parent group
            */
            boolean getChecked[] = new boolean[getChildrenCount(mGroupPosition)];

            // add getChecked[] to the mChildCheckStates hashmap using mGroupPosition as the key
            mChildCheckStates.put(mGroupPosition, getChecked);

            // set the check state of this position's checkbox based on the 
            // boolean value of getChecked[position]
            childViewHolder.mCheckBox.setChecked(false);
        }

        childViewHolder.mCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                            boolean isChecked) {

                        if (isChecked) {

                                boolean getChecked[] = mChildCheckStates.get(mGroupPosition);
                                getChecked[mChildPosition] = isChecked;
                                mChildCheckStates.put(mGroupPosition, getChecked);

                        } else {

                                boolean getChecked[] = mChildCheckStates.get(mGroupPosition);
                                getChecked[mChildPosition] = isChecked;
                                mChildCheckStates.put(mGroupPosition, getChecked);
                        }
                    }
                });

        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    public final class GroupViewHolder {

        TextView mGroupText;
    }

    public final class ChildViewHolder {

        TextView mChildText;
        CheckBox mCheckBox;
    }
}
person Psest328    schedule 02.02.2014
comment
Спасибо, что поделились кодом. Я действительно застрял на этом в течение длительного времени. Быстрый вопрос: как нам получить доступ к списку проверенных элементов из основного действия? Спасибо. - person RmK; 30.01.2015
comment
Если ваша активность содержит ссылку на адаптер, вы можете просто создать геттер в адаптере, который возвращает массив флажков, и вызвать myAdapeter.myGetter() из активности - person Psest328; 30.01.2015

Я также стал жертвой той же проблемы и попробовал ваше решение, и теперь оно работает как шарм. Спасибо, приятель. :)

Я просто изменил код с помощью String вместо пользовательской модели домена для удобства других людей.

MainActivity.java

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.Toast;

public class MainActivity extends Activity {

List<String> groupList;
List<String> childList;
Map<String, List<String>> laptopCollection;
ExpandableListView expListView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Log.d("-Test Exapansion-", "Nai Yara");

    createGroupList();

    createCollection();

    expListView = (ExpandableListView) findViewById(R.id.laptop_list);

 final MyExpandableListAdapter expListAdapter = new  MyExpandableListAdapter
(getApplicationContext() , 
groupList, laptopCollection);
    expListView.setAdapter(expListAdapter);
    expListView.getHeaderViewsCount();

    //expListView.expandGroup(1);
    //expListView.expandGroup(2);

int numberOfHeaders = expListView.getExpandableListAdapter().getGroupCount();
    Log.d("-Test Exapansion-", "Number of Groups are:"+numberOfHeaders);

    for(int i = 0; i<numberOfHeaders; i++){
        expListView.expandGroup(i);
    }

    setGroupIndicatorToRight();

    expListView.setOnChildClickListener(new OnChildClickListener() {

        public boolean onChildClick(ExpandableListView parent, View v,
                int groupPosition, int childPosition, long id) {
            final String selected = (String) expListAdapter.getChild(
                    groupPosition, childPosition);
        Toast.makeText(getBaseContext(), selected, Toast.LENGTH_LONG)
                    .show();

            return true;
        }
    });
}

private void createGroupList() {
    groupList = new ArrayList<String>();
    groupList.add("HP");
    groupList.add("Dell");
    groupList.add("Lenovo");
    groupList.add("Sony");
    groupList.add("HCL");
    groupList.add("Samsung");
    groupList.add("HTC");
}

private void createCollection() {
    // preparing laptops collection(child)
    String[] hpModels = { "HP Pavilion G6-2014TX", "ProBook HP 4540",
            "HP Envy 4-1025TX" };
    String[] hclModels = { "HCL S2101", "HCL L2102", "HCL V2002" };
    String[] lenovoModels = { "IdeaPad Z Series", "Essential G Series",
            "ThinkPad X Series", "Ideapad Z Series" };
    String[] sonyModels = { "VAIO E Series", "VAIO Z Series",
            "VAIO S Series", "VAIO YB Series" };
    String[] dellModels = { "Inspiron", "Vostro", "XPS" };
    String[] samsungModels = { "NP Series", "Series 5", "SF Series" };
    String[] hTcModels = { "One", "One X", "Desire Series" };

    laptopCollection = new LinkedHashMap<String, List<String>>();

    for (String laptop : groupList) {
        if (laptop.equals("HP")) {
            loadChild(hpModels);
        } else if (laptop.equals("Dell"))
            loadChild(dellModels);
        else if (laptop.equals("Sony"))
            loadChild(sonyModels);
        else if (laptop.equals("HCL"))
            loadChild(hclModels);
        else if (laptop.equals("Samsung"))
            loadChild(samsungModels);
        else if (laptop.equals("HTC"))
            loadChild(hTcModels);
        else
            loadChild(lenovoModels);

        laptopCollection.put(laptop, childList);
    }
}

private void loadChild(String[] laptopModels) {
    childList = new ArrayList<String>();
    for (String model : laptopModels)
        childList.add(model);
}

private void setGroupIndicatorToRight() {
    /* Get the screen width */
    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    int width = dm.widthPixels;

    expListView.setIndicatorBounds(width - getDipsFromPixel(35), width
            - getDipsFromPixel(5));
}

// Convert pixel to dip
public int getDipsFromPixel(float pixels) {
    // Get the screen's density scale
    final float scale = getResources().getDisplayMetrics().density;
    // Convert the dps to pixels, based on density scale
    return (int) (pixels * scale + 0.5f);
}

@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;
}
}

MyExpandableListAdapter.java

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.Toast;

public class MainActivity extends Activity {

List<String> groupList;
List<String> childList;
Map<String, List<String>> laptopCollection;
ExpandableListView expListView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Log.d("-Test Exapansion-", "Nai Yara");

    createGroupList();

    createCollection();

expListView = (ExpandableListView) findViewById(R.id.laptop_list);
final MyExpandableListAdapter 
expListAdapter = 
new MyExpandableListAdapter(getApplicationContext()
, groupList, laptopCollection);
    expListView.setAdapter(expListAdapter);
    expListView.getHeaderViewsCount();



int numberOfHeaders = expListView.getExpandableListAdapter().getGroupCount();
    Log.d("-Test Exapansion-", "Number of Groups are:"+numberOfHeaders);

    for(int i = 0; i<numberOfHeaders; i++){
        expListView.expandGroup(i);
    }

    setGroupIndicatorToRight();

    expListView.setOnChildClickListener(new OnChildClickListener() {

        public boolean onChildClick(ExpandableListView parent, View v,
                int groupPosition, int childPosition, long id) {
            final String selected = (String) expListAdapter.getChild(
                    groupPosition, childPosition);
        Toast.makeText(getBaseContext(), selected, Toast.LENGTH_LONG)
                    .show();

            return true;
        }
    });
}

private void createGroupList() {
    groupList = new ArrayList<String>();
    groupList.add("HP");
    groupList.add("Dell");
    groupList.add("Lenovo");
    groupList.add("Sony");
    groupList.add("HCL");
    groupList.add("Samsung");
    groupList.add("HTC");
}

private void createCollection() {
    // preparing laptops collection(child)
    String[] hpModels = { "HP Pavilion G6-2014TX", "ProBook HP 4540",
            "HP Envy 4-1025TX" };
    String[] hclModels = { "HCL S2101", "HCL L2102", "HCL V2002" };
    String[] lenovoModels = { "IdeaPad Z Series", "Essential G Series",
            "ThinkPad X Series", "Ideapad Z Series" };
    String[] sonyModels = { "VAIO E Series", "VAIO Z Series",
            "VAIO S Series", "VAIO YB Series" };
    String[] dellModels = { "Inspiron", "Vostro", "XPS" };
    String[] samsungModels = { "NP Series", "Series 5", "SF Series" };
    String[] hTcModels = { "One", "One X", "Desire Series" };

    laptopCollection = new LinkedHashMap<String, List<String>>();

    for (String laptop : groupList) {
        if (laptop.equals("HP")) {
            loadChild(hpModels);
        } else if (laptop.equals("Dell"))
            loadChild(dellModels);
        else if (laptop.equals("Sony"))
            loadChild(sonyModels);
        else if (laptop.equals("HCL"))
            loadChild(hclModels);
        else if (laptop.equals("Samsung"))
            loadChild(samsungModels);
        else if (laptop.equals("HTC"))
            loadChild(hTcModels);
        else
            loadChild(lenovoModels);

        laptopCollection.put(laptop, childList);
    }
}

private void loadChild(String[] laptopModels) {
    childList = new ArrayList<String>();
    for (String model : laptopModels)
        childList.add(model);
}

private void setGroupIndicatorToRight() {
    /* Get the screen width */
    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    int width = dm.widthPixels;

    expListView.setIndicatorBounds(width - getDipsFromPixel(35), width
            - getDipsFromPixel(5));
}

// Convert pixel to dip
public int getDipsFromPixel(float pixels) {
    // Get the screen's density scale
    final float scale = getResources().getDisplayMetrics().density;
    // Convert the dps to pixels, based on density scale
    return (int) (pixels * scale + 0.5f);
}

@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;
}
}
person Nodxpert    schedule 15.05.2014

Проблема в том, что вы используете позиции в качестве идентификаторов. Позиция не является идентификатором. Позиция может меняться, и позиция ребенка без групповой позиции не является уникальным идентификатором.

person A. Binzxxxxxx    schedule 02.02.2014

  1. Сначала вам нужно создать новый HashMap, чтобы сохранить дочерний элемент CheckBoxState в ExpandablelistView.

  2. Объявите HashMap в адаптере как подобное-

    private HashMap mChildCheckStates;// Создан новый HashMap

  3. Следование коду, прошедшему в вашем адаптере

    cb.setOnCheckedChangeListener(null);
    
    if (mChildCheckStates.containsKey(mGroupPosition)) {
    
        boolean getChecked[] = mChildCheckStates.get(mGroupPosition);
         cb.setChecked(getChecked[mChildPosition]);
    
    
    }else {
    
        boolean getChecked[] = new boolean[getChildrenCount(mGroupPosition)];
    
        mChildCheckStates.put(mGroupPosition, getChecked);
    
       cb.setChecked(false);
    
    
    }
    
     cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    
         @Override
         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    
             if (isChecked) {
    
                 boolean getChecked[] = mChildCheckStates.get(mGroupPosition);
                 getChecked[mChildPosition] = isChecked;
                 mChildCheckStates.put(mGroupPosition, getChecked);
    
                 //Toast.makeText(mContext,"group-"+mGroupPosition+"child-"+mChildPosition,Toast.LENGTH_SHORT).show();
                // String value=mListDataChild[0];
    
                 Toast.makeText(mContext,"-"+mListDataChild,Toast.LENGTH_SHORT).show();
    
    
             } else {
    
                 boolean getChecked[] = mChildCheckStates.get(mGroupPosition);
                 getChecked[mChildPosition] = isChecked;
                 mChildCheckStates.put(mGroupPosition, getChecked);
                 Toast.makeText(mContext,"group-"+mGroupPosition+"child-"+mChildPosition,Toast.LENGTH_SHORT).show();
             }
         }
     });
    
  4. cb - флажок.

Я надеюсь, что эта логика поможет всем, спасибо

person Pravin Patil    schedule 03.09.2016
comment
cb.setOnCheckedChangeListener (нуль); это не t null, это моя ошибка, чтобы написать выше, если, иначе код условия находится под этим cb.setOnCheckedChangeListener { ....Используйте выше сначала, если, условие els внутри........ } - person Pravin Patil; 03.09.2016