Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: launch a custom Preference from a PreferenceActivity

I would like to be able launch a 2nd Preference screen from my PreferenceActivity. And in the 2nd Preference screen I'd like to use a predefined layout from xml. So, I have two questions:

How do I use an xml layout as the layout view of a Preference? How do I add this custom preference to a PreferenceActivity such that launched when tapped?

Thank you

*EDIT in response to alibi

I am trying to launch an activity from a preference screen, by declaring the activity to be launched in xml. This causes this exception:

 04-01 19:04:37.962: ERROR/AndroidRuntime(8061): android.content.ActivityNotFoundException: Unable to find explicit activity class {com.me/CustomPrefScreen}; have you declared this activity in your AndroidManifest.xml?

*Another update. However, if I replace PrefrenceScreen in settings.xml with some extension of Preference, which overrides onClick() to launch CustomPrefScreen, then everything works fine.

Main preferences activity:

public class MyPreferences extends PreferenceActivity 
{
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.settings);
    }
}

settings.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceScreen  
        android:summary="my summary" 
        android:title="my title">
        <intent android:action="android.intent.action.MAIN"
                    android:targetPackage="com.me"
                    android:targetClass="CustomPrefScreen"/>
    </PreferenceScreen>

</PreferenceScreen>

mainfest file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.me"
    android:versionCode="1"
    android:versionName="1.0">
    <application 
        android:icon="@drawable/icon" 
        android:label="@string/app_name" 
        android:theme="@style/Theme.NoBackground">
        <activity 
            android:name=".MyApp"
            android:label="@string/app_name">
            <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
             </activity>
        <activity 
            android:name=".CustomPrefScreen"
            android:label="@string/app_name">
        </activity>
        <activity 
            android:name=".MyPreferences"
            android:label="@string/app_name">
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="4" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest> 
like image 799
ab11 Avatar asked Apr 01 '11 16:04

ab11


People also ask

How do I use preference fragments?

Use PreferenceFragmentCompat to programatically handle preferences. To load the settings into the fragment, load the preferences in the onCreatePreferences() method. To get an instance of a preference, search for a preference using its key through the PreferenceManager within onCreateView() .

How do I get to preferences in Android Studio?

From the menu bar, click File > Settings (on macOS, click Android Studio > Preferences).

What is PreferenceFragmentCompat?

A PreferenceFragmentCompat is the entry point to using the Preference library. This Fragment displays a hierarchy of Preference objects to the user. It also handles persisting values to the device. To retrieve an instance of android.


2 Answers

One solution would be to extend a DialogPreference which allows the setting of a custom layout for the preference dialog. This way you have a preference listed and when you tap it, you get a dialog with your custom settings UI.

 <com.xyz.MyPreference 
           android:dialogLayout="@layout/yourlayout"
           android:dialogTitle="Dialog Title"
            android:dialogMessage="Dialog summary"
            android:key="preference_key"
            android:title="Preference Title"
            android:summary="Preference summary"
            android:defaultValue="Default Value" /> 

And the class

class MyPreference extends DialogPreference {
// along with constructors, you will want to override
    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);
        // view is your layout expanded and added to the dialog
            // find and hang on to your views here, add click listeners etc
            // basically things you would do in onCreate
        mTextView = (TextView)view.findViewById(R.Id.mytextview);
        }

        @Override
        protected void onDialogClosed(boolean positiveResult) {
           super.onDialogClosed(positiveResult);

            if (positiveResult) {
                // deal with persisting your values here
            }
        }
}

Obviously there are some other details, but this is the basic idea.

like image 143
slund Avatar answered Oct 07 '22 17:10

slund


alibi's solution - of defining an intent within a <PreferenceScreen> entry - worked for me, after much trial-and-error of the targetPackage and targetClass fields.

targetPackage needs to be the full path to the package name of my application (that is, the package= entry in the AndroidManifest.xml file). targetClass needs to be the full path to the Activity - INCLUDING the package name, even if the Activity is in the same package as the Application.

The AndroidManifest.xml file for the Application also (of course) needs an entry for the Activity. I didn't define an <intent-filter> for this entry, presumably because the action is MAIN (this was true whether the Activity was in the same or a different package than the Application).

Example: the Application's package is com.thissocialworld. The Activity I'd like to kick off from the PreferencesScreen is in a package called com.coolcommon and the Activity class is com.thissocialworld.SpecialPreferences. The entry within the <PreferenceScreen> looks like this:

<intent android:action="android.intent.action.MAIN"
 android:targetPackage="com.thissocialworld"
 android:targetClass="com.thissocialworld.SpecialPreferences"/>

I may try changing action.MAIN to action.PREFERENCES if it seems to be necessary to get access to the PreferencesManager.

(PS my first post here, I couldn't figure out how to post this as a comment to the discussion started by alibi.)

like image 30
SR Austin Avatar answered Oct 07 '22 17:10

SR Austin