S.P.
S.P.

Reputation: 2564

ClassCastException in PreferenceActivity with Android N Preview

I'm testing the app in the new Android N Preview version and I'm having one problem with the preference activity (in MarshMallow - Android 6.0 and lower versions is working fine).

I'm using: 'com.android.support:appcompat-v7:22.2.1' 'com.android.support:design:22.2.1'

This is the error:

java.lang.ClassCastException: android.widget.FrameLayout cannot be cast to android.widget.LinearLayout
   at com.myApp.PreferenceActivity.setUpNestedScreen(PreferenceActivity.java:1606)
   at com.myApp.PreferenceActivity.onPreferenceTreeClick(PreferenceActivity.java:1594)
   at android.preference.Preference.performClick(Preference.java:1005)
   at android.preference.PreferenceScreen.onItemClick(PreferenceScreen.java:214)
   at android.widget.AdapterView.performItemClick(AdapterView.java:310)
   at android.widget.AbsListView.performItemClick(AbsListView.java:1155)
   at android.widget.AbsListView$PerformClick.run(AbsListView.java:3087)
   at android.widget.AbsListView$3.run(AbsListView.java:4002)
   at android.os.Handler.handleCallback(Handler.java:739)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:148)
   at android.app.ActivityThread.main(ActivityThread.java:6066)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:770)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:660)

This is the code that is pointing the error:

public void setUpNestedScreen(PreferenceScreen preferenceScreen) {
        final Dialog dialog = preferenceScreen.getDialog();

        Toolbar bar;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            LinearLayout root = (LinearLayout) dialog.findViewById(android.R.id.list).getParent(); //Here is the line 1606
            View topView = LayoutInflater.from(this).inflate(R.layout.preference_toolbar, root, false);
            root.addView(topView, 0); // insert at top
            bar = (Toolbar) topView.findViewById(R.id.toolbar);

            bar.setTitle(preferenceScreen.getTitle());

            bar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialog.dismiss();
                }
            });

        }
    }

Upvotes: 1

Views: 347

Answers (2)

Priyank Patel
Priyank Patel

Reputation: 12372

Try like below to fix issue in android N (API level 24)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // For API level 24 - Android N 
    LinearLayout root = (LinearLayout) dialog.findViewById(android.R.id.list).getParent().getParent();
    View topView = LayoutInflater.from(this).inflate(R.layout.preference_toolbar, root, false);
    root.addView(topView, 0); // insert at top
}

Upvotes: 1

Aleks G
Aleks G

Reputation: 57326

From what I see, you have no reason to cast the result of your findViewById to LineraLayout. Just cast it to ViewGroup instead:

ViewGroup root = (ViewGroup) dialog.findViewById(android.R.id.list).getParent();
View topView = LayoutInflater.from(this).inflate(R.layout.preference_toolbar, root, false);
root.addView(topView, 0); // insert at top

That said, what is the actual problem you are trying to solve? Do you really want to add a custom component to a system-generated dialog?

EDIT: Based on the additional comments...

The solution in linked question is really a hack, which relies on a private, unpublished implementation of some internal android classes. Most likely, the new version of Android has changed the internal implementation. There's nothing you can do about it. You can try adopting the solution to work on Android N, but then the next version of android may break it again.

If you want a specific layout, you should create your own layout. The easiest thing to do is to move all your Preferences into a PreferenceFragment, then create a regular Activity from an XML with your top view and a placeholder, which you then replace with your Fragment.

This is a lot less work than it seems - I did this with my app recently, took me only about an hour to get everything working.

Upvotes: 0

Related Questions