2011-04-01 15 views
10

Me gustaría poder lanzar una segunda pantalla de preferencias desde mi actividad de preferencia. Y en la pantalla 2nd Preference me gustaría usar un diseño predefinido de xml. Entonces, tengo dos preguntas:Android: lanzar una preferencia personalizada desde una actividad de preferencia

¿Cómo uso un diseño xml como la vista de diseño de una preferencia? ¿Cómo agrego esta preferencia personalizada a una actividad de preferencia tal que se inició cuando se tocó?

Gracias

* EDITAR en respuesta a ALibi

Estoy tratando de poner en marcha una actividad de una pantalla de preferencias, al declarar la actividad que será lanzado en XML. Esto causa esta excepción:

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? 

* Otra actualización. Sin embargo, si reemplazo PrefrenceScreen en settings.xml con alguna extensión de Preference, que anula onClick() para iniciar CustomPrefScreen, todo funciona bien. actividad

principales preferencias:

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> 

archivo mainfest

<?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> 
+1

Ambas cosas están bien explicado en el ejemplo Api Demos. Lo curioso es que está en el directorio SDK, por lo tanto, tiene los ejemplos en su disco duro en este momento. – Cristian

+0

¿Necesitas absolutamente las otras preferencias para ser una segunda actividad? Si solo quieres más de una pantalla, ¿tal vez simplemente usar una pantalla PreferenceScreen? – slund

+0

@Slund. Me gustaría usar PreferenceScreen, pero no estoy seguro de cómo usar un diseño xml personalizado para él; parece que solo se pueden agregar vistas de tipo Preferencia? – ab11

Respuesta

18

Una solución sería la de extender un DialogPreference que permite la fijación de un diseño personalizado para el diálogo de preferencia. De esta manera, tiene una preferencia en la lista y cuando la toca, obtiene un diálogo con la interfaz de usuario de configuración personalizada.

<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" /> 

Y la clase

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

Obviamente hay algunos otros detalles, pero esta es la idea básica.

+0

Consideré esto, pero realmente no quiero extender DialogPreference. No quiero los botones "Aceptar" y "Cancelar", ni el estilo de diálogo. Me gustaría que la preferencia personalizada tenga un estilo similar al de la actividad de preferencia que lo lanzó. – ab11

+0

Bueno, podrías hacer lo mismo con Preference y establecer android: layout para que la preferencia sea tu diseño xml. De esta forma, su diseño se muestra en la pantalla de preferencias. También puede anular la porción del widget con android: widgetLayout. Luego escuchas onBindView para adjuntar listeners a tus controles. – slund

+0

No es difícil, pero ... Si agrego una pantalla de preferencia a mi actividad de preferencia principal y luego configuro el diseño de esa pantalla de preferencia, el diseño personalizado se muestra dentro de la actividad de preferencia principal, y el título y el resumen de PreferenceScreen no se muestran. Preferiría mostrar el título y el resumen, y el diseño personalizado para mostrar en una nueva ventana, cuando se toca la preferencia. – ab11

0

Puede usar una actividad personalizada para esto. Simplemente diseñe la actividad e inclúyala como PreferenceScreen en sus preferencias.

<PreferenceScreen android:summary="@string/pref_summary" android:title="@string/title_summary"> 
    <intent android:action="android.intent.action.MAIN" 
    android:targetPackage="targetPackage" 
    android:targetClass="targetClass"/> 
</PreferenceScreen> 

¡No olvide registrar su actividad en el manifiesto!

+0

Gracias, esto tiene sentido. Sin embargo, falla con la siguiente excepción, aunque estoy absolutamente seguro de haber registrado la actividad en mi manifiesto. ¿Alguna idea de por qué? "android.content.ActivityNotFoundException: no se puede encontrar la clase de actividad explícita {com.me.CustomPreference}; ¿ha declarado esta actividad en su AndroidManifest.xml?" – ab11

+0

¿Puedes publicar el manifiesto? – alibi

+0

Lo agregué como una edición en mi publicación original. – ab11

5

Es posible que desee algo similar a lo que hice para cargar una foto de la galería o la cámara. solución

package com.atClass.lmt; 
import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.ContentValues; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.net.Uri; 
import android.os.Bundle; 
import android.preference.PreferenceActivity; 
import android.preference.Preference; 
import android.preference.Preference.OnPreferenceClickListener; 
import android.provider.MediaStore; 
import android.util.Log; 


public class Prefs extends PreferenceActivity{ 
    //public static final int FLAG_ACTIVITY_CLEAR_TOP = 1; 
    private static final int MEDIA_IMAGE_REQUEST_CODE = 1; 
    private static final int CAMERA_IMAGE_REQUEST_CODE = 2; 
    public static Uri cImageUri; 

    public static Context cContext; 
    public static Activity cActivity; 

    @Override 
    protected void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
     addPreferencesFromResource(R.xml.settings); 

     this.cContext = (Context)this; 
     this.cActivity = (Activity)this; 

     Preference customPref = (Preference) findPreference("user_display_picture"); 
     customPref.setOnPreferenceClickListener(
       new OnPreferenceClickListener() { 
        public boolean onPreferenceClick(Preference preference) { 
         return imageUploadDialog(); 
        } 
       }); 
    } 

    protected void onStop(){ 
     super.onStop(); 
     MapTools.createMapView(false); 
     Lmt.serviceBinder.serviceThread("loginDevice"); 
    } 

    public boolean imageUploadDialog(){ 
     final CharSequence[] items = {"Take picture now","Upload from gallery"}; 
     AlertDialog.Builder lAlertDialog = new AlertDialog.Builder(cContext); 
     lAlertDialog.setTitle("Upload action"); 
     lAlertDialog.setCancelable(true); 
     lAlertDialog.setItems(items, 
       new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialogInterface, int i){ 
       //Toast.makeText(getApplicationContext(), "Selected item: " +i, Toast.LENGTH_SHORT).show(); 
       if (i == 0){ 
        attachCameraImage(); 
       } 
       if (i == 1){ 
        attachGalleryImage(); 
       } 
      } 
     }); 
     lAlertDialog.setIcon(R.drawable.click_to_url); 
     lAlertDialog.show(); 
     return true; 
    } 

    public void attachGalleryImage(){ 
     Intent getImageFromGalleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI); 
     startActivityForResult(getImageFromGalleryIntent, MEDIA_IMAGE_REQUEST_CODE); 
    } 

    public void attachCameraImage(){ 
     String fileName = "testphoto.jpg"; 
     ContentValues values = new ContentValues(); 
     values.put(MediaStore.Images.Media.TITLE, fileName); 
     values.put(MediaStore.Images.Media.DESCRIPTION,"Image capture by camera"); 
     values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); 
     cImageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 
     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
     intent.putExtra(MediaStore.EXTRA_OUTPUT, cImageUri); 
     intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); 
     startActivityForResult(intent, CAMERA_IMAGE_REQUEST_CODE); 
    } 

    protected final void onActivityResult(final int requestCode, final int resultCode, final Intent i) { 
     Log.d(Global.TAG,"--> Received callback with:" + resultCode); 
     super.onActivityResult(requestCode, resultCode, i); 
     if(resultCode == RESULT_OK) { 
      Log.d(Global.TAG,"--> Result OK with:" + requestCode); 
      switch(requestCode) { 
      case MEDIA_IMAGE_REQUEST_CODE: 
       Log.d(Global.TAG,"--> MEDIA_IMAGE_REQUEST_CODE"); 
       Gui.GuiProgressDialog.showLoadingSpinner(cActivity); 
       cImageUri = i.getData(); 
       if (cImageUri == null){Log.d(Global.TAG,"--> ImageURI is null!");} 
       Lmt.serviceBinder.serviceThread("uploadMemberPicture"); 
       break; 
      case CAMERA_IMAGE_REQUEST_CODE: 
       Log.d(Global.TAG,"--> CAMERA_IMAGE_REQUEST_CODE"); 
       //cImageUri = i.getData(); 
       if (cImageUri == null){Log.d(Global.TAG,"--> ImageURI is null!");} 
       Lmt.serviceBinder.serviceThread("uploadMemberPicture"); 
       break; 
      } 
     } 
    } 
} 
7

de coartada - de definir una intención dentro de una entrada de <PreferenceScreen> - trabajó para mí, después de mucho ensayo y error de los campos targetPackage y targetClass.

targetPackage debe ser la ruta completa al nombre del paquete de mi aplicación (es decir, la entrada package= en el archivo AndroidManifest.xml). targetClass debe ser la ruta completa a la Actividad, INCLUYENDO el nombre del paquete, incluso si la Actividad está en el mismo paquete que la Aplicación.

El archivo AndroidManifest.xml para la Aplicación también (por supuesto) necesita una entrada para la Actividad.No definí un <intent-filter> para esta entrada, presumiblemente porque el action es MAIN (esto era cierto si la Actividad estaba en el mismo paquete o en un paquete diferente que la Aplicación).

Ejemplo: el paquete de la aplicación es com.thissocialworld. La actividad que me gustaría iniciar desde el PreferencesScreen se encuentra en un paquete llamado com.coolcommon y la clase de actividad es com.thissocialworld.SpecialPreferences. La entrada en el <PreferenceScreen> se ve así:

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

que puede intentar cambiar a action.MAINaction.PREFERENCES si parece ser necesario para obtener acceso a la PreferencesManager.

(PS mi primer post aquí, no podía encontrar la manera de enviar esto como un comentario a la discusión iniciada por coartada.)

+0

¡buen trabajo, gracias! –

Cuestiones relacionadas