How to use PreferenceScreen of Androidx
Asked Answered
S

3

22

My problem is that I wanted to add a PreferenceScreen to my Application, but I can't use it and I don't know why.

I implemented the library androidx.preference:preference:1.1.0-rc01. Then I wanted to add the PreferenceScreen to my XML-layout and it doesn't suggest any suggestion.

Next, I copied the XML-Code from Android-Developers into my XML-layout and compiled it, but by starting the activity it breaks with the error: java.lang.ClassCastException: class androidx.preference.PreferenceScreen cannot be cast to android.view.View

Can somebody help me to use the androidx.preference.PreferenceScreen correctly?

My Layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">
    <androidx.preference.SwitchPreference
        android:defaultValue="true"
        android:key="example_switch"
        android:summary="Turn this option on or off"
        android:title="Settings option" />
</androidx.preference.PreferenceScreen>
Stability answered 12/8, 2019 at 18:48 Comment(3)
Can you post your layout?Worker
Yes, I can post my layout. There is it.Stability
Also, your Preference activity would be helpful.Worker
S
40

Now the whole answer:

  1. Add this line to your App-Gradle: implementation 'androidx.preference:preference:1.1.1' or implementation 'androidx.preference:preference-ktx:1.1.1' for Kotlin. And sync Gradle. Create a Directory named xml in res Folder.

  2. Create in this directory an XML-File with your prefered name for example main_preferences. Root Element must be androidx.preference.PreferenceScreen.

  3. Fill XML-File with your settings for example:

<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">
    <androidx.preference.SwitchPreference
        android:defaultValue="true"
        android:key="example_switch"
        android:summary="Turn this option on or off"
        android:title="Settings option" />
</androidx.preference.PreferenceScreen>
  1. Create somewhere in the folder com.???.??? a java file for example named MainSettingsFragment. Superclass (means <Classname> extends <Superclass>) must be PreferenceFragmentCompat and override onCreatePreferences. You can copy this code:
import android.os.Bundle; 
import androidx.preference.PreferenceFragmentCompat;
import com.???.???.R;

public class <YourClassname> extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        // Load the preferences from an XML resource
        setPreferencesFromResource(R.xml.<yourXmlFilename>, rootKey);
    }
}
  1. Next, there are two options to implement the PreferencesSreen in your .

The beautiful and best way is, it to implement it per code on creation. Add in your SettingsActivty a FrameLayout and give it an ID for example fl_main_settings:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:id="@+id/<!-- yourID -->">

</FrameLayout>

And in your Activity Code add really on the top of the onCreate method this:

package com.???.???;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.Html;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.text.HtmlCompat;

import com.???.???.MainSettingsFragment;
public class SettingsActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.<SettingsActivityXML(with the FrameLayout)>);

        //If you want to insert data in your settings
        <YourSettingsFragmentClass> settingsFragment = new <YourSettingsFragmentClass>();
        settingsFragment. ...
        getSupportFragmentManager().beginTransaction().replace(R.id.<YourFrameLayout>,settingsFragment).commit();
        
        //Else
        getSupportFragmentManager().beginTransaction().replace(R.id.<YourFrameLayout>,new <YourSettingsFragmentClass>()).commit();
    }

Or you implement a Fragment in your SettingsActivityXml. But I don't recommend this ,because starting the activity takes a few seconds:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false">

    <fragment
        android:tag="frag"
        android:name="com.quickme.musicme.Fragments.MainSettingsFragment"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>
</LinearLayout>

That's it have fun.

Stability answered 13/8, 2019 at 7:30 Comment(4)
Thank you for this tutorial, it's very clear. But can you make it clearer when you say (point 5) "Add in your a FrameLayout" you missed a word, no ? is it Add in your main_activity.xml a FrameLayout ??? or is it in another xml file ?Cheffetz
I keep getting "java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setAdapter(androidx.recyclerview.widget.RecyclerView$Adapter)' on a null object reference" and only when I uncomment the line: "setPreferencesFromResource(R.xml.settings, rootKey);" and the xml looks fineCordwainer
Thank you, Christian. Unintentionally I commented it. Now I have fixed itStability
Where and why do you use a RecyclerView, Pete? I don't think that it's because of my code. Maybe you check your RecyclerView Adapter and its initialization ;)Stability
P
1

java.lang.ClassCastException: class androidx.preference.PreferenceScreen cannot be cast to android.view.View
My Layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen>
...
</androidx.preference.PreferenceScreen>

Pay attention.
It is not a layout.

Can somebody help me to use the androidx.preference.PreferenceScreen correctly?

You can find all info here.

You can define a Preference hierarchy.

Caution: The root tag must be a <PreferenceScreen>, and the XML resource must be placed in the res/xml/ directory.

<PreferenceScreen
    xmlns:app="http://schemas.android.com/apk/res-auto">

    ....

</PreferenceScreen>

To inflate a hierarchy from an XML attribute, create a PreferenceFragmentCompat, override onCreatePreferences(), and provide the XML resource:

class MySettingsFragment : PreferenceFragmentCompat() {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.preferences, rootKey)
    }
}

then add this Fragment to your Activity as you would with any other `Fragment.

Pinkham answered 12/8, 2019 at 21:24 Comment(0)
W
-2

Try: xml/preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen  
  xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">
    <SwitchPreference
        android:defaultValue="true"
        android:key="example_switch"
        android:summary="Turn this option on or off"
        android:title="Settings option" />
</PreferenceScreen>

I also prefer using a preference fragment, hosted by my activity.

class MySettingsActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportFragmentManager
                .beginTransaction()
                .replace(R.id.settings_container, SettingsFragment())
                .commit()
    }
}
class SettingsFragment : PreferenceFragmentCompat() {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.preferences, rootKey)
    }
}
Worker answered 12/8, 2019 at 19:6 Comment(1)
The question asked for a solution in Java, and not kotlinGussiegussman

© 2022 - 2024 — McMap. All rights reserved.