Сначала немного предыстории:
У меня есть макет внутри прокрутки. Сначала, когда пользователь прокручивает экран, прокручивается прокрутка. Однако после определенного количества прокрутки я должен был отключить прокрутку в представлении прокрутки, чтобы переместить «фокус прокрутки» на веб-представление внутри дочернего макета. Таким образом, прокрутка фиксируется, и все события прокрутки переходят в веб-просмотр внутри нее.
Итак, для решения, когда достигается порог прокрутки, я удаляю дочерний макет из scrollview и помещаю его в родительский scrollview (и делаю прокрутку невидимой).
// Remove the child view from the scroll view
scrollView.removeView(scrollChildLayout);
// Get scroll view out of the way
scrollView.setVisibility(View.GONE);
// Put the child view into scrollview's parent view
parentLayout.addView(scrollChildLayout);
Общая идея: (-> означает содержит)
Раньше: parentlayout -> scrollview -> scrollChildLayout
После: parentLayout -> scrollChildLayout
Приведенный выше код дает мне это исключение:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:1976)
at android.view.ViewGroup.addView(ViewGroup.java:1871)
at android.view.ViewGroup.addView(ViewGroup.java:1828)
at android.view.ViewGroup.addView(ViewGroup.java:1808)
Вы знаете, что происходит? Я явно вызываю removeView для родителя.
источник
scrollView.removeView(scrollChildLayout)
пытается удалить дочерний элемент scrollView, а не сам scrollView из его родительской ViewGroupif (mAdView.getParent()!=null) ((ViewGroup) mAdView.getParent()).removeView(mAdView);
Попробуйте сначала удалить scrollChildLayout из родительского представления?
scrollview.removeView(scrollChildLayout)
Или удалите всех дочерних элементов из родительского представления и добавьте их снова.
scrollview.removeAllViews()
источник
В onCreate с действием или в onCreateView с фрагментом.
if (view != null) { ViewGroup parent = (ViewGroup) view.getParent(); if (parent != null) { parent.removeView(view); } } try { view = inflater.inflate(R.layout.fragment_main, container, false); } catch (InflateException e) { }
источник
Хорошо, называйте меня параноиком, но я предлагаю:
final android.view.ViewParent parent = view.getParent (); if (parent instanceof android.view.ViewManager) { final android.view.ViewManager viewManager = (android.view.ViewManager) parent; viewManager.removeView (view); } // if
кастинг без
instanceof
просто кажется неправильным. И (спасибо IntelliJ IDEA за то, что сообщили мне)removeView
является частьюViewManager
интерфейса. И не следует приводить к конкретному классу, когда доступен идеально подходящий интерфейс.источник
Все, что вам нужно сделать, это post () Runnable, который выполняет addView ().
источник
Котлин Решение
Kotlin упрощает родительское приведение с помощью
as?
, возвращая null, если левая сторона имеет значение null или приведение не выполняется.(childView.parent as? ViewGroup)?.removeView(childView)
Kotlin Extension Solution
Если вы хотите еще больше упростить это, вы можете добавить это расширение.
childView.removeSelf() fun View?.removeSelf() { this ?: return val parentView = parent as? ViewGroup ?: return parentView.removeView(this) }
Он не будет безопасно ничего делать, если это представление имеет значение null, родительское представление имеет значение null или родительское представление не является ViewGroup.
fun ViewGroup.removeViewSafe(toRemove: View) { if (contains(toRemove)) removeView(toRemove) }
источник
Я звонил parentView.removeView (childView), а childView все еще показывал. В конце концов я понял, что метод каким-то образом срабатывает дважды, и дважды добавил childView к parentView.
Итак, используйте parentView.getChildCount (), чтобы определить, сколько дочерних элементов имеет родительский элемент до добавления представления и после него. Если дочерний элемент добавляется слишком много раз, то самый верхний дочерний элемент удаляется, а копия childView остается, что похоже, что removeView работает, даже если это так.
Также не следует использовать View.GONE для удаления представления. Если он действительно удален, вам не нужно его скрывать, иначе он все еще там, и вы просто скрываете его от себя :(
источник
В моем случае у меня есть BaseFragment, а все остальные фрагменты наследуются от него.
Итак, мое решение было добавить эти строки в
OnDestroyView()
метод@Override public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (mRootView == null) { mRootView = (inflater == null ? getActivity().getLayoutInflater() : inflater).inflate(mContentViewResourceId, container, false); } ....//// } @Override public void onDestroyView() { if (mRootView != null) { ViewGroup parentViewGroup = (ViewGroup) mRootView.getParent(); if (parentViewGroup != null) { parentViewGroup.removeAllViews(); } } super.onDestroyView(); }
источник
Вы также можете сделать это, проверив, возвращает ли метод indexOfView View, если метод indexOfView возвращает -1, тогда мы можем использовать.
DetachViewFromParent ViewGroup (v); за которым следует removeDetachedView ViewGroup (v, true / false);
источник
Что я делал неправильно, поэтому я получил эту ошибку, я не создавал динамический макет и не добавлял к нему дочерние элементы, поэтому получил эту ошибку
источник
Вот мое решение.
Допустим, у вас есть два,
TextViews
и поместите их наLinearLayout
(с именемll
). Вы наденете этоLinerLayout
на другоеLinerLayout
.< lm Linear Layout> < ll Linear Layout> <name Text view> </name Text view> <surname Text view> </surname Text view> </ll Linear Layout> </lm Linear Layout>
Если вы хотите создать эту структуру, вам нужно передать родительский элемент в качестве наследования.
Если вы хотите использовать его в
onCreate
методе,this
будет достаточно.В противном случае вот сольон:
LinerLayout lm = new LinearLayout(this); // You can use getApplicationContext() also LinerLayout ll = new LinearLayout(lm.getContext()); TextView name = new TextView(ll.getContext()); TextView surname = new TextView(ll.getContext());
источник