2011-04-01 78 views
10

我想从我的PreferenceActivity启动第二首选项屏幕。在第二个首选项屏幕中,我想使用xml中的预定义布局。所以,我有两个问题:Android:从PreferenceActivity启动自定义首选项

如何使用xml布局作为首选项的布局视图? 如何将此自定义首选项添加到PreferenceActivity,以便点击时启动?

谢谢

*编辑回应托辞

我试图从偏好屏幕启动的活动,宣称在XML要启动的活动。这导致此例外:

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? 

*另一个更新。但是,如果我将settings.xml中的PrefrenceScreen替换为Preference的一些扩展,这会覆盖onClick()以启动CustomPrefScreen,那么一切正常。

主要偏好活性:

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文件

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

两件事在API演示例子是很好的解释。有趣的是它在SDK目录中,因此你现在在你的硬盘中有例子。 – Cristian 2011-04-01 16:18:06

+0

你是否绝对需要其他喜好来成为第二个活动?如果您只想使用PreferenceScreen工作,可能需要多个屏幕? – slund 2011-04-01 16:34:19

+0

@Slund。我想使用PreferenceScreen,但我不确定如何使用自定义xml布局;似乎只有偏好类型的意见可以添加到它? – ab11 2011-04-01 16:49:42

回答

18

一种解决方案将是扩展一个DialogPreference其允许自定义布局的设置为首选对话框。通过这种方式,您可以列出一个首选项,当您点击它时,您将获得一个包含您的自定义设置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" /> 

和类

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

显然还有其他一些细节,但是这是基本的想法。

+0

我考虑过这个,但真的不想扩展DialogPreference。我不想要“ok”和“cancel”按钮,也不需要对话框样式。我希望自定义首选项具有与启动它的PreferenceActivity类似的样式。 – ab11 2011-04-01 17:31:12

+0

那么你可以用Preference做同样的事情,并将android:layout设置为你的xml布局。这样您的布局显示在首选项屏幕上。你也可以用android:widgetLayout覆盖widget部分。然后,您在onBindView上监听以将监听器附加到您的控件。 – slund 2011-04-01 17:50:05

+0

不难,但..如果我将PreferenceScreen添加到主PreferenceActivity,然后设置PreferenceScreen的布局,则自定义布局显示在主PreferenceActivity中,并且不显示PreferenceScreen标题和摘要。我更喜欢显示的标题和摘要,以及在点击首选项时显示在新窗口中的自定义布局。 – ab11 2011-04-01 18:19:06

0

您可以为此使用自定义活动。只需设计活动并将其作为PreferenceScreen包含在您的偏好中即可。

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

不要忘记注册您的活动清单!

+0

谢谢,这是有道理的。然而,即使我绝对肯定我在我的清单中注册了该活动,它也会失败,并具有以下例外情况。任何想法为什么? “android.content.ActivityNotFoundException:无法找到显式活动类{com.me.CustomPreference};你是否在你的AndroidManifest.xml中声明了这个活动?” – ab11 2011-04-01 17:53:24

+0

你可以发布清单吗? – alibi 2011-04-01 18:51:57

+0

我在原始文章中添加了它作为编辑。 – ab11 2011-04-01 19:09:52

5

您可能想要类似于我从画廊或相机上传照片的操作。

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

不在场证明的解决方案 - 定义<PreferenceScreen>条目内的意图 - 为我工作,后targetPackagetargetClass领域的许多试验和错误。

targetPackage需要是我的应用程序的软件包名称(即AndroidManifest.xml文件中的package=条目)的完整路径。 targetClass需要是活动的完整路径 - 包括软件包名称,即使活动与应用程序在同一个软件包中。

应用程序的AndroidManifest.xml文件(当然)需要一个活动条目。我没有为此条目定义<intent-filter>,大概是因为actionMAIN(无论Activity是否与应用程序位于相同或不同的包中,情况都是如此)。

例如:应用程序的包是com.thissocialworld。我想从PreferencesScreen开始的活动是名为com.coolcommon的套餐,活动类别为com.thissocialworld.SpecialPreferences。在<PreferenceScreen>中的条目是这样的:

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

我可能会尝试改变action.MAINaction.PREFERENCES如果它似乎有必要获得访问PreferencesManager

(PS我在这里的第一篇文章,我无法弄清楚如何发布此作为由托辞开始讨论的一个注释。)

+0

不错,谢谢! – 2016-04-19 13:17:44

相关问题