Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

父布局为ConstraintLayout时报错 #15

Closed
LuckyTerry opened this issue Sep 18, 2018 · 14 comments
Closed

父布局为ConstraintLayout时报错 #15

LuckyTerry opened this issue Sep 18, 2018 · 14 comments

Comments

@LuckyTerry
Copy link

172行左右
源代码
FrameLayout root = new FrameLayout(parent.getContext());
root.setLayoutParams(parent.getLayoutParams());
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
parent.setLayoutParams(layoutParams);

            if (viewParent instanceof ViewGroup) {
                ViewGroup rootGroup = (ViewGroup) viewParent;
                // 把 parent 从它自己的父容器中移除
                rootGroup.removeView(parent);
                // 然后替换成新的
                rootGroup.addView(root);
            }
            root.addView(parent);
            parent = root;

应该改为
FrameLayout root = new FrameLayout(parent.getContext());
root.setLayoutParams(parent.getLayoutParams());

            if (viewParent instanceof ViewGroup) {
                ViewGroup rootGroup = (ViewGroup) viewParent;
                // 把 parent 从它自己的父容器中移除
                rootGroup.removeView(parent);
                // 然后替换成新的
                rootGroup.addView(root);
            }
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            parent.setLayoutParams(layoutParams);
            root.addView(parent);
            parent = root;

在rootGroup.removeView(parent);之前设置parent.setLayoutParams(layoutParams);会导致remove时viewGroup cast 错误

@LuckyTerry
Copy link
Author

另外大佬什么时间能修复呢?公司项目,否则我得copy源码,本地打包才能使用了。

@nukc
Copy link
Owner

nukc commented Sep 18, 2018

StateView 版本是多少?还有布局层次是 stateView.inject(ConstraintLayout) ? 还是其它情况,代码贴一下会更好找到问题,我这边 inject ConstraintLayout 是没有问题的

@nukc
Copy link
Owner

nukc commented Sep 18, 2018

我按照你指定的代码试着重现了下,确实是兼容有问题,发现 ConstraintLayout 的 remove 方法里

    public void onViewRemoved(View view) {
        if (android.os.Build.VERSION.SDK_INT >= 14) {
            super.onViewRemoved(view);
        }

        this.mChildrenByIds.remove(view.getId());
        ConstraintWidget widget = this.getViewWidget(view); // 有widget 的存在,还需要转换再 remove
        this.mLayoutWidget.remove(widget);
        this.mConstraintHelpers.remove(view);
        this.mVariableDimensionsWidgets.remove(widget);
        this.mDirtyHierarchy = true;
    }
    public final ConstraintWidget getViewWidget(View view) {
        if (view == this) {
            return this.mLayoutWidget;
        } else {
            return view == null ? null : ((ConstraintLayout.LayoutParams)view.getLayoutParams()).widget;
        }
    }

之后我会发个版本

@LuckyTerry
Copy link
Author

最新版本;
外层ConstraintLayout,里面vertical_chain链接,共4个子布局,其中一个是RecyclerView;
inject(RecyclerView), 从源码上看,rv是ScrollingView,且其parent是Cl,所以进172行else块儿。
182行remove时,CL源码里面会有一个ViewGroup.LayoutParam到ConstraintLayout.LayoutParams的cast,这儿就报错了。实际上照我第一条的说法,解决了这个报错,但是又抛出了其他问题。感觉自己是改不动了。。

@nukc nukc closed this as completed in cc07875 Sep 18, 2018
@nukc nukc reopened this Sep 18, 2018
@nukc
Copy link
Owner

nukc commented Sep 18, 2018

之后又抛出什么问题了?你说一下,我这边试着复现一下

@nukc nukc added the bug label Sep 18, 2018
@LuckyTerry
Copy link
Author

cl移除了rv,但是cl在layout的时候通过bottomToTop这个id又找到了Rv(其实rv的children 即SparseArray<View

那个,的确仅包含最外层的Fl,不包含Rv,但是不知道为什么通过id还能取到Rv),并且取它的layoutParams,cast,然后就又错了。

@LuckyTerry
Copy link
Author

下班了,没有复现的环境,明天我给您一个复现场景和异常栈

@LuckyTerry
Copy link
Author

重现环境:
外层Cl,里面从上到下是一个Vertical的Chain,包含4个控件,injectedView是Rv,如此,意味着有控件约束于Rv

ConstraintLayout.java:1144(从源码上看,有别的控件约束于Rv(aka: injectedView)时,就会出错。Rv加入到FrameLayout,变成了FrameLayout.LayoutParams,getTargetWidget中cast 就又错了)

具体: java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.support.constraint.ConstraintLayout$LayoutParams
at android.support.constraint.ConstraintLayout.getTargetWidget(ConstraintLayout.java:1144)
at android.support.constraint.ConstraintLayout.setChildrenConstraints(ConstraintLayout.java:1038)
at android.support.constraint.ConstraintLayout.updateHierarchy(ConstraintLayout.java:803)
at android.support.constraint.ConstraintLayout.onMeasure(ConstraintLayout.java:1561)
at android.view.View.measure(View.java:19871)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6083)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.view.View.measure(View.java:19871)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6083)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
at android.view.View.measure(View.java:19871)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6083)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:689)
at android.view.View.measure(View.java:19871)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2275)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1366)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1619)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6343)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
at android.view.Choreographer.doCallbacks(Choreographer.java:686)
at android.view.Choreographer.doFrame(Choreographer.java:621)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

@nukc
Copy link
Owner

nukc commented Sep 19, 2018

布局发一下

@LuckyTerry
Copy link
Author

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="532dp"
android:layout_height="480dp"
android:background="@color/global_dialog_background">

<com.holderzone.android.store.aio.widget.DialogHeader
    app:layout_constraintVertical_chainStyle="spread"
    android:id="@+id/dialog_header_remark"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:title="@string/specification_goods" />

<EditText
    android:id="@+id/et_remark"
    style="@style/EditText"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginLeft="@dimen/global_margin_24dp"
    android:layout_marginRight="@dimen/global_margin_24dp"
    android:layout_marginTop="@dimen/global_margin_24dp"
    android:background="@drawable/global_et_corner_gray_shape"
    android:gravity="left|top"
    android:hint="@string/please_enter_remark"
    android:textColor="@color/global_black_ff0c1516"
    android:textColorHint="@color/global_gray_ff8da2a6"
    android:textSize="@dimen/global_size_16sp"
    app:layout_constraintBottom_toTopOf="@+id/rv_remark"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/dialog_header_remark"
    app:layout_constraintVertical_weight="1"
    tools:ignore="RtlHardcoded" />

<android.support.v7.widget.RecyclerView
    android:id="@+id/rv_remark"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginBottom="@dimen/global_margin_24dp"
    android:layout_marginLeft="@dimen/global_margin_24dp"
    android:layout_marginRight="@dimen/global_margin_24dp"
    android:layout_marginTop="@dimen/global_margin_16dp"
    app:layout_constraintBottom_toTopOf="@+id/btn_remark_determine"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/et_remark"
    app:layout_constraintVertical_weight="2">

</android.support.v7.widget.RecyclerView>

<Button
    android:id="@+id/btn_remark_determine"
    style="@style/Button.Angle"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="@string/determine"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />

</android.support.constraint.ConstraintLayout>

margin、bg、style等请忽略

@nukc
Copy link
Owner

nukc commented Sep 19, 2018

没复现出来

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/constraint_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.github.nukc.sample.ConstraintLayoutActivity">

    <TextView
        android:id="@+id/text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="顶部"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="spread" />

    <EditText
        android:id="@+id/et_remark"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="12dp"
        android:gravity="left|top"
        app:layout_constraintBottom_toTopOf="@+id/recycler_view"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/text"
        app:layout_constraintVertical_weight="1" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="12dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="12dp"
        app:layout_constraintBottom_toTopOf="@id/btn"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/et_remark"
        app:layout_constraintVertical_weight="2" />

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</android.support.constraint.ConstraintLayout>
mStateView = StateView.inject(findViewById(R.id.recycler_view));

@LuckyTerry
Copy link
Author

代码中是这样注入的, tartgetView即Rv,不介意的话能QQ(1018498538)上交流吗,这样效率慢了点。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

    stateView = StateView.inject(targetView())

}

@LuckyTerry
Copy link
Author

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants