Фрагменти - У зазначеної дитини вже є батько. Спочатку потрібно викликати removeView () батьків батьків


80

Я отримую цю помилку. Я спробував багато рішень, але не міг цього вирішити. Допоможи мені! Мені потрібно додати вигляд поверхні та кнопку до діяльності за допомогою фрагментів.

CamActivity.java:

public class CamActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cam);
        
        FragmentManager fm = getSupportFragmentManager();
        
        Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
        
        if(fragment == null) {
            fragment = new CamFragment();
            fm.beginTransaction()
            .add(R.id.fragmentContainer, fragment)
            .commit();
        }
    }
}

CamFragment.java:

public class CamFragment extends Fragment {

    private static final String TAG = "CamFragment";
    
    private Camera mCamera;
    private SurfaceView mSurfaceView;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
    View v = inflater.inflate(R.layout.camera_fragment, parent);
    
    Button capturePic = (Button)v.findViewById(R.id.img_capture);
    capturePic.setOnClickListener(new View.OnClickListener() {
        
        @Override
        public void onClick(View v) {
            getActivity().finish();
        }
    });
    
    mSurfaceView = (SurfaceView)v.findViewById(R.id.surfaceView1);
    return v;
}

}

Помилка:

04-18 13:24:12.735: E/AndroidRuntime(6321): FATAL EXCEPTION: main
04-18 13:24:12.735: E/AndroidRuntime(6321): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pack.camdictionary/com.pack.camdictionary.CamActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1728)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1747)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.access$1500(ActivityThread.java:155)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:993)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.os.Handler.dispatchMessage(Handler.java:130)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.os.Looper.loop(SourceFile:351)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.main(ActivityThread.java:3814)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at java.lang.reflect.Method.invokeNative(Native Method)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at java.lang.reflect.Method.invoke(Method.java:538)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:659)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at dalvik.system.NativeStart.main(Native Method)
04-18 13:24:12.735: E/AndroidRuntime(6321): Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.view.ViewGroup.addViewInner(ViewGroup.java:2007)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.view.ViewGroup.addView(ViewGroup.java:1902)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.view.ViewGroup.addView(ViewGroup.java:1859)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.view.ViewGroup.addView(ViewGroup.java:1839)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.NoSaveStateFrameLayout.wrap(NoSaveStateFrameLayout.java:40)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:570)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1166)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.Activity.performStart(Activity.java:3837)
04-18 13:24:12.735: E/AndroidRuntime(6321):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1701)
04-18 13:24:12.735: E/AndroidRuntime(6321):     ... 11 more

коли стався виняток. На capturePic клацання або перед ним.
maddy d

куди мені дзвонити getParent ?? @maddy перед цим
Вівек,

1
опублікуйте свій activity_camфайл xml
maddy d

Відповіді:


198

Спробуйте замінити

View v = inflater.inflate(R.layout.camera_fragment, parent);

С

View v = inflater.inflate(R.layout.camera_fragment, parent, false);

або

View v = inflater.inflate(R.layout.camera_fragment, null);

10
Намагайтеся уникати передачі нуля як батьків, використовуйте перший варіант, про який він згадав
Домінік

7
@sudocoder Щоб відповісти, чому? Батьківський - це кореневий вигляд ієрархії, до якої ви роздуваєте ресурс, до якого потрібно приєднатись, LayoutInflater автоматично спробує приєднати завищений вигляд до поданого кореня. Однак у фреймворку є перевірка, що якщо ви передаєте значення null для кореня, він обходить цю спробу уникнути аварійного завершення роботи додатка ur. Якщо тут нічого не передавати, це говорить про те, що ви не знаєте батьківського подання завищеного xml.
Elltz,

2
гарне пояснення bignerdranch.com/blog/…
Раджеш Хадка

Дякую! Ти врятував мої години.
Прощання

8

На це питання вже було дано відповідь, але все ж я хотів би додати причину додавання false як третій параметр.

Метод inflate () приймає три аргументи:

  • Ідентифікатор ресурсу макета, який потрібно надути.
  • ViewGroup, щоб бути батьком завищеного макета. Передача контейнера є важливою для того, щоб система застосувала параметри макета до кореневого подання завищеного макета, зазначеного батьківським видом, в якому він відбувається.
  • Логічне значення, яке вказує, чи слід приєднувати завищений макет до ViewGroup (другий параметр) під час надування. (У цьому випадку це хибно, оскільки система вже вставляє завищений макет в контейнер - передача true створить надлишкову групу переглядів у кінцевому макеті.)

Джерело: http://developer.android.com/guide/components/fragments.html


7

У моєму випадку я робив це setTransition()протягом FragmentTransaction. Нижче код працював для мене:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        if(this::rootView.isInitialized){
            if(rootView.getParent() != null){
                (rootView.getParent() as ViewGroup).endViewTransition(rootView)
            }
            return this.rootView

        }

        ...

}

Можливо, це трапляється, коли ви неодноразово перемикаєтесь між фрагментами, що подання не встигає справді відірватися від батьківського через поточний перехід.


Так, я можу це підтвердити. У моєму конкретному випадку деякі мої фрагменти мають важкий та складний інтерфейс, такий як показ Google, MapViewі користувач може часто переходити між такими фрагментами. Оскільки повторне створення їхнього представлення цілком є ​​громіздким кожного разу, я роблю кешування подання (зберігаючи екземпляр подання у фрагменті та повертаючи його у onCreateView). Але через анімацію переходу між двома такими фрагментами обидва види існують короткочасно, і якщо користувач досить швидко повернеться назад, він вийде з ладу. Тож дзвінок endViewTransition- це рішення. Велике спасибі та +1 заслужено.
Мачкович

Крім того, як примітка, і як не дивно, наразі моя проблема стосується виключно пристроїв HUAWEI з операційною системою Android 9. Але ця проблема може бути відтворена на Nexus 5 та інших не пов’язаних між собою пристроях. Чому, я не знаю ... чи може бути проблема реалізації анімації власне до EMUI OS / Huawei , щоб зробити це , що легко трапитися так часто?
Мачкович

ця відповідь золота
coolcool1994

5

Я використовую API 26.0.2, і в моєму випадку збій стався через спеціальні анімації, встановлені для моїх фрагментів. Коментуючи виклик для встановлення власної анімації, вирішено проблему.

fragmentTransaction.setCustomAnimations (android.R.anim.fade_in, android.R.anim.fade_out);


подяка за коментар. Я відкрив це посилання, але пропустив вашу відповідь. на налагодження цього пішло 3 дні. Я міг би витратити більше днів, якби не побачив вашої відповіді.
Кадір Хуссейн,

ти знайшов якийсь спосіб зробити цю роботу за допомогою setCustomAnimations.?
Кадір Хуссейн,

@QadirHussain Вибачте, Hussain, я не намагався.
Satheesh

2

Я також зустрів цю проблему, і це моє рішення. це дуже просто

View v;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    if (v == null) {
        v = inflater.inflate(R.layout.camera_fragment, container);
    } else {
        ViewGroup parent = (ViewGroup) v.getParent();
        if (parent != null) {
            parent.removeView(v);
        }
    }
    return v;
}

Сподіваюся бути вам корисним



0

Тільки для довідки. Здається, це проблема в Android SDK.

У мене така сама ситуація, як у @Satheesh з версією SDK: 27.0.2, і спроба видалити setCustomAnimation, здається, працює. Але для видалення setCustomAnimations потрібно внести для мене багато змін, я вважаю за краще зберегти спеціальну анімацію. Що я зробив, так це оновити SDK до останньої версії, яка наразі є 27.1.1. І це працює для мене.


0

Може бути корисним

           View customView1;
           inflater= (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
           customView1= inflater.inflate(R.layout.edit_custom_alert_window, null);     
           try {
                if(customView2.getParent()!=null)
                    ((ViewGroup)customView2.getParent()).removeView(customView2);
            }catch (Exception e){

            }

0

У моєму коді була навігація, і ця помилка була показана, коли я натиснув кнопку «Назад» з одного з фрагментів. Це вирішено, коли в nav_graph я поставив popUpTo у відповідні дії . Деякі дії було виконано, але нічого не спливало.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.