通过Android 源码分析ScrollView ‘ScrollView can host only one direct child’错误问题

通过Android 源码分析ScrollView ‘ScrollView can host only one direct child’错误问题。


我们在初次使用SrollView的时候,可能会遇到 ScrollView can host only one direct child 的错误。

02-14 15:41:02.310 6111-6111/wjc.random.patternlock.demo E/AndroidRuntime: FATAL EXCEPTION: main
                                                                       Process: wjc.random.patternlock.demo, PID: 6111
                                                                       java.lang.RuntimeException: Unable to start activity ComponentInfo{wjc.random.patternlock.demo/wjc.random.patternlock.demo.PhotoActivity}: android.view.InflateException: Binary XML file line #30: ScrollView can host only one direct child
                                                                           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2576)
                                                                           at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2658)
                                                                           at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1492)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:111)
                                                                           at android.os.Looper.loop(Looper.java:207)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5737)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
                                                                        Caused by: android.view.InflateException: Binary XML file line #30: ScrollView can host only one direct child
                                                                           at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
                                                                           at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
                                                                           at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
                                                                           at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:413)
                                                                           at android.app.Activity.setContentView(Activity.java:2191)
                                                                           at wjc.random.patternlock.demo.PhotoActivity.onCreate(PhotoActivity.java:22)
                                                                           at android.app.Activity.performCreate(Activity.java:6309)
                                                                           at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1113)
                                                                           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2523)
                                                                           at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2658) 
                                                                           at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                                                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1492) 
                                                                           at android.os.Handler.dispatchMessage(Handler.java:111) 
                                                                           at android.os.Looper.loop(Looper.java:207) 
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5737) 
                                                                           at java.lang.reflect.Method.invoke(Native Method) 
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) 
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)

现在为通过来看看报错地源码:ScrollView.java

    @Override
public void addView(View child) {
    if (getChildCount() > 0) {
        throw new IllegalStateException("ScrollView can host only one direct child");
    }

    super.addView(child);
}

@Override
public void addView(View child, int index) {
    if (getChildCount() > 0) {
        throw new IllegalStateException("ScrollView can host only one direct child");
    }

    super.addView(child, index);
}

@Override
public void addView(View child, ViewGroup.LayoutParams params) {
    if (getChildCount() > 0) {
        throw new IllegalStateException("ScrollView can host only one direct child");
    }

    super.addView(child, params);
}

@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
    if (getChildCount() > 0) {
        throw new IllegalStateException("ScrollView can host only one direct child");
    }

在addview的时候,ScrollView会判断childcount,等已经存在一个childcount时,在addview就会报错。
同样在onMeasure 中也要求一个childcount: final View child = getChildAt(0);

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    if (!mFillViewport) {
        return;
    }

    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    if (heightMode == MeasureSpec.UNSPECIFIED) {
        return;
    }

    if (getChildCount() > 0) {
        final View child = getChildAt(0);
        final int height = getMeasuredHeight();
        if (child.getMeasuredHeight() < height) {
            final int widthPadding;
            final int heightPadding;
            final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
            final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
            if (targetSdkVersion >= VERSION_CODES.M) {
                widthPadding = mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin;
                heightPadding = mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin;
            } else {
                widthPadding = mPaddingLeft + mPaddingRight;
                heightPadding = mPaddingTop + mPaddingBottom;
            }

            final int childWidthMeasureSpec = getChildMeasureSpec(
                    widthMeasureSpec, widthPadding, lp.width);
            final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
                    height - heightPadding, MeasureSpec.EXACTLY);
            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
    }
}

通过上面的源码,我们就知道报错的原因了,addview>1了。

造成以上原因的实例:

1。layout布局中静态加载错误:

    <ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/scroll"
    android:layout_gravity="center_horizontal" >

    <LinearLayout
        android:id="@+id/content"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></LinearLayout>
    //多加了下面的LinearLayout,应去掉
    <LinearLayout
        android:id="@+id/content1"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></LinearLayout>
</ScrollView>

2.动态加载过程的错误:

        mScroll = (ScrollView)findViewById(R.id.scroll);
        // mScroll 只能一次addview
        for (int i=0;i<100;i++){
            TextView textView = new TextView(this);
            textView.setText("cntent "+i);
            mScroll.addView(textView);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值