RadioGroup onCheckedChanged 获得高于 ChildCount 的索引

RadioGroup onCheckedChanged getting an index higher than ChildCount

我正在动态创建一个 LinearLayout(一个扩展 LinearLayout 的自定义 Class),其中包含一个 RadioGroup。我也在动态添加 RadioButtons。此 LinearLayout class 用于多个 Activity 和 Fragments。

奇怪的是,当我第二次添加 LinearLayout 时,当调用 OnCheckedChanged 时,获取的索引在我当前的 RadioGroup 中不存在。似乎每次我创建 LinearLayout 的新实例时,RadioGroup 都认为之前添加的 RadioButtons 仍然存在。

例如,如果我创建一个自定义 LinearLayout 并添加四个项目,然后我创建另一个带有其他 4 个项目的 LinearLayout(在其他 Activity 中),当我单击第一个项目(在second Activity), 我得到一个 5 作为点击的项目位置。

这是我自定义的 LinearLayout class:

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

----------------解决方案------------------------

Marius 的回答是关键,我点击的是 RadioButton id,而不是他在 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);
                }
            }
        }
    });

使用这个。

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

你肯定看错了API。第二个参数不是位置。这是按钮的ID。您的问题有多种解决方案。

添加 id,基于位置:

//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