【问题标题】:addView inconsistent behavioraddView 不一致的行为
【发布时间】:2015-11-13 15:24:22
【问题描述】:

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

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)调用此方法时,微调器要么不在那里,要么只有其中一个出现。它们确实占用了空间,因为我看到了行和可移动图像视图。

我还注意到,当我在同一个活动中关注 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 无济于事。

我研究了 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);
}

【问题讨论】:

  • 尝试在你的布局上调用 invalidate() 来强制它重绘,看起来这是你的问题。

标签: android


【解决方案1】:

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

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

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

【讨论】:

  • 我更新了我的问题。我可能没有在正确的地方执行 invalidate() 。此外,在屏幕旋转时,任何添加的元素都会消失,我还没有处理屏幕旋转,所以我无法评论这种行为。
  • 我实际上认为,与其继承RelativeLayout,不如使用旨在添加条目的视图(例如RecyclerView)。这也将帮助您进行屏幕旋转,并为您提供对滚动等的内置控制这样做,您只需将您的项目添加到适配器,然后通过调用 NotifyDatasetChanged 要求 RecyclerView 重绘
  • 谢谢,我会调查的。我从未听说过 RecyclerView。
猜你喜欢
  • 1970-01-01
  • 2015-03-20
  • 2011-03-19
  • 2012-05-15
  • 2014-11-11
  • 2013-08-21
  • 2011-03-29
  • 2015-12-15
  • 1970-01-01
相关资源
最近更新 更多