5

In my android application, I'm facing a IllegalStateException. I can't reproduce this exception later. This is the stacktrace

Non-fatal Exception: java.lang.IllegalStateException: ScrollView can host only one direct child
       at android.widget.ScrollView.addView(ScrollView.java:397)
       at android.support.design.widget.BaseTransientBottomBar.showView(BaseTransientBottomBar.java:436)
       at android.support.design.widget.BaseTransientBottomBar$1.handleMessage(BaseTransientBottomBar.java:178)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at android.os.Looper.loop(Looper.java:146)
       at android.app.ActivityThread.main(ActivityThread.java:5679)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:515)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
       at dalvik.system.NativeStart.main(NativeStart.java)  

Anyone please help me!

vm345
  • 813
  • 12
  • 28
  • Can you show us your layout XML with your ScrollView? I think the problem will be there... – Geryson Jun 12 '17 at 11:43
  • 3
    It looks like you're showing a `Snackbar` with a target `View` that's in some hierarchy that doesn't have a `CoordinatorLayout` or the `android.R.id.content` container, but it does have a `ScrollView` it's using as the fallback, since a `ScrollView` is a `FrameLayout`. Are you using a `Snackbar` in your app? If so, where? – Mike M. Jun 12 '17 at 12:02
  • I'm using Snackbar for showing error message to users. And the issue is with pre-lollipop devices – vm345 Jun 12 '17 at 12:09
  • 1
    Where exactly are you showing the `Snackbar`s? In an `Activity`? A `Dialog`? Also, which version of the support library are you using? – Mike M. Jun 12 '17 at 12:18
  • mainly in fragments – vm345 Jun 12 '17 at 12:20
  • 1
    Well, without knowing anything more about your setup, all I can suggest is kind of a hack. If you wrap your `ScrollView`s in `FrameLayout`s, the `Snackbar` _should_ then use that outer `FrameLayout` as its fallback, and not try to add itself to the `ScrollView`. I'm not sure that would solve everything, though, 'cause this might just be a symptom of another issue altogether. – Mike M. Jun 12 '17 at 12:28
  • 1
    I'm using https://github.com/NikolaDespotoski/BottomNavigationLayout library. This may be the issue – vm345 Jun 12 '17 at 12:35
  • 1
    Yeah, looks like a possibility. If you can narrow it down to that, you could file a bug report. Or use something else. – Mike M. Jun 12 '17 at 12:57
  • 1
    issues only for devices with OS – vm345 Jun 12 '17 at 12:59
  • 3
    Yep, the reason I say it looks like a possible cause is because it has two separate implementations of an internal `Snackbar` helper class; one for pre-Lollipop versions, and another for later versions. I'd suggest you test your app on a pre-Lollipop version, and if you can reproduce the issue, file a bug report with the minimal setup needed to demonstrate it. – Mike M. Jun 12 '17 at 13:13
  • let me check with those devices – vm345 Jun 12 '17 at 13:17
  • 2
    I had some spare time, so I ran some tests with that library on a KitKat device I've available. I tried every which way I can think of, but I couldn't reproduce your issue with it. In fact, the only way I could get `Snackbar` to fail exactly like that was to show it in a `PopupWindow` with a `ScrollView` for the content. Every other configuration I can come up with will have another eligible `FrameLayout` further up the hierarchy. Even if that library is part of the cause, I'd have to say it's somehow to do with your exact setup, as well. If you can reproduce it, add as much detail as you can. – Mike M. Jun 12 '17 at 15:52
  • @Mike M : Exactly! On my HC Desire 816, which it is upgraded to MarshMallow, came with Kit Kat installed. Even though upgraded, it has same Kit Kat related bugs e.g. Camera resource crashes, where if you take a pic from inside an app, you will see that Camera does not releases resources and you can't take another pic, unless device is rebooted. The problem we are referring to here is the another one. – Abhinav Saxena Aug 21 '18 at 10:01
  • 1
    @AbhinavSaxena Well, I was never able to reproduce this, so I don't really have any other suggestions, apart from the wrapper `FrameLayout` workaround I mentioned in a comment above. I don't know if vm345 ever figured anything out, but maybe they'll let ya know, if they did. – Mike M. Aug 21 '18 at 10:18
  • @Mike M: Well Sir, since it is an internal exception, I could not see the ScrollView myself. Secondly I do not get this bug frequently. My logic says that this happens due to Context being invalidated, or some thread (executor) still running in background, where Snackbar is called to show up. – Abhinav Saxena Aug 21 '18 at 10:55
  • 1
    @AbhinavSaxena Yeah, I'm not even sure if that's the exact same situation as this one. I'd assumed that vm345 had their own `ScrollView` in their `Fragment` layout somewhere, but I don't really know. They didn't give a lot of details here. – Mike M. Aug 21 '18 at 10:59
  • Possible duplicate of [How can I avoid "IllegalStateException: Scrollview can host only one direct child"?](https://stackoverflow.com/questions/3735095/how-can-i-avoid-illegalstateexception-scrollview-can-host-only-one-direct-chil) – Stanley Ko Mar 15 '19 at 05:38
  • 1
    @Mike M, Você é o cara. Resolveu parte do meu problema. Já tinha feito de tudo com o NestedScrollView, mas não era suficiente. o SnackBar era um dos problemas. Valeu! – Vicente Domingos Sep 10 '22 at 23:15

7 Answers7

2

I examined the question carefully, and I logically found that it is related to showing Snackbar on a fragment or activity, taken as a reference in another class as global object, when it is invalidated in onStop(), onDestroy() life cycle callback stage respectively:

https://stackoverflow.com/a/52019719/787399

Abhinav Saxena
  • 1,990
  • 2
  • 24
  • 55
1

Inside your ScrollView you have to host a child (e.g. a Linear Layout) which at it's time will host all the UI elements from that scrollview. You can't have, for example, 2 textviews added directly to a ScrollView. You need to have something to hold those UI elements inside the scrollview.

Gabi
  • 667
  • 1
  • 7
  • 17
1

In ScrollView you can have only one View (in View I mean TextView, Button and cetera, but ViewGroup is child of View too) or ViewGroup. So if you have multiple Views put them in a proper ViewGroup and it will work fine.

Dav iD
  • 56
  • 4
1

Scrollview can only have one direct child

example: This is valid-->

ScrollView
    LinearLayout
        Other Views
        ....
        ....
    LinearLayout
ScrollView

This is not-->

ScrollView
    LinearLayout
        Other Views
        ....
        ....
    LinearLayout
    LinearLayout
        Other Views
        ....
        ....
    LinearLayout

ScrollView
Shubham Goel
  • 1,962
  • 17
  • 25
1

I got the same issue. and I have reproduced using the below steps.

Step 1: make you Fragment Or Activity Layout with a parent of Scrollview.

Step 2: show Snackbar in onPause(), onStop(), onDestroy() like belove.

@Override
    public void onPause() {
        super.onPause();
        Snackbar.make(button, "onPause", Snackbar.LENGTH_LONG).show();
    }

    @Override
    public void onStop() {
        super.onPause();
        Snackbar.make(button, "onStop", Snackbar.LENGTH_LONG).show();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        Snackbar.make(button, "onDestroy", Snackbar.LENGTH_LONG).show();
    }

Now run an app and check in logcat. when you click on back button you will get same error mention in question.

Solution:

make a common Snackbar like below.

@Override
        public void onPause() {
            super.onPause();
            showSnackbar("onPause");
        }

        @Override
        public void onStop() {
            super.onPause();
            showSnackbar("onStop");
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            showSnackbar("onDestroy");
        }

    private void showSnackbar(String message) {
            if (isValidContext(getActivity())) {
                Snackbar.make(btnConsume, message, Snackbar.LENGTH_LONG).show();
            } 
        }

    public static boolean isValidContext(final Context context) {

            if (context == null) {
                return false;
            }
            if (context instanceof Activity) {
                final Activity activity = (Activity) context;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                    return !activity.isDestroyed() && !activity.isFinishing();
                } else {
                    return !activity.isFinishing();
                }
            }
            return true;

        }
VIISHRUT MAVANII
  • 11,410
  • 7
  • 34
  • 49
0

ScrollView will not accept many child's, Use only one Layout inside ScrollView like LinearLayout, RelativeLayout,FrameLayout or ConstraintLayout(Based on your needs)and then add all your child's.

See this for your reference

 <?xml version="1.0" encoding="utf-8"?>
    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

          //Add your Views here
        </android.support.constraint.ConstraintLayout>
    </ScrollView>
MathankumarK
  • 2,717
  • 1
  • 17
  • 34
0

Scroll view allow only one child directly like below :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
     <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
       <!--Here scroll view allow only one direct child-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
           <!--Here your other xml code-->
        </LinearLayout>
    </ScrollView>
 </LinearLayout>
ashish
  • 848
  • 6
  • 16