Raptrex
Raptrex

Reputation: 4115

Android ScrollView can host only one direct child

I have a onclick listener from the gallery that should clear all the rows inside the tableview, then add row/rows to a tableview inside a scrollview. The fragment should change on every button click.

However I am getting: java.lang.IllegalStateException: ScrollView can host only one direct child.

myactivity button listener

            TrackerFragment tf = (TrackerFragment) getFragmentManager().findFragmentById(R.id.tracker1);
            tf = TrackerFragment.newInstance(listOfList.get(id).get(position));

            fragmentTransaction.add(R.id.tracker1, tf);
            fragmentTransaction.commit();
            t1 = true; //being used
            getFragmentManager().executePendingTransactions();

tracker fragment

public class TrackerFragment extends Fragment
{
    private Dish dish;

    public static TrackerFragment newInstance(Serializable dish) 
    {
        TrackerFragment tf = new TrackerFragment();

        Bundle args = new Bundle();
        args.putSerializable("dish", dish);
        tf.setArguments(args);

        return tf;
    }

    public static TrackerFragment newInstance(Bundle bundle)
    {
        Dish dish = (Dish) bundle.getSerializable("dish");
        return newInstance(dish);
    }

    @Override
    public void onCreate(Bundle myBundle)
    {
        super.onCreate(myBundle);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) 
    {
        View v = inflater.inflate(R.layout.tracker, container, false);

        TableLayout tableLayout = (TableLayout) v.findViewById(R.id.tracker_layout);
        tableLayout.removeAllViews();

        if (dish != null)
        {   
            //display others

            //display subsystem stuff
            for (int i = 0; i < dish.getSubsystems().size(); i++)
            {
                TableRow tableRow = new TableRow(v.getContext());
                tableRow.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));

                TextView tv = new TextView(v.getContext());
                tv.setText(dish.getSubsystems().get(i).getConnFuncAddr());

                tableRow.addView(tv);

                tableLayout.addView(tableRow);
            }
        }
        else
        {
            TableRow tableRow = new TableRow(v.getContext());
            tableRow.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));

            TextView tv = new TextView(v.getContext());
            tv.setText("Click on image to view more data");

            tableRow.addView(tv);

            tableLayout.addView(tableRow);
        }

        return v;
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="horizontal" 
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Trackers -->
    <LinearLayout
        android:layout_height="fill_parent"
        android:layout_width="300dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <fragment 
            android:name="android.gallery.TrackerFragment"
            android:id="@+id/tracker1"
            android:layout_height="500dp"
            android:layout_width="300dp"
            android:layout_weight="1">
        </fragment>

    </LinearLayout>

    <!-- Gallery -->
    <LinearLayout
        android:layout_height="fill_parent"
        android:layout_width="600dp"
        android:layout_weight="1"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="245dp">

            <Gallery 
                android:id="@+id/galleryid0"
                android:layout_width="fill_parent" 
                android:layout_height="match_parent"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="245dp">

            <Gallery 
                android:id="@+id/galleryid1"
                android:layout_width="fill_parent" 
                android:layout_height="match_parent"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="245dp">

            <Gallery 
                android:id="@+id/galleryid2"
                android:layout_width="fill_parent" 
                android:layout_height="match_parent"/>

            </LinearLayout>

        </LinearLayout>

</LinearLayout>

tracker.xml

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

    <TableLayout 
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        android:id="@+id/tracker_layout">

    </TableLayout>

</ScrollView>

Does anyone know whats wrong? I am guessing I am adding a table row to the scrollview and not the tableview, however, I dont see where I am doing that wrong in my code.

Upvotes: 7

Views: 53419

Answers (8)

Sohaib Aslam
Sohaib Aslam

Reputation: 1325

I am suffering from this problem last week and then find the best possible answer of that problem.

Scrollview can host only one direct child

Upvotes: 0

Devenias
Devenias

Reputation: 31

Try to use a <FrameLayout> instead of the <fragment> in your main.xml

So instead of

<fragment 
    android:name="android.gallery.TrackerFragment"
    android:id="@+id/tracker1"
    android:layout_height="500dp"
    android:layout_width="300dp"
    android:layout_weight="1">
</fragment>

use

<FrameLayout
    android:id="@+id/tracker1"
    android:layout_height="500dp"
    android:layout_width="300dp"
    android:layout_weight="1"
/>

It solved a similar problem with the ScrollView, where I was replacing the fragment from the activity with:

getSupportFragmentManager().beginTransaction()
    .replace(R.id.details_container, new DetailsFragment(), DETAILFRAGMENT_TAG)
    .commit();

Upvotes: 0

nobjta_9x_tq
nobjta_9x_tq

Reputation: 1241

You should add LinearLayout into ScrollView, it will working.

Upvotes: 3

MovGP0
MovGP0

Reputation: 7792

Another possibility is that the closing element is not matching. Ie.

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content">
    <LinearLayout ...>
        ...
    </LinearLayout>
</LinearLayout>

The error is in the last line.

Upvotes: 3

tyczj
tyczj

Reputation: 74066

I know this question is quite old but I ran into the same problem and it end up being that you cant have a ScrollView as you base view for the layout.

Just wrap the Scrollview in your tracker.xml layout with a RelativeLayout and you should be good to go

Upvotes: 5

Dax
Dax

Reputation: 2185

In fact, you can't have things like :

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:id="@+id/widget27"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<TableLayout
android:id="@+id/layoutOption"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
>
<ImageView
android:id="@+id/logoImmoweb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/logoimmoweb"
android:layout_gravity="top"
/>
 ...
</TableLayout>
</ScrollView>

but if you have an extra element outside the table, it crash with an java.lang.IllegalStateException: ScrollView can host only one direct child

example

<ScrollView
android:id="@+id/widget27"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<ImageView
android:id="@+id/logoImmoweb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/logoimmoweb"
android:layout_gravity="top"
/>
<TableLayout
android:id="@+id/layoutOption"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
>
...
</TableLayout>
</ScrollView>

Hope this help.

Upvotes: 5

Budius
Budius

Reputation: 39856

edit (2nd answer):

I've been playing with the code and I'm still not sure WHY this happens, definitely there's something wrong on the fragment manager when it swapping fragments (replace(resId, fragment))

In my fragment onCreateView was this code:

    View view = inflater.inflate(R.layout.post_fragment, null, false);
    if (item == null)
        return view;

    return BuildView(view);

post_fragment is an empty canvas with 1 ScrollView, 1 LinearLayout inside it, and some other ViewGroups inside it. This is to load an empty canvas on the 1st load (item is null) and on the 2nd time, through a user input, it would get the actual data to show.

for some reason beyond my knowledge, as seen in the logcat, FragmentManagerImpl.moveToState was calling ScrollView.AddChild causing the error.

Now I changed my fragments onCreateView to:

    if (item == null)
        return inflater.inflate(R.layout.empty, null, false);

    View view = inflater.inflate(R.layout.post_fragment, null, false);
    return BuildView(view);

so that the 'empty' canvas is a FrameLayout with nothing on it, and now everything is working happily. I'm sure this sounds like some odd error on the actual fragments framework, but it's a work around it.

1st answer:

Raptrex, as far as I can see. Yes, that table layout is the only child your scrowview have. I am having the exactly the same problem, and very frustrated trying to solve it.

From the LogCat/Debug, it seems that there's something in the Fragments manager that is calling and .AddView(view) in my ScrollView (check the log) it depends on how I change my XML layout I get this error or not, which let's say sounds pretty absurd!

Any ideas of how?why?what? I'm listening...

FATAL EXCEPTION: main
java.lang.IllegalStateException: ScrollView can host only one direct child
at android.widget.ScrollView.addView(ScrollView.java:219)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:787)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:977)
at android.app.BackStackRecord.run(BackStackRecord.java:638)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1309)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:398)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4123)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)

Upvotes: 0

hackbod
hackbod

Reputation: 91361

Um... don't put multiple views inside of a scroll view. Put a single view inside of it that is the kind of layout you want for your multiple views -- TableLayout, FrameLayout, etc.

Upvotes: 1

Related Questions