Evento onclick de preferencias de Android

111

En mis preferencias.xml tengo un elemento de preferencia como este:

<Preference android:title="About" />

Quiero asignar un onClickevento, por lo que si el usuario hace clic en él, podría abrir un nuevo Intento un navegador. Traté de hacerlo como lo hago con los botones, pero no parece funcionar.

Badr Hari
fuente

Respuestas:

230

Badr,

Debe configurar android:keyel artículo, luego en su código puede hacer ...

Suponiendo que usa lo siguiente en su XML:

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

Entonces puedes hacer lo siguiente en tu código:

Preference myPref = (Preference) findPreference("myKey");
myPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
             public boolean onPreferenceClick(Preference preference) {
                 //open browser or intent here
                 return true;
             }
         });
Will Tate
fuente
3
¿Dónde debo colocar esto? en mi SettingsActivity en onPostCreateno funcionará porque es demasiado pronto (Nullpointer-Exception). Se agradece cualquier ayuda
Wandang
1
findPreferencees obsoleto.
zackygaurav
6
PreferenceActivity.findPreferencees obsoleto. Sin embargo, la documentación dice "[E] sta funcionalidad ahora debería encontrarse en la nueva clase PreferenceFragment. Si está utilizando PreferenceActivity en su modo anterior, la documentación se aplica a las API obsoletas aquí", y PreferenceFragment.findPreferenceno está obsoleta (a partir de API nivel 23, actual en el momento de escribir este artículo). Entonces, en findPreferencesí mismo no está desaprobado; es el uso directo del PreferenceActivityque está en desuso. Google quiere que nos PreferenceFragmentmudemos, no que abandonemos findPreference.
Mike Playle
En onPreferenceClick, regrese truesi el clic se manejó de otra manera false.
Thupten
Esto me funciona con PreferenceFragmentCompatDividers.
Joseph Lam
59

para lanzar un sitio web:

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

para lanzar una actividad específica:

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

también puede usar "android: mimetype" para configurar el mimetype.

Jason Gilbert
fuente
1
Estoy de acuerdo, este enfoque es mejor, especialmente porque no usa el método findPreference (String key) ahora obsoleto y porque es más limpio en general.
lyallcooper
Muy bien, pero ¿también es posible crear un IntentChooser de esta manera?
Peterdk
@jasongilbert ¿Es posible enviar una transmisión con ACCIÓN en lugar de iniciar la actividad desde el clic de preferencia?
Sazzad Hissain Khan
1
@jasongilbert ¿Debo especificar alguno intent-filteren el manifiesto para el SomeActivity, porque estoy obteniendo ActivityNotFoundException:(
theapache64
11

Debe utilizar el evento onPreferenceTreeClick.

Por ejemplo, consulte 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
fuente
El enlace es 404
JZAU
6

ACTUALIZACIÓN 2018+ Hoy, el findPreferencemétodo está depurado. Entonces, para lograr esto, simplemente anule el onPreferenceTreeClickmétodo en su fragmento de Preferencia. Por ejemplo:

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;
    }
}

Además, si necesita manejar un clic dentro de un elemento de preferencia particular (por ejemplo ListPreference), debe registrar setOnPreferenceChangeListenerel onCreatemétodo dentro del 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
fuente
¿Cuál es la diferencia entre onPreferenceClicky onPreferenceTreeClick ?
Yousha Aleayoub
3

Un seguimiento de la respuesta de @jason gilbert

Estoy en targetSdkVersion 25 y su respuesta no funcionó, tuve que envolver la etiqueta de intención con una etiqueta de preferencia. Ejemplo:

<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
fuente