Événement onclick des préférences Android

111

Dans mon preferences.xml, j'ai un élément de préférence comme celui-ci:

<Preference android:title="About" />

Je veux attribuer un onClickévénement, donc si l'utilisateur clique dessus, je pourrai ouvrir un nouveau Intentnavigateur ou un nouveau navigateur. J'ai essayé de le faire comme je le fais avec des boutons, mais cela ne semble pas fonctionner.

Badr Hari
la source

Réponses:

230

Badr,

Vous devez définir android:key pour l'élément, puis dans votre code, vous pouvez faire ...

En supposant que vous utilisez ce qui suit dans votre XML:

<Preference android:title="About" android:key="myKey"></Preference>

Ensuite, vous pouvez effectuer les opérations suivantes dans votre code:

Preference myPref = (Preference) findPreference("myKey");
myPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
             public boolean onPreferenceClick(Preference preference) {
                 //open browser or intent here
                 return true;
             }
         });
Will Tate
la source
3
Où dois-je placer cela? dans mon SettingsActivity dans onPostCreatene fonctionnera pas car il est trop tôt (Nullpointer-Exception). Toute aide est appréciée
Wandang
1
findPreferenceest obsolète.
zackygaurav
6
PreferenceActivity.findPreferenceest obsolète. Cependant, la documentation indique que «[T] sa fonctionnalité doit maintenant être trouvée dans la nouvelle classe PreferenceFragment. Si vous utilisez PreferenceActivity dans son ancien mode, la documentation s'applique aux API obsolètes ici.», Et PreferenceFragment.findPreferencen'est pas obsolète (à partir de l'API niveau 23, actuel au moment de la rédaction). Donc, findPreferencelui-même n'est pas obsolète; c'est l'utilisation directe PreferenceActivityqui est déconseillée. Google veut que nous passions à la PreferenceFragmentplace et non à l'abandon findPreference.
Mike Playle
Dans onPreferenceClick, retourne truesi le clic a été géré autrement false.
Jeudi
Cela fonctionne pour moi avec PreferenceFragmentCompatDividers.
Joseph Lam
59

pour lancer un site Web:

<PreferenceScreen android:title="website">
    <intent
        android:action="android.intent.action.VIEW"
        android:data="http://www.example.com"
        />
</PreferenceScreen>

pour lancer une activité spécifique:

<PreferenceScreen android:title="something">
    <intent
        android:action="android.intent.action.MAIN"
        android:targetPackage="com.example.foo"
        android:targetClass="com.example.foo.SomeActivity"
        />
</PreferenceScreen>

vous pouvez également utiliser "android: mimetype" pour définir le type MIME.

jason gilbert
la source
1
Je suis d'accord, cette approche est meilleure, en particulier parce qu'elle n'utilise pas la méthode maintenant obsolète findPreference (String key) et parce qu'elle est juste plus propre dans l'ensemble.
lyallcooper
Très bien, mais est-il également possible de créer un IntentChooser de cette façon?
Peterdk
@jasongilbert Est-il possible d'envoyer une diffusion avec ACTION plutôt que de démarrer l'activité à partir d'un clic de préférence?
Sazzad Hissain Khan
1
@jasongilbert Dois-je en spécifier intent-filterdans le manifeste pour le SomeActivity, parce que je reçois ActivityNotFoundException:(
theapache64
11

Vous devez utiliser l'événement onPreferenceTreeClick.

Par exemple, voir http://www.javased.com/index.php?source_dir=platform_packages_apps_phone/src/com/android/phone/MobileNetworkSettings.java

 @Override 
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 
        /** TODO: Refactor and get rid of the if's using subclasses */ 
        if (mGsmUmtsOptions != null && 
                mGsmUmtsOptions.preferenceTreeClick(preference) == true) { 
            return true; 
        } else if (mCdmaOptions != null && 
                   mCdmaOptions.preferenceTreeClick(preference) == true) { 
            if (Boolean.parseBoolean( 
                    SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) { 

                mClickedPreference = preference; 

                // In ECM mode launch ECM app dialog 
                startActivityForResult( 
                    new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null), 
                    REQUEST_CODE_EXIT_ECM); 
            } 
            return true; 
        } else if (preference == mButtonPreferredNetworkMode) { 
            //displays the value taken from the Settings.System 
            int settingsNetworkMode = android.provider.Settings.Secure.getInt(mPhone.getContext(). 
                    getContentResolver(), android.provider.Settings.Secure.PREFERRED_NETWORK_MODE, 
                    preferredNetworkMode); 
            mButtonPreferredNetworkMode.setValue(Integer.toString(settingsNetworkMode)); 
            return true; 
        } else if (preference == mButtonDataRoam) { 
            if (DBG) log("onPreferenceTreeClick: preference == mButtonDataRoam."); 

            //normally called on the toggle click 
            if (mButtonDataRoam.isChecked()) { 
                // First confirm with a warning dialog about charges 
                mOkClicked = false; 
                new AlertDialog.Builder(this).setMessage( 
                        getResources().getString(R.string.roaming_warning)) 
                        .setTitle(android.R.string.dialog_alert_title) 
                        .setIconAttribute(android.R.attr.alertDialogIcon) 
                        .setPositiveButton(android.R.string.yes, this) 
                        .setNegativeButton(android.R.string.no, this) 
                        .show() 
                        .setOnDismissListener(this); 
            } else { 
                mPhone.setDataRoamingEnabled(false); 
            } 
            return true; 
        } else if (preference == mButtonDataEnabled) { 
            if (DBG) log("onPreferenceTreeClick: preference == mButtonDataEnabled."); 
            ConnectivityManager cm = 
                    (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 

            cm.setMobileDataEnabled(mButtonDataEnabled.isChecked()); 
            return true; 
        } else if (preference == mLteDataServicePref) { 
            String tmpl = android.provider.Settings.Secure.getString(getContentResolver(), 
                        android.provider.Settings.Secure.SETUP_PREPAID_DATA_SERVICE_URL); 
            if (!TextUtils.isEmpty(tmpl)) { 
                TelephonyManager tm = (TelephonyManager) getSystemService( 
                        Context.TELEPHONY_SERVICE); 
                String imsi = tm.getSubscriberId(); 
                if (imsi == null) { 
                    imsi = ""; 
                } 
                final String url = TextUtils.isEmpty(tmpl) ? null 
                        : TextUtils.expandTemplate(tmpl, imsi).toString(); 
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 
                startActivity(intent); 
            } else { 
                android.util.Log.e(LOG_TAG, "Missing SETUP_PREPAID_DATA_SERVICE_URL"); 
            } 
            return true; 
        } else { 
            // if the button is anything but the simple toggle preference, 
            // we'll need to disable all preferences to reject all click 
            // events until the sub-activity's UI comes up. 
            preferenceScreen.setEnabled(false); 
            // Let the intents be launched by the Preference manager 
            return false; 
        } 
    } 
Pentium10
la source
Le lien est 404
JZAU
6

MISE À JOUR 2018+ Aujourd'hui, la findPreferenceméthode est obsolète. Donc, pour y parvenir, remplacez simplement la onPreferenceTreeClickméthode dans votre fragment de préférence. Par exemple:

public class MySettingsFragment extends PreferenceFragment {

    @Override
    public boolean onPreferenceTreeClick (PreferenceScreen preferenceScreen,
                                          Preference preference)
    {
        String key = preference.getKey();
        if(key.equals("someKey")){
            // do your work
            return true;
        }
        return false;
    }
}

De plus, si vous devez gérer un clic à l'intérieur d'un élément de préférence particulier (par exemple ListPreference), vous devez enregistrer l' setOnPreferenceChangeListenerintérieur de la onCreateméthode du MySettingsFragment:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Load the preferences from an XML resource
    addPreferencesFromResource(R.xml.preferences);

    // register listener
    final Preference prefList = findPreference("key");
    prefList.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        public boolean onPreferenceChange(Preference preference, Object value) {
            System.out.println("Selected: " + value);
            return true;
        }
    });
}
Akelec
la source
Quelle est la différence entre onPreferenceClicket onPreferenceTreeClick ?
Yousha Aleayoub
3

Un suivi sur la réponse de @jason gilbert

Je suis sur targetSdkVersion 25 , et sa réponse n'a pas fonctionné, j'ai dû envelopper la balise d'intention avec une balise Preference. Exemple:

<PreferenceScreen android:title="something">
    <Preference title="Title">
       <intent
       android:action="android.intent.action.MAIN"
       android:targetPackage="com.example.foo"
       android:targetClass="com.example.foo.SomeActivity"
       />
    </Preference>
</PreferenceScreen>
Malek Hijazi
la source