RadioGroup onCheckedChanged получава индекс, по-висок от ChildCount

Създавам динамично LinearLayout (персонализиран клас, който разширява LinearLayout) с RadioGroup вътре в него. Добавям също динамично RadioButtons. Този клас LinearLayout се използва в няколко дейности и фрагменти.

Странното поведение е, че вторият път, когато добавя LinearLayout, когато се извика OnCheckedChanged, получавам индекс, който не съществува в текущата ми RadioGroup. Не изглежда, че всеки път, когато създавам нов екземпляр на моя LinearLayout, RadioGroup смята, че RadioButtons, добавени преди това, все още са там.

Например, ако създам персонализиран LinearLayout и добавя четири елемента и след това създам друг LinearLayout (в друга дейност) с други 4 елемента, когато щракна върху първия елемент (на втората дейност), получавам 5 като позиция на кликнатия елемент.

Това е моят персонализиран клас LinearLayout:

public class AgrupacionConmutadorLayout extends LinearLayout{

    private static final String TAG = "AgrupacionConmutadorLayout";
    private int[] mColorFromLevel = {R.color.inspeccion_aparato_agrupacion_color_level_1, R.color.inspeccion_aparato_agrupacion_color_level_2,
            R.color.inspeccion_aparato_agrupacion_color_level_3, R.color.inspeccion_aparato_agrupacion_color_level_4, R.color.inspeccion_aparato_agrupacion_color_level_5};
    private Context mContext;

    private LinearLayout dataContainer;
    private TextView mTitle;
    private RelativeLayout mSubAgrupacionesContainer;
    private LinearLayout mDataAndSubAgrupacionesContainer;
    private RadioGroup mConmutadorContainer;

    private ArrayList<View> mLayoutsDataContained = new ArrayList<View>();

    private int mLevel;
    private LinearLayout mTitleContainer;
    private InspeccionesFormWidgetReceiver mModificationReceiver;

    private boolean isEdicion;

    public AgrupacionConmutadorLayout(Context context) {
        super(context);
        this.mContext = context;
        init(null, 0);
    }

    public AgrupacionConmutadorLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        init(attrs, 0);
    }

    public AgrupacionConmutadorLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.mContext = context;
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyle) {
        dataContainer = (LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.ins_agrupacion_conmutador_container, this);
        mTitle = (TextView) dataContainer.findViewById(R.id.ins_agrupacion_container_title);
        mSubAgrupacionesContainer = (RelativeLayout) findViewById(R.id.rl_ins_subagrupacion_container);
        mConmutadorContainer = (RadioGroup) findViewById(R.id.ins_agrupacion_conmutador_radio_group);
        mDataAndSubAgrupacionesContainer = (LinearLayout) findViewById(R.id.ll_ins_data_and_subagrupacion_container);
        mTitleContainer = (LinearLayout) findViewById(R.id.ll_ins_agrupacion_container_title);
        mConmutadorContainer.removeAllViews();
        mConmutadorContainer.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int pos) {
                Log.d(TAG, "onCheckedChanged Clicked pos: " + pos);
                Log.d(TAG, "onCheckedChanged RadioGroup size: " + radioGroup.getChildCount());
                Log.d(TAG, "onCheckedChanged " + mLayoutsDataContained.size());
                    //OnCheckedChanged comienza a devolver en 1, al ArrayList en 0
                    for (int i = 1; i < mLayoutsDataContained.size() + 1; i++) {
                        if (i == pos) {
                            mLayoutsDataContained.get(i - 1).setVisibility(View.VISIBLE);
                        } else {
                            mLayoutsDataContained.get(i - 1).setVisibility(View.GONE);
                        }
                    }
            }
        });

    }

    public void initialice(AgrupacionSios agrupacionSios, InspeccionesFormWidgetReceiver modificationReceiver, boolean isEdicion) {
        this.mModificationReceiver = modificationReceiver;
        this.isEdicion = isEdicion;

        mTitle.setText(agrupacionSios.getTitle());
        mTitle.setTextColor(mContext.getResources().getColor(mColorFromLevel[agrupacionSios.getLevel()]));
        if (agrupacionSios.isOcultarContenedor()) mTitleContainer.setVisibility(View.GONE);

        if (agrupacionSios.getNumOfSons() > 0) {
            drawSubAgrupaciones(agrupacionSios);
        }
        this.refreshDrawableState();
    }

    private void drawSubAgrupaciones(AgrupacionSios agrupacionSios) {
        ViewGroup.LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

        ArrayList<AgrupacionSios> agrupaciones = agrupacionSios.getAgrupacionesHijos();
        Iterator itAgr = agrupaciones.iterator();

        while (itAgr.hasNext()) {
            AgrupacionSios agrupacionHija = (AgrupacionSios) itAgr.next();
            if (agrupacionHija.getNumOfLevels() > 0 || agrupacionHija.getNumOfSons() > 0) {
                switch (agrupacionHija.getTipoSubAgrupaciones()) {
                    case CONMUTADOR:
                        AgrupacionConmutadorLayout v = new AgrupacionConmutadorLayout(mContext);
                        v.initialice(agrupacionHija, mModificationReceiver, isEdicion);
                        mSubAgrupacionesContainer.addView(v, layoutParams);
                        mLayoutsDataContained.add(v);
                        break;
                    case COLUMNAS:
                        AgrupacionColumnasLayout vCol = new AgrupacionColumnasLayout(mContext);
                        vCol.initialice(agrupacionHija, mModificationReceiver, isEdicion);
                        mSubAgrupacionesContainer.addView(vCol, layoutParams);
                        mLayoutsDataContained.add(vCol);
                        break;
                    default:
                        AgrupacionGenericaLayout vGen = new AgrupacionGenericaLayout(mContext);
                        vGen.isSonOfConmutador(true);
                        vGen.initialice(agrupacionHija, mModificationReceiver, isEdicion);
                        mSubAgrupacionesContainer.addView(vGen, layoutParams);
                        mLayoutsDataContained.add(vGen);
                        break;
                }
            }
            //Añadimos el botón de conmutación correspondiente a la subagrupación.
            addAgrupacionToConmutadorContainer(agrupacionHija);
        }
        mConmutadorContainer.check(1);
    }

    public void setBackgroundColor(int color) {
        setBackgroundResource(color);
    }



    private void addAgrupacionToConmutadorContainer(AgrupacionSios mAgrupacion) {
        ViewGroup.LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        RadioButton b = new RadioButton(mContext);
        b.setLayoutParams(layoutParams);
        b.setText(mAgrupacion.getTitle());
        b.setButtonDrawable(android.R.color.transparent);
        b.setBackground(mContext.getResources().getDrawable(R.drawable.ins_conmutador_radio_background));
        b.setPadding(20,5,20,5);
        RadioGroup.LayoutParams params
                = new RadioGroup.LayoutParams(mContext, null);
        params.setMargins(10, 0, 10, 0);
        b.setLayoutParams(params);

        mConmutadorContainer.addView(b);
    }
}

И това е начинът, по който създавам AgrupacionConmutadorLayout върху дейности и фрагменти:

   AgrupacionConmutadorLayout vConm = new AgrupacionConmutadorLayout(this);
   vConm.initialice(agrupacion, this, isEdicion);
   vConm.setVisibility(View.VISIBLE);
   mAgrupacionesContainer.addView(vConm, layoutParams);

-----------------РЕШЕНИЕ---------------------------

Отговорът на Мариус беше ключът, аз получавах щракнат ID на RadioButton, а не неговата позиция в RadioGroup.

Най-накрая го направих с помощта на тагове. Зададох реда му за всеки RadioButton като етикет:

private void addAgrupacionToConmutadorContainer(AgrupacionSios mAgrupacion) {
    ViewGroup.LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
    RadioButton b = new RadioButton(mContext);
    b.setLayoutParams(layoutParams);
    b.setText(mAgrupacion.getTitle());
    b.setButtonDrawable(android.R.color.transparent);
    b.setBackground(mContext.getResources().getDrawable(R.drawable.ins_conmutador_radio_background));
    b.setPadding(20, 5, 20, 5);
    RadioGroup.LayoutParams params
            = new RadioGroup.LayoutParams(mContext, null);
    params.setMargins(10, 0, 10, 0);
    b.setLayoutParams(params);
    b.setTag(mConmutadorContainer.getChildCount());
    mConmutadorContainer.addView(b);
}

И получавам този етикет в OnCheckedChangeListener:

   mConmutadorContainer.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup radioGroup, int clickedId) {
            View radioButtonClicked = radioGroup.findViewById(clickedId);
            if (radioButtonClicked != null) {
                Integer pos = (Integer) radioButtonClicked.getTag();
                Log.d(TAG, "onCheckedChanged RadioGroup clicked position: " + pos);
                for (int i = 0; i < mLayoutsDataContained.size(); i++) {
                    View view = mLayoutsDataContained.get(i);
                    if (pos.intValue() == i) {
                        view.setVisibility(View.VISIBLE);
                    } else view.setVisibility(View.GONE);
                }
            }
        }
    });

person pozuelog    schedule 28.01.2015    source източник
comment
Можете ли да извикате mConmutadorContainer.removeAllViews(); в initialice и проверка?   -  person Vilas    schedule 28.01.2015
comment
@EagleEye това е, което вече правя!   -  person pozuelog    schedule 28.01.2015
comment
Не в init(), в initialice()   -  person Vilas    schedule 28.01.2015
comment
Прав си, EagleEye, пробвах го в init(), но резултатите са същите.   -  person pozuelog    schedule 28.01.2015


Отговори (2)


Трябва да сте прочели погрешно API. Вторият параметър НЕ е позиция. Това е идентификаторът на бутона. Има няколко решения на вашия проблем.

Добавяне на идентификатор въз основа на позиция:

//not recommended way, as activity.findViewById uses this id, I GUESS something wrong may happen
private int currId;
...
b.setId(currId);
currId++;
container.addView(b);

Добавяне на етикет:

//recommended
b.setTag(mAgrupacion);
container.addView(b);
//then...
AgrupacionSios tag = (AgrupacionSios) b.getTag();
//do action based on tag information
person Marius    schedule 28.01.2015

Използвай това.

for (int i = 0; i < mLayoutsDataContained.size(); i++) {
                        if (i == pos) {
                            mLayoutsDataContained.get(i - 1).setVisibility(View.VISIBLE);
                        } else {
                            mLayoutsDataContained.get(i - 1).setVisibility(View.GONE);
                        }
                    }
person SANJAY GUPTA    schedule 28.01.2015
comment
Проблемът ми е, че pos съдържа стойност, по-висока от mLayoutsDataContained.size(); - person pozuelog; 28.01.2015