mikepenz/MaterialDrawer

ClassCastException when using androidx.preference and MiniDrawer

anthonydelahoz opened this issue · 6 comments

Hello,

I have a ClassCastException when using the MiniDrawer (Always Visible) and when the app has 'androidx.preference:preference-ktx:1.2.0' implementation.

I reproduced it with your sample code, only by adding "implementation 'androidx.preference:preference-ktx:1.2.0'" in the gradle :

2022-02-16 13:37:05.926 27386-27386/com.mikepenz.materialdrawer.app.debug E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.mikepenz.materialdrawer.app.debug, PID: 27386
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mikepenz.materialdrawer.app.debug/com.mikepenz.materialdrawer.app.MiniDrawerActivity}: java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to androidx.slidingpanelayout.widget.SlidingPaneLayout$LayoutParams
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        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)
     Caused by: java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to androidx.slidingpanelayout.widget.SlidingPaneLayout$LayoutParams
        at com.mikepenz.crossfader.Crossfader.setLeftMargin(Crossfader.java:394)
        at com.mikepenz.crossfader.Crossfader.build(Crossfader.java:306)
        at com.mikepenz.materialdrawer.app.MiniDrawerActivity.onCreate(MiniDrawerActivity.kt:152)
        at android.app.Activity.performCreate(Activity.java:6756)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        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) 

It seems to crash in the setLeftMargin method of Crossfader.

When removing the androidx.preference:preference implementation or using version 1.1.1 instead of 1.2.0 in the gradle, it works normally.

The crash happens here: https://github.com/mikepenz/Crossfader/blob/develop/library/src/main/java/com/mikepenz/crossfader/Crossfader.java#L306

Which means the R.id.content layout of the baseLayout is different: https://github.com/mikepenz/Crossfader/blob/develop/library/src/main/java/com/mikepenz/crossfader/Crossfader.java#L293

Looks like either the id is duplicated or the parent layout type changed from FrameLayout to SlidingPaneLayout

@mikepenz how can we solve it?
i also changed the androidx.preference:preference version back to 1.1.1 but it didn't help. by the way I'm using version 8.4.5

well, I found a solution 💯 . first of all YES, the app will crash if you add the androidx.preference:preference library no matter the version. but I don't think that's causing it. I think it is because of the lifecycle libraries that are shipping with androidx.preference:preference library meaning if you remove the preferences library and add the lifecycle library the app starts crashing again.

but if you force your build to use slidingpanelayout version 1.1.0 then everything works fine. since the current version of slidingpanelayout is 1.2.0 you have to add this to your grade :

implementation ("androidx.slidingpanelayout:slidingpanelayout:1.1.0"){
        force true
    }

personally, I don't like this because I'm using an older version of slidingpanelayout which may introduce more bugs In the feature.

one other thing that I did was extending the Crossfader class and add a little bit of check to the setLeftMargin function like this:

protected void setLeftMargin(View view, int leftMargin) {
        // avoiding the exception :)
       if (view.getLayoutParams() instanceof  SlidingPaneLayout.LayoutParams){
          SlidingPaneLayout.LayoutParams lp = (SlidingPaneLayout.LayoutParams) view.getLayoutParams();
          lp.leftMargin = leftMargin;
          lp.rightMargin = 0;

          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
             lp.setMarginStart(leftMargin);
             lp.setMarginEnd(0);
          }
          view.setLayoutParams(lp);
       }
    }

but the result was not desirable as some of the views wouldn't render or be misplaced on the screen

Thank you @ranjbarhadi for the additional details.

As of now it looks the Crossfader is no longer compatible with the latest sliding pane layout.

While the individual views (mini vs normal) of the drawer still exist in this library, it looks at this time implementing a sliding pane layout manually may be needed.

I am not yet sure at which time I may find time to look into the Crossfader library.

Looked over things. At the very moment I do not plan to update the Crossfader anymore. I archived its repo.

Please stay with the old v1.1.x version of it.

Thank you very much