addisonElliott / SegmentedButton

Segmented Control/Button with animation for Android API 16+
Apache License 2.0
148 stars 39 forks source link

IllegalStateException when dragging #10

Closed tkashkin closed 5 years ago

tkashkin commented 5 years ago

IllegalStateException is thrown when dragging to the end of SegmentedButtonGroup.

SegmentedButtonGroup is in ConstraintLayout, has layout_width=wrap_content and is constrained to both start and end of parent.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.app, PID: 14547
    java.lang.IllegalStateException: X position does not have a button in getButtonPositionFromXF (X = 543,245483)
        at com.addisonelliott.segmentedbutton.SegmentedButtonGroup.getButtonPositionFromXF(SegmentedButtonGroup.java:490)
        at com.addisonelliott.segmentedbutton.SegmentedButtonGroup.dispatchTouchEvent(SegmentedButtonGroup.java:573)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2632)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2321)
        at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:418)
        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1810)
        at android.app.Activity.dispatchTouchEvent(Activity.java:3065)
        at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
        at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:380)
        at android.view.View.dispatchPointerEvent(View.java:10264)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4444)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4312)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3859)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3912)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3878)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4005)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3886)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4062)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3859)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3912)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3878)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3886)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3859)
        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6253)
        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6227)
        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6188)
        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6356)
        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
        at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
        at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176)
        at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:6327)
E/AndroidRuntime:     at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:6379)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
        at android.view.Choreographer.doCallbacks(Choreographer.java:686)
        at android.view.Choreographer.doFrame(Choreographer.java:615)
        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:6236)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)

Layout:

<com.addisonelliott.segmentedbutton.SegmentedButtonGroup
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@id/someView"
    app:radius="10dp"
    app:selectedButtonRadius="10dp"
    app:selectedBackground="@color/primary"
    app:draggable="true"
    app:ripple="true"
    app:rippleColor="@color/primary">

    <com.addisonelliott.segmentedbutton.SegmentedButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:paddingTop="4dp"
        android:paddingBottom="4dp"
        app:textStyle="bold"
        app:text="Button"
        app:selectedTextColor="@android:color/white" />

    ...

    <com.addisonelliott.segmentedbutton.SegmentedButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:paddingTop="4dp"
        android:paddingBottom="4dp"
        app:textStyle="bold"
        app:text="Button"
        app:selectedTextColor="@android:color/white" />

</com.addisonelliott.segmentedbutton.SegmentedButtonGroup>
addisonElliott commented 5 years ago

Hmm, this is odd. I fixed a similar issue like this but there was an underlying problem with how touch events were received.

Anyway, I'll look into this later this week. PRs are welcome and encouraged if you're able. Just let me know so we're both not working on it.

(I'm thinking I might just have touch events be ignored if out of bounds of the segmented button group but we'll see)