SegmentedButton icon indicating copy to clipboard operation
SegmentedButton copied to clipboard

Invalid child view for SegmentedButtonGroup. Only SegmentedButton's are valid children of the group

Open Mr-Ramzan opened this issue 4 years ago • 6 comments

I am facing the issue of application crash on replacing the host fragment Of Segmented Buttons
Below is my Layout configuration for the Segmented Button Group.

    `
        <com.addisonelliott.segmentedbutton.SegmentedButtonGroup
            android:id="@+id/segmentedgroupjobs"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_margin="4dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="16dp"
            android:background="@color/white"
            android:elevation="3dp"
            android:orientation="horizontal"
            app:borderColor="@color/blue"
            app:borderWidth="1.2dp"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/add_new_job_button"
            app:position="1"
            app:radius="20dp"
            app:ripple="true"
            app:rippleColor="@color/white"
            app:selectedBackground="@color/blue"
            app:selectedButtonRadius="20dp"
            app:selectionAnimationDuration="250"
            app:selectionAnimationInterpolator="fastOutSlowIn">

            <com.addisonelliott.segmentedbutton.SegmentedButton
                android:id="@+id/Invited_jobs"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:layout_marginStart="1dp"
                android:layout_marginTop="1dp"
                android:layout_marginEnd="0dp"
                android:layout_marginBottom="1dp"
                android:layout_weight="1"


                app:selectedTextColor="@color/white"
                app:text="@string/invitedJobs"
                app:textColor="@color/blue"


                />

            <com.addisonelliott.segmentedbutton.SegmentedButton
                android:id="@+id/all_jobs"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:layout_marginTop="1dp"
                android:layout_marginBottom="1dp"
                android:layout_weight="1"
                android:gravity="center"
                app:selectedTextColor="@color/white"
                app:text="@string/publicJobs"
                app:textColor="@color/blue"


                />

            <com.addisonelliott.segmentedbutton.SegmentedButton
                android:id="@+id/invited_jobs"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:layout_marginStart="0dp"
                android:layout_marginTop="1dp"
                android:layout_marginEnd="1dp"
                android:layout_marginBottom="1dp"
                android:layout_weight="1"
                app:selectedTextColor="@color/white"
                app:text="@string/applied_jobs"
                app:textColor="@color/blue"

                />
        </com.addisonelliott.segmentedbutton.SegmentedButtonGroup>`

Below Snippets Define The Usage inside fragments

  1. The Initialization

      `segmentedGroup = view!!.findViewById(R.id.segmentedgroupjobs)
         if (RoutingAppController.instance!!.role != "Teacher") {
          segmentedGroup.visibility= View.GONE
         }`
    
  2. The Position Changed Listener

      ` if(RoutingAppController.instance!!.role =="Teacher") {
    
             segmentedGroup.setOnPositionChangedListener { position ->
                 selectedButton = position
                 when (position) {
                     0 -> {
    
                         childFragmentManager.beginTransaction().hide(active)
                             .show(invitedJobs).commit()
                         active = invitedJobs
                     }
                     1 -> {
    
                         childFragmentManager.beginTransaction().hide(active)
                             .show(otherJobs).commit()
                         active = otherJobs
                     }
                     2 -> {
                         childFragmentManager.beginTransaction().hide(active)
                             .show(appliedJobs).commit()
                         active = appliedJobs
                     }
                     else -> {
                     }
                 }
    
             }
    
         }` 
    

The Crash Stack is as below (SegmentedButtonGroup.java:507)

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.atomicskills.chatteach, PID: 30039 java.lang.IllegalArgumentException: Invalid child view for SegmentedButtonGroup. Only SegmentedButton's are valid children of the group at com.addisonelliott.segmentedbutton.SegmentedButtonGroup.addView(SegmentedButtonGroup.java:507) at android.view.ViewGroup.addView(ViewGroup.java:4960) at androidx.transition.TransitionUtils.createViewBitmap(TransitionUtils.java:138) at androidx.transition.TransitionUtils.copyViewImage(TransitionUtils.java:64) at androidx.transition.Visibility.onDisappear(Visibility.java:401) at androidx.transition.Visibility.createAnimator(Visibility.java:257) at androidx.transition.Transition.createAnimators(Transition.java:747) at androidx.transition.TransitionSet.createAnimators(TransitionSet.java:480) at androidx.transition.Transition.playTransition(Transition.java:1821) at androidx.transition.TransitionManager$MultiListener.onPreDraw(TransitionManager.java:301) at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1088) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2898) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1821) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7916) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:980) at android.view.Choreographer.doCallbacks(Choreographer.java:804) at android.view.Choreographer.doFrame(Choreographer.java:739) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:965) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:264) at android.app.ActivityThread.main(ActivityThread.java:7510) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)

Also, I am using Add() of fragment transaction for the first time and replace the other times In A bottom Navigation view.

Before I used Hide Show Approach for fragment Transactions, It was working fine in that scenario.

Mr-Ramzan avatar May 29 '20 06:05 Mr-Ramzan

Hello,

Sorry, but I only sort of understand what's going on here. Basically, the issue is that SegmentedButtonGroup can only have SegmentedButton directly as children. See here for the source code: https://github.com/addisonElliott/SegmentedButton/blob/master/library/src/main/java/com/addisonelliott/segmentedbutton/SegmentedButtonGroup.java#L543

I'm confused as to why a non-SegmentedButton is being added to the group? I don't see anywhere in your provided code where that would occur.

addisonElliott avatar May 29 '20 22:05 addisonElliott

Thanks For a Quick Response.

So I Override that throw expression, will it resolve the crash at least.

Since I am not adding or removing any view other than Segmented Button, I do not think it will be an issue If override throw statement with toast or something like it.

Mr-Ramzan avatar May 30 '20 08:05 Mr-Ramzan

The crash is happening while creating or destroying fragment 5 or 6thtime

Mr-Ramzan avatar May 30 '20 08:05 Mr-Ramzan

Hmm. So does commenting out the throw work?

For debugging purposes, I'd be interested in seeing what the child being added actually is. You might try just setting a breakpoint there or something

addisonElliott avatar May 30 '20 11:05 addisonElliott

I have toasted the type of view it turned out to be FrameLayout.

  `        {
        // Not allowed to have children of any type besides SegmentedButton
       //  throw new IllegalArgumentException("Invalid child view for SegmentedButtonGroup. Only 
       //    SegmentedButton's " + "are valid children of the group");
        **Toast.makeText(getContext(),"Different type view Found",Toast.LENGTH_LONG).show();
        Toast.makeText(getContext(),child.getClass().getName(),Toast.LENGTH_LONG).show();**

    }`

Screen is attached below

image

Crash went away though

Mr-Ramzan avatar May 31 '20 11:05 Mr-Ramzan

Okay, that's interesting.

Here are my thoughts:

  • Since a FrameLayout is added, if there are SegmentedButton children in that FrameLayout then this library will not work correctly. It expects the SegmentedButton's to be direct descendants.
    • If this is the case, then commenting out that exception probably won't work.
  • If the FrameLayout being added is just a temporary thing that is done for animation purposes, then commenting out that code is probably a perfectly fine thing to do.

Can you log the addView function and record each time it is called to see what's going on? I would recommend seeing what the View is an instance of. If it's a SegmentedButton, you could try getting the text in the button too.

I might also recommend adding the onViewRemoved handler to see when the views are being removed.

I think this will give us much more clarity as to what's going on.

addisonElliott avatar May 31 '20 12:05 addisonElliott