addView不一致的行为

时间:2015-11-13 15:24:23

标签: android

我有一个自定义组件,它扩展了RelativeLayout,后者又包含一个GridLayout(名为mFormLayout)。我有一个公共方法,它添加了两个带有适当适配器源的微调器和一个用作删除行的按钮的imageview。

public class EditableTwinSpinnerGridForm extends EditableGridForm
{
    public void addTwinSpinnerRow(final Locale.MapKey spinner1DefVal, final Locale.MapKey spinner2DefVal)
    {
        Spinner spinner1 = createSpinner(mTSP.getFirstSpinnerRes(), spinner1DefVal.getId());
        spinner1.setOnItemSelectedListener(mTSP.getIsl());

        Spinner spinner2 = createSpinner(mTSP.getSecondSpinnerRes(), spinner2DefVal.getId());


        ImageView rmvBtn = createRemoveBtn();


        mFormLayout.addView(spinner1);
        mFormLayout.addView(spinner2);
        mFormLayout.addView(rmvBtn);
    }
}

出于某种原因,当我在活动中向onCreate 调用添加行时,此方法有效,但是当我在创建活动后调用此方法时(来自onclicklistener),Spinners要么不存在,要么只有其中一个出现。他们占据了空间,因为我看到了行和可移动图像视图。

我还注意到,当我在同一个活动中专注于EditText并弹出键盘时,当我按下以取下键盘时,添加的微调器会显示出来。

这是我用来创建微调器的代码:

protected Spinner createSpinner(Integer spinnerSrc, String defaultSpinnerValue)
    {
        Spinner spinner = new Spinner(mCtx, Spinner.MODE_DIALOG);
        // Setting the bg color to the containing color to remove the spinner arrow.
        spinner.setBackgroundResource(R.color.container_bg);

        SparseArray<Phrase> map = Locale.getInstance().getMap(spinnerSrc);
        PhraseArrayAdapter adapter = createSpinnerFromMap(spinnerSrc);
        spinner.setAdapter(adapter);

        if (defaultSpinnerValue.equals(Utilities.EMPTY_STRING) || defaultSpinnerValue.isEmpty())
        {
            throw new IllegalStateException();
        }
        else
        {
            Utilities.getInstance().setMapSpinnerPosByValue(map, defaultSpinnerValue, spinner);
        }

        adapter.setDropDownViewResource(R.layout.editable_spinner_dropdown_item);
        setSpinnerLayoutParams(spinner);

        return spinner;
    }

protected void setSpinnerLayoutParams(Spinner spinner)
    {
        GridLayout.LayoutParams lp = createDefaultGridParams();
        lp.setGravity(Gravity.FILL_HORIZONTAL);
        lp.width = 250;
        lp.rightMargin = 0;
        spinner.setLayoutParams(lp);
    }

代码在加载活动时起作用,所以我有点难过。我环顾四周,有些人建议我在addView中设置LayoutParams,但为什么这个方法在onCreate中工作,但之后没有?

这是视觉上发生的事情(前三行是从onCreate()中的循环添加的,后两个是通过按“Add +”添加的。正如你所看到的那样,第二个微调器没有出现,有时两个都没有显示出来。我也尝试调用invalidate和requestLayout无济于事。 Snapshot

我查看了invalidate方法,这是当前它所在的位置:

public abstract class EditableForm extends RelativeLayout implements ObservableInt
{
    private class OnAddClicked implements OnClickListener
    {
        @Override
        public void onClick(View v)
        {
            onAddClicked(v);
            EditableForm.this.invalidate();
            mFormLayout.invalidate();
        }
    }
}

哪些调用(在EditableGrid的子类中):

@Override
protected void onAddClicked(View clickedView)
{
    addTwinSpinnerRow();
    notifyObservers(new ObservableData(EDITABLE_ADD_GRID_CLICKED, null));
}

protected void addTwinSpinnerRow()
{
    Locale.MapKey v1 = Locale.getInstance().getMap(mTSP.getFirstSpinnerRes()).get(0).getMapId();
    Locale.MapKey v2 = Locale.getInstance().getMap(mTSP.getSecondSpinnerRes()).get(0).getMapId();
    addTwinSpinnerRow(v1, v2);
}

1 个答案:

答案 0 :(得分:1)

您是否尝试过调用容器视图的Invalidate方法而不是添加视图?

您添加的视图很可能就在那里,只需要绘制键盘隐藏/显示差异所建议的视图。旋转设备是否也会导致它们出现?如果是这样,这再次表明您需要重新绘制自定义布局。

When it's necessary to execute invalidate() on a View?