View.addView() выдает исключение IllegalStateException (ViewSwitcher)`

У меня есть ViewSwitcher и я хочу добавить к нему представления:

    // initialize views
    final ViewSwitcher switcher = new ViewSwitcher(this);
    layMenu = (LinearLayout)findViewById(R.id.menu_main_view);
    final LevelPicker levelPicker = new LevelPicker(getApplicationContext());   

    (//)switcher.addView(layMenu);
    (//)switcher.addView(findViewById(R.layout.menu_switcher));

Один из них — пользовательский вид, другой — из XML. Я прокомментировал один из них, но они оба, кажется, бросаютIllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

Я попытался сделать несколько вещей, например сначала поместить представления в «контейнер» (другой макет) или попытался удалитьView ((View) getParent), как я полагаю, что logcat пытается сказать.

Вот мой xml-файл (в двух словах):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/menu_main_view">

<TextView>
</TextView>

<LinearLayout>
    <Button></Button> //couple of buttons
</LinearLayout>

</LinearLayout> //this is the parent i guess

Мое первое предположение заключалось в том, что все дочерние элементы должны быть у одного родителя, в моем случае это LinearLayout. Это не сработало.

Спасибо


person user717572    schedule 31.12.2011    source источник


Ответы (1)


да, любой экземпляр View должен иметь только 1 родителя в соответствии с исходным файлом {android}/frameworks/base/core/java/android/view/View.java

чтобы удалить экземпляр View из его контейнера, вам нужно сделать следующее:

// View view = ...
ViewParent parent = view.getParent();
if (parent instanceof ViewGroup) {
    ViewGroup group = (ViewGroup) parent;
    group.removeView(view);
}
else {
    throw new UnsupportedOperationException();
}

Я предполагаю, что вы вызвали Activity.this.setContentView(R.layout....) в файле макета xml. в данном случае родительским элементом представления LinearLayout был другой экземпляр LinearLayout, предоставленный "декоративным окном".

часто не рекомендуется удалять единственный дочерний элемент «декоративного окна». вам лучше создать дочерние элементы ViewSwitcher явно:

// Activity.this.setContentView(viewSwitcher);
// final Context context = Activity.this;
final android.view.LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View layMenu = inflater.inflate(R.layout...., null /* container */);
final View menuSwitcher = inflater.inflate(R.layout...., null /* container */);
viewSwitcher.addView(layMenu);
viewSwitcher.addView(menuSwitcher);
person chyou    schedule 31.12.2011
comment
Я смущен. т.е. мой LevelPicker - это пользовательский класс, расширяющий LinearLayout, где в конструкторе я вызываю this.addView(inflater.inflate(R.layout...). Как мне это сделать правильно? Также каким должно быть содержимое Xml при выполнении что вы описали выше? - person user717572; 31.12.2011
comment
LayoutInflater подходит для файла макета xml. в случае с LevelPicker просто создайте экземпляр с помощью оператора java new. или, если хотите, вы также можете использовать файл xml для описания пользовательского интерфейса на его основе, точно так же, как вы используете обычный LinearLayout в xml. единственное отличие состоит в том, что вы должны использовать полное имя LevelPicker в качестве тега xml, т. е. ‹you.package.name.LevelPicker android:layout_height=... .../› - person chyou; 02.01.2012
comment
любой действительный XML-файл макета, который вы использовали в вызове Activity.this.setContentView(), может быть увеличен с помощью LayoutInflater. - person chyou; 02.01.2012