подключение каскадных флажков для расширения списка

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

    for(int i = 0; i < check_states.get(groupPosition).size(); i++) {
        if (check_states.get(groupPosition).get(i) == false) {
            Log.d ("Meat", "Child checkboxes are not all checked!!!");
        }
    }

Теперь я очень уверен, что это потому, что я вызываю эти команды до того, как список массивов закончит заполнение --> "check_states" - это список массивов массивов, который я использую для сохранения контрольных состояний флажков.

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

РЕДАКТИРОВАТЬ: обновлено с помощью logcat

10-06 19:18:08.204: W/dalvikvm(540): threadid=1: thread exiting with uncaught exception (group=0x40015560)
10-06 19:18:08.224: E/AndroidRuntime(540): FATAL EXCEPTION: main
10-06 19:18:08.224: E/AndroidRuntime(540): java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
10-06 19:18:08.224: E/AndroidRuntime(540):  at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
10-06 19:18:08.224: E/AndroidRuntime(540):  at java.util.ArrayList.get(ArrayList.java:311)
10-06 19:18:08.224: E/AndroidRuntime(540):  at com.mangodeveloper.mcathomie.McatTopicsExpandableListAdapter.getGroupView(McatTopicsExpandableListAdapter.java:166)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.ExpandableListConnector.getView(ExpandableListConnector.java:445)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.AbsListView.obtainView(AbsListView.java:1430)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.ListView.makeAndAddView(ListView.java:1745)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.ListView.fillDown(ListView.java:670)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.ListView.fillFromTop(ListView.java:727)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.ListView.layoutChildren(ListView.java:1598)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.AbsListView.onLayout(AbsListView.java:1260)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.view.View.layout(View.java:7175)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.RelativeLayout.onLayout(RelativeLayout.java:912)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.view.View.layout(View.java:7175)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.view.View.layout(View.java:7175)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.RelativeLayout.onLayout(RelativeLayout.java:912)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.view.View.layout(View.java:7175)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.view.View.layout(View.java:7175)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.view.View.layout(View.java:7175)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.view.ViewRoot.performTraversals(ViewRoot.java:1140)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.os.Handler.dispatchMessage(Handler.java:99)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.os.Looper.loop(Looper.java:123)
10-06 19:18:08.224: E/AndroidRuntime(540):  at android.app.ActivityThread.main(ActivityThread.java:3683)
10-06 19:18:08.224: E/AndroidRuntime(540):  at java.lang.reflect.Method.invokeNative(Native Method)
10-06 19:18:08.224: E/AndroidRuntime(540):  at java.lang.reflect.Method.invoke(Method.java:507)
10-06 19:18:08.224: E/AndroidRuntime(540):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-06 19:18:08.224: E/AndroidRuntime(540):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-06 19:18:08.224: E/AndroidRuntime(540):  at dalvik.system.NativeStart.main(Native Method)

Изменить еще раз: вот только о соответствующих частях расширяемого адаптера.

public class McatTopicsExpandableListAdapter extends BaseExpandableListAdapter {

...

public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild,
            View convertView, ViewGroup parent) {

        final ViewHolder holder;

        if (convertView == null) {
            LayoutInflater viewInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = viewInflater.inflate(R.layout.mtopics_childview, parent, false);  
            holder = new ViewHolder();
            holder.text = (TextView)convertView.findViewById(R.id.mtopicschildtv);
            holder.checkbox = (CheckBox)convertView.findViewById(R.id.mtopicchildchkbox);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.text.setText(getChild(groupPosition, childPosition).toString());

        for(int i = 0; i < children.length; i++) {
            ArrayList<Boolean> tmp = new ArrayList<Boolean>(children[i].length);
            for(int j = 0; j < children[i].length; j++) {
                tmp.add(true);
            }
            check_states.add(tmp);
        }

        if (check_states.get(groupPosition).get(childPosition) == true) {
            holder.checkbox.setChecked(true);
        }else{ holder.checkbox.setChecked(false);
        }

        holder.checkbox.setOnClickListener(new OnClickListener() {  
            public void onClick(View v) {
                if (holder.checkbox.isChecked()) {
                    check_states.get(groupPosition).set(childPosition, true);
                }else{ check_states.get(groupPosition).set(childPosition, false);
                }
            }   
        });

        return convertView;
    }

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

        ViewHolder holder;

        if (convertView == null) {
            LayoutInflater viewInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = viewInflater.inflate(R.layout.mtopics_groupview, parent, false);
            holder = new ViewHolder();
            holder.text = (TextView)convertView.findViewById(R.id.mtopicsgrouptv);
            holder.checkbox = (CheckBox)convertView.findViewById(R.id.cb_group);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.text.setText(getGroup(groupPosition).toString());

        for(int i = 0; i < check_states.get(groupPosition).size(); i++) {
            if (check_states.get(groupPosition).get(i) == false) {
                Log.d ("Meat", "Child checkboxes are not all checked!!!");
            }
        }

        holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    for(int i = 0; i < check_states.get(groupPosition).size(); i++) {
                        check_states.get(groupPosition).set(i, true);   
                    }       
                } else if (!isChecked)
                    for(int i = 0; i < check_states.get(groupPosition).size(); i++) {
                        check_states.get(groupPosition).set(i, false);          
                    }

                notifyDataSetChanged();
            }
        }); 

        return convertView;
    }

    //  additional components
    ArrayList<ArrayList<Boolean>> check_states = new ArrayList<ArrayList<Boolean>>(children.length);

    static class ViewHolder {
        TextView text;
        CheckBox checkbox;
    }

}

person mango    schedule 06.10.2012    source источник
comment
Вы должны добавить трассировку стека с исключением из файла logcat. Что делает заполнение списка значений boolean таким трудоемким?   -  person user    schedule 06.10.2012
comment
а как насчет логического allChildBoxesChecked = !check_states.get(groupPosition).contains(false); Однако это не решит вашу проблему. пожалуйста, опубликуйте logcat и код   -  person Tamir Scherzer    schedule 06.10.2012
comment
Там. я обновил его с помощью logcat. У меня есть основания полагать, что это должно быть какая-то проблема с разницей во времени в миллисекундах, потому что, если я помещу код сразу после метода заполнения массива, он работает без сучка и задоринки. Спасибо за этот элегантный лакомый кусочек, Тамир.   -  person mango    schedule 06.10.2012
comment
это: if (check_states.get(groupPosition).get(i) == false) {строка 183 в McatTopicsExpandableListAdapter? если да, то кажется, что массив совсем пустой (размер 0)   -  person Tamir Scherzer    schedule 06.10.2012
comment
где вы его поместите, если не после метода массива популяции?   -  person Tamir Scherzer    schedule 06.10.2012
comment
да. это строка 183. Я помещаю ее в getGroupView моего расширяемого адаптера списка. последовательность заполнения arraylist находится в моем getChildView расширяемого адаптера. но этот код не будет полезен в дочернем представлении, когда я заменю мясной журнал моими реальными намерениями. возможно, способ состоит в том, чтобы объединить оба метода в какой-то логический метод. :/   -  person mango    schedule 06.10.2012


Ответы (2)


Вы проверяете длину другого массива... Измените условие цикла на это:

for(int i = 0; i < check_states.get(groupPosition).size(); i++) {
    if (check_states.get(groupPosition).get(i) == false) {
        Log.d ("Meat", "Child checkboxes are not all checked!!!");
    }
}
person Sam    schedule 06.10.2012
comment
к сожалению, это не сработало, но я думаю, вы показали мне, что все это время я работал с чем-то близким, но не совсем правильными переменными - person mango; 06.10.2012
comment
Я признаю, что не уверен, что вы пытаетесь сделать, я просто прочитал логарифм и исправил ошибку. check_states.get(groupPosition) по-прежнему имеет размер 0. Однако я не думаю, что предоставляю более конкретную помощь, не видя больше кода. - person Sam; 06.10.2012

В порядке. имея в виду, что моей целью была каскадная цепочка с флажками, я наконец понял, что я делаю неправильно. причина, по которой мой arraylist не был заполнен к тому времени, когда я увидел расширяемый список, заключалась в том, что он по умолчанию рухнул, и я поместил экземпляр в getChildView, который еще не вызывался. Поэтому перемещение его в блок кода getGroupView исправило это. Но чтобы групповые флажки работали должным образом, мне понадобился новый (намного меньший) массив только для этих флажков группового списка, чтобы их состояния сохранялись. Затем я соответствующим образом устанавливаю проводные события флажка. Просто я подумал, что стоит отметить, что вызов notifyDataSetChanged() лучше всего работал в прослушивателях кликов или обработчиках событий, измененных, потому что, если он был оставлен в открытом или каком-либо условном выражении, то есть риск того, что он будет вызван посторонним, что блокировало мой расширяемый список. Ниже приведены важные части исправленного кода, и я изменю тему, чтобы точно отразить ответ, поскольку этот вопрос пошел в другом направлении.

ArrayList<ArrayList<Boolean>> child_check_states = new ArrayList<ArrayList<Boolean>>(children.length);
ArrayList<Boolean> group_check_states = new ArrayList<Boolean> (groups.length);

static class ViewHolder {
    TextView text;
    CheckBox checkbox;
}

public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild,
        View convertView, ViewGroup parent) {

    final ViewHolder holder;

    if (convertView == null) {
        LayoutInflater viewInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = viewInflater.inflate(R.layout.mtopics_childview, parent, false);  
        holder = new ViewHolder();
        holder.text = (TextView)convertView.findViewById(R.id.mtopicschildtv);
        holder.checkbox = (CheckBox)convertView.findViewById(R.id.mtopicchildchkbox);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.text.setText(getChild(groupPosition, childPosition).toString());

    if (child_check_states.get(groupPosition).get(childPosition) == true) {
        holder.checkbox.setChecked(true);   
    }else{ holder.checkbox.setChecked(false);
    }

    holder.checkbox.setOnClickListener(new OnClickListener() {  
        public void onClick(View v) {
            if (holder.checkbox.isChecked()) {
                child_check_states.get(groupPosition).set(childPosition, true);
                if (child_check_states.get(groupPosition).contains(false)) {
                    group_check_states.set(groupPosition, false);
                }else{
                    group_check_states.set(groupPosition, true);
                }
            }else{ 
                child_check_states.get(groupPosition).set(childPosition, false);
                group_check_states.set(groupPosition, false);
            }
            notifyDataSetChanged();
        }   
    });

    return convertView;
}

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

    fillChildArraylists();
    fillGroupArraylist();

    final ViewHolder holder;

    if (convertView == null) {
        LayoutInflater viewInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = viewInflater.inflate(R.layout.mtopics_groupview, parent, false);
        holder = new ViewHolder();
        holder.text = (TextView)convertView.findViewById(R.id.mtopicsgrouptv);
        holder.checkbox = (CheckBox)convertView.findViewById(R.id.cb_group);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.text.setText(getGroup(groupPosition).toString());

    if ((group_check_states.get(groupPosition)) == true) {
        holder.checkbox.setChecked(true);
    } else {
        holder.checkbox.setChecked(false);
    }

    holder.checkbox.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            if (holder.checkbox.isChecked()) {
                for(int i = 0; i < child_check_states.get(groupPosition).size(); i++) {
                    child_check_states.get(groupPosition).set(i, true);
                    group_check_states.set(groupPosition, true);
                }
            } else {
                for(int i = 0; i < child_check_states.get(groupPosition).size(); i++) {
                    child_check_states.get(groupPosition).set(i, false);
                    group_check_states.set(groupPosition, false);
                }
            }
            notifyDataSetChanged();
        }
    });

    return convertView;
}

private void fillChildArraylists () {
    for(int i = 0; i < children.length; i++) {
        ArrayList<Boolean> tmp = new ArrayList<Boolean>(children[i].length);
        for(int j = 0; j < children[i].length; j++) {
            tmp.add(true);
        }
        child_check_states.add(tmp);
    }
}

private void fillGroupArraylist () {
    for(int i = 0; i < groups.length; i++) {
        group_check_states.add(true);
    }
}
person mango    schedule 07.10.2012