2013-02-01 28 views
21

我正在使用偏好标题创建使用PreferenceActivity的设置活动。我试图划分标题变为类别/组,像这样的(有类别的无线网络&,设备,个人,...):如何在Android PreferenceActivity中创建偏好标题组?

无论如何,即使是Android开发者网站是关于这种创建偏好活动的方式,我无法找到任何方式来创建像它们在图像上一样的偏好活动。我设法做的只是简单的首选项标题列表。

我发现的唯一的事情是this,但是它的工作原理挺奇怪。所以这似乎不是一种选择。

所以我的问题是:如何创建PreferenceActivity使用偏好标题可能将头分为不同的类别和使用主开关的可能性?

我的一些代码:

preference_headers.xml

<?xml version="1.0" encoding="utf-8"?> 
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> 
    <header 
     android:fragment="cz.vse.myevents.activity.SettingsActivity$EventsFragment" 
     android:title="@string/settings_events" 
     android:icon="@android:drawable/ic_menu_agenda" /> 
    <header 
     android:fragment="cz.vse.myevents.activity.SettingsActivity$OrganizationsFragment" 
     android:title="@string/settings_subscribed_organizations" 
     android:icon="@android:drawable/ic_menu_view" /> 
</preference-headers> 

SettingsActivity

@Override 
public void onBuildHeaders(List<Header> target) { 
    super.onBuildHeaders(target); 
    loadHeadersFromResource(R.xml.preference_headers, target); 
} 

我不张贴片段资源,认为这是不必要的。

回答

5

似乎最好的解决方案是创建三个不同的代码块 - 一个用于Honeycomb之前,一个用于Honeycomb之后,另一个用于平板电脑。

首选项标头的使用仅在平板电脑上有效,因此它们仅保留在平板电脑上。这里没有使用分组。

后蜂窝上的首选标题有点没用,所以最好的是使用典型的PreferenceScreenPreferenceFragment。团体可以通过PreferenceCategory轻松制作。

最后,对于预蜂窝,不使用PrefrenceFragment的弃用方式是唯一的方法。

不幸的是有很多代码重复,但在Leandros的答案中提到的UnifiedPreference库是buggy - 它完全忽略了PreferenceFragment,所以它是无用的(至少对我来说)。

+0

请参阅我的答案http://stackoverflow.com/a/20806812/1139784关于减少一些代码重复。 –

6

我认为你在Xavier Gouchet的site找到的是我们必须这样做的方式。我查看了Android设置应用程序的源代码,以及Gouchet提取的this is。我调整它为我的目的(留出声音使能开关),并获得与分隔线类别标题。

我希望Android API的设置将被增强以支持类别很快。它不应该是这个困难。

+1

一年多后,仍然没有。似乎有点荒谬,基本设置屏幕,每个人都看到了没有简单的方法来添加类别。 – Mgamerz

+0

死链接,答案没有提供真实的信息。 –

-1

AOSP settings_headers.xml实现:

<preference-headers 
     xmlns:android="http://schemas.android.com/apk/res/android"> 


    <!-- WIRELESS and NETWORKS --> 
    <header android:title="@string/header_category_wireless_networks" /> 

    <!-- Wifi --> 
    <header 
     android:id="@+id/wifi_settings" 
     android:fragment="com.android.settings.wifi.WifiSettings" 
     android:title="@string/wifi_settings_title" 
     android:icon="@drawable/ic_settings_wireless" /> 

    <!-- Bluetooth --> 
    <header 
     android:id="@+id/bluetooth_settings" 
     android:fragment="com.android.settings.bluetooth.BluetoothSettings" 
     android:title="@string/bluetooth_settings_title" 
     android:icon="@drawable/ic_settings_bluetooth2" /> 

    <!-- Data Usage --> 
    <header 
     android:id="@+id/data_usage_settings" 
     android:fragment="com.android.settings.DataUsageSummary" 
     android:title="@string/data_usage_summary_title" 
     android:icon="@drawable/ic_settings_data_usage" /> 

    <!-- Operator hook --> 
    <header 
     android:fragment="com.android.settings.WirelessSettings" 
     android:id="@+id/operator_settings"> 
     <intent android:action="com.android.settings.OPERATOR_APPLICATION_SETTING" /> 
    </header> 

    <!-- Other wireless and network controls --> 
    <header 
     android:id="@+id/wireless_settings" 
     android:title="@string/radio_controls_title" 
     android:breadCrumbTitle="@string/wireless_networks_settings_title" 
     android:fragment="com.android.settings.WirelessSettings" 
     android:icon="@drawable/empty_icon" /> 

    <!-- Ethernet --> 
    <header 
     android:id="@+id/ethernet_settings" 
     android:title="@string/eth_radio_ctrl_title" 
     android:icon="@drawable/ic_settings_ethernet" 
     android:fragment="com.android.settings.ethernet.EthernetSettings"/> 

    <!-- DEVICE --> 
    <header android:title="@string/header_category_device" /> 

    <!-- Sound --> 
    <header 
     android:id="@+id/sound_settings" 
     android:icon="@drawable/ic_settings_sound" 
     android:fragment="com.android.settings.SoundSettings" 
     android:title="@string/sound_settings" /> 

    <!-- Display --> 
    <header 
     android:id="@+id/display_settings" 
     android:icon="@drawable/ic_settings_display" 
     android:fragment="com.android.settings.DisplaySettings" 
     android:title="@string/display_settings" /> 

    <!-- Storage --> 
    <header 
     android:id="@+id/storage_settings" 
     android:fragment="com.android.settings.deviceinfo.Memory" 
     android:icon="@drawable/ic_settings_storage" 
     android:title="@string/storage_settings" /> 

    <!-- Battery --> 
    <header 
     android:id="@+id/battery_settings" 
     android:fragment="com.android.settings.fuelgauge.PowerUsageSummary" 
     android:icon="@drawable/ic_settings_battery" 
     android:title="@string/power_usage_summary_title" /> 

    <!-- Application Settings --> 
    <header 
     android:fragment="com.android.settings.applications.ManageApplications" 
     android:icon="@drawable/ic_settings_applications" 
     android:title="@string/applications_settings" 
     android:id="@+id/application_settings" /> 

    <!-- TEMPORARY FACTORY STARTER WILL BE REMOVED WITH UPDATED SETTINGS --> 
    <header 
     android:icon="@drawable/ic_settings_applications" 
     android:title="Factory" 
     android:id="@+id/application_settings" > 
     <intent android:action="android.intent.action.MAIN" 
       android:targetPackage="com.jamdeo.tv.sample.factory" 
       android:targetClass="com.jamdeo.tv.sample.factory.TvFactoryMainActivity" /> 
    </header> 

    <!-- Manufacturer hook --> 
    <header 
     android:fragment="com.android.settings.WirelessSettings" 
     android:id="@+id/manufacturer_settings"> 
     <intent android:action="com.android.settings.MANUFACTURER_APPLICATION_SETTING" /> 
    </header> 


    <!-- PERSONAL --> 
    <header android:title="@string/header_category_personal" /> 

    <!-- Data Sync. The settings activity will ensure this is resolved to an 
     activity on the system image, otherwise it will remove this 
     preference. --> 
    <header 
     android:fragment="com.android.settings.accounts.ManageAccountsSettings" 
     android:icon="@drawable/ic_settings_sync" 
     android:title="@string/sync_settings" 
     android:id="@+id/sync_settings" /> 

    <!-- Location --> 
    <header 
     android:fragment="com.android.settings.LocationSettings" 
     android:icon="@drawable/ic_settings_location" 
     android:title="@string/location_settings_title" 
     android:id="@+id/location_settings" /> 

    <!-- Security --> 
    <header 
     android:fragment="com.android.settings.SecuritySettings" 
     android:icon="@drawable/ic_settings_security" 
     android:title="@string/security_settings_title" 
     android:id="@+id/security_settings" /> 

    <!-- Language --> 
    <header 
     android:id="@+id/language_settings" 
     android:fragment="com.android.settings.inputmethod.InputMethodAndLanguageSettings" 
     android:icon="@drawable/ic_settings_language" 
     android:title="@string/language_settings" /> 

    <!-- Backup and reset --> 
    <header 
     android:fragment="com.android.settings.PrivacySettings" 
     android:icon="@drawable/ic_settings_backup" 
     android:title="@string/privacy_settings" 
     android:id="@+id/privacy_settings" /> 


    <!-- SYSTEM --> 
    <header android:title="@string/header_category_system" /> 

    <!-- Dock --> 
    <header 
     android:id="@+id/dock_settings" 
     android:fragment="com.android.settings.DockSettings" 
     android:icon="@drawable/ic_settings_dock" 
     android:title="@string/dock_settings" /> 

    <!-- Date & Time --> 
    <header 
     android:id="@+id/date_time_settings" 
     android:fragment="com.android.settings.DateTimeSettings" 
     android:icon="@drawable/ic_settings_date_time" 
     android:title="@string/date_and_time_settings_title" /> 

    <!-- Accessibility feedback --> 
    <header 
     android:id="@+id/accessibility_settings" 
     android:fragment="com.android.settings.AccessibilitySettings" 
     android:icon="@drawable/ic_settings_accessibility" 
     android:title="@string/accessibility_settings" /> 

    <!-- Development --> 
    <header 
     android:id="@+id/development_settings" 
     android:fragment="com.android.settings.DevelopmentSettings" 
     android:icon="@drawable/ic_settings_development" 
     android:title="@string/development_settings_title" /> 

    <!-- About Device --> 
    <header 
     android:id="@+id/about_settings" 
     android:fragment="com.android.settings.DeviceInfoSettings" 
     android:icon="@drawable/ic_settings_about" 
     android:title="@string/about_settings" /> 

</preference-headers> 

只要使用<header>只有android:title属性。

+3

这不起作用 - 只创建另一个不执行任何操作的标题,并且不显示任何组划分。我认为在你的例子中有一些程序性的东西缺失。 – James

+0

我查看了设置活动的源代码,您需要做很多工作才能获得相同的结果。我以代理设置的适配器而结束,并为我的头条返回了不同的视图。 – rekire

+0

正如@詹姆斯所说,它不起作用。不要浪费你的时间。 – tomrozb

7

这是偏好类别的例子,你可以使用偏好类别,并设置各自的片段,并实现这一点,让我知道如果我误解你的情况。

下面是示例布局

<PreferenceCategory android:title="Heading1"> 
     <Preference 
      android:title="title1" 
      android:summary="summary1" 
      android:key="keyName"/> 

     <Preference 
      android:title="title2" 
      android:summary="summary2" 
      android:key="keyName"/> 
</PreferenceCategory> 

<PreferenceCategory android:title="Heading2"> 
     <Preference 
      android:title="title3" 
      android:summary="summary3" 
      android:key="keyName"/> 
</PreferenceCategory> 
+0

这会在片段(属性窗格)内创建标题。问题是关于在标头secion中创建标题(由'loadHeadersFromResource'创建)。 – vbence

2

为了阐述从T. Folsom答案,这里是我的实现:

RES /布局/ preference_header_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:background="?android:attr/activatedBackgroundIndicator" 
    android:baselineAligned="false" 
    android:gravity="center_vertical" 
    android:minHeight="48dp" 
    android:paddingRight="?android:attr/scrollbarSize" > 

    <LinearLayout 
     android:layout_width="@dimen/header_icon_width" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="6dip" 
     android:layout_marginRight="6dip" > 

     <ImageView 
      android:id="@+id/icon" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_gravity="center" /> 
    </LinearLayout> 

    <RelativeLayout 
     android:layout_width="0dip" 
     android:layout_height="wrap_content" 
     android:layout_marginBottom="6dip" 
     android:layout_marginLeft="2dip" 
     android:layout_marginRight="6dip" 
     android:layout_marginTop="6dip" 
     android:layout_weight="1" > 

     <TextView 
      android:id="@+android:id/title" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:ellipsize="marquee" 
      android:fadingEdge="horizontal" 
      android:singleLine="true" 
      android:textAppearance="?android:attr/textAppearanceMedium" /> 

     <TextView 
      android:id="@+android:id/summary" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_below="@android:id/title" 
      android:ellipsize="end" 
      android:maxLines="2" 
      android:textAppearance="?android:attr/textAppearanceSmall" /> 
    </RelativeLayout> 

</LinearLayout> 

RES /价值/ dimens.xml

<resources> 

    <dimen name="header_icon_width">28dp</dimen> 

</resources> 

在PreferenceActivity类:

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    if (savedInstanceState != null) { 
     /* 
     * the headers must be restored before the super call in order 
     * to be ready for the call to setListAdapter() 
     */ 
     if (savedInstanceState.containsKey("headers")) { 
      setHeaders((ArrayList<Header>)savedInstanceState.getSerializable("headers")); 
     } 
    } 

    // as suggest by https://stackoverflow.com/questions/15551673/android-headers-categories-in-preferenceactivity-with-preferencefragment 
    if(onIsMultiPane()) getIntent().putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, PreferencesFragment.class.getName()); 

    super.onCreate(savedInstanceState); 

    ... 

} 

@Override 
protected void onResume() { 
    super.onResume(); 

    // https://stackoverflow.com/questions/15551673/android-headers-categories-in-preferenceactivity-with-preferencefragment 
    // Select the displayed fragment in the headers (when using a tablet) : 
    // This should be done by Android, it is a bug fix 
    if(getHeaders() != null) { 

     final String displayedFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT); 
     if (displayedFragment != null) { 
      for (final Header header : getHeaders()) { 
       if (displayedFragment.equals(header.fragment)) { 
        switchToHeader(header); 
        break; 
       } 
      } 
     } 
    } 

    ... 

} 

/** 
* Populate the activity with the top-level headers. 
*/ 
@Override 
public void onBuildHeaders(List<Header> target) { 
    // we have to save the headers as the API call getHeaders() is hidden. 
    setHeaders(target); 
    loadHeadersFromResource(R.xml.settings_headers, target); 
} 

private List<Header> headers; 

private void setHeaders(List<Header> headers) { 
    this.headers = headers; 
} 

private List<Header> getHeaders() { 
    return headers; 
} 

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    outState.putSerializable("headers", (ArrayList<PreferenceActivity.Header>)headers); 
    super.onSaveInstanceState(outState); 
} 

@Override 
public void setListAdapter(ListAdapter adapter) { 
    if (adapter == null) { 
     super.setListAdapter(null); 
    } else { 
     super.setListAdapter(new HeaderAdapter(this, getHeaders())); 
    } 
} 

private static class HeaderAdapter extends ArrayAdapter<Header> { 
    static final int HEADER_TYPE_CATEGORY = 0; 
    static final int HEADER_TYPE_NORMAL = 1; 
    private static final int HEADER_TYPE_COUNT = HEADER_TYPE_NORMAL + 1; 

    private static class HeaderViewHolder { 
     ImageView icon; 
     TextView title; 
     TextView summary; 
    } 

    private LayoutInflater mInflater; 

    static int getHeaderType(Header header) { 
     if (header.fragment == null && header.intent == null) { 
      return HEADER_TYPE_CATEGORY; 
     } else { 
      return HEADER_TYPE_NORMAL; 
     } 
    } 

    @Override 
    public int getItemViewType(int position) { 
     Header header = getItem(position); 
     return getHeaderType(header); 
    } 

    @Override 
    public boolean areAllItemsEnabled() { 
     return false; // because of categories 
    } 

    @Override 
    public boolean isEnabled(int position) { 
     return getItemViewType(position) != HEADER_TYPE_CATEGORY; 
    } 

    @Override 
    public int getViewTypeCount() { 
     return HEADER_TYPE_COUNT; 
    } 

    @Override 
    public boolean hasStableIds() { 
     return true; 
    } 

    public HeaderAdapter(Context context, List<Header> objects) { 
     super(context, 0, objects); 

     mInflater = (LayoutInflater) context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     HeaderViewHolder holder; 
     Header header = getItem(position); 
     int headerType = getHeaderType(header); 
     View view = null; 

     if (convertView == null) { 
      holder = new HeaderViewHolder(); 
      switch (headerType) { 
      case HEADER_TYPE_CATEGORY: 
       view = new TextView(getContext(), null, 
         android.R.attr.listSeparatorTextViewStyle); 
       holder.title = (TextView) view; 
       break; 

      case HEADER_TYPE_NORMAL: 
       view = mInflater.inflate(R.layout.preference_header_item, 
         parent, false); 
       holder.icon = (ImageView) view.findViewById(R.id.icon); 
       holder.title = (TextView) view 
         .findViewById(android.R.id.title); 
       holder.summary = (TextView) view 
         .findViewById(android.R.id.summary); 
       break; 
      } 
      view.setTag(holder); 
     } else { 
      view = convertView; 
      holder = (HeaderViewHolder) view.getTag(); 
     } 

     // All view fields must be updated every time, because the view may 
     // be recycled 
     switch (headerType) { 
     case HEADER_TYPE_CATEGORY: 
      holder.title.setText(header.getTitle(getContext() 
        .getResources())); 
      break; 
     case HEADER_TYPE_NORMAL: 
      holder.icon.setImageResource(header.iconRes); 
      holder.title.setText(header.getTitle(getContext() 
        .getResources())); 
      CharSequence summary = header.getSummary(getContext() 
        .getResources()); 
      if (!TextUtils.isEmpty(summary)) { 
       holder.summary.setVisibility(View.VISIBLE); 
       holder.summary.setText(summary); 
      } else { 
       holder.summary.setVisibility(View.GONE); 
      } 
      break; 
     } 

     return view; 
    } 

} 

有了这些代码后,创建头很简单:

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" > 
    <header android:title="atitle" /> 
</preference-headers> 

希望这可以帮助别人。我知道这花了我一些时间才能正常工作。

1

这实际上很简单。从我发现的情况来看,PreferenceActivity本身并不支持添加分类/章节标题,看起来您只能添加Header s - 这不是很有趣。

所以,你首先需要做的是没有做任何繁重的工作在你的PreferenceActivity本身并直接进入加载PreferenceFragment

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

    setTitle("Settings"); 

    // Display the fragment as the main content. 
    getFragmentManager().beginTransaction() 
      .replace(android.R.id.content, new PreferencesFragment()) 
      .commit(); 

} 

public static class PreferencesFragment extends PreferenceFragment { 

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

     addPreferencesFromResource(R.xml.prefs); 
    } 
} 

一旦你做到了这一点,你现在可以做的所有工作中你的PreferenceFragment,好消息是你现在可以使用类别

你R.xml.prefs文件应该是这个样子:

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > 
    <PreferenceCategory 
     android:summary="Login credentials" 
     android:title="Login credentials" > 
     <EditTextPreference 
      android:key="username" 
      android:summary="Username" 
      android:title="Username" /> 
     <EditTextPreference 
      android:key="password" 
      android:summary="Password" 
      android:title="Password" /> 
    </PreferenceCategory> 

    <PreferenceCategory 
     android:summary="Settings" 
     android:title="Settings" > 
     <CheckBoxPreference 
      android:key="persist" 
      android:summary="Yes/No" 
      android:title="Keep me signed in" /> 

    </PreferenceCategory> 
</PreferenceScreen> 

您要添加的每个新的类别只需创建一个PreferenceCategory

相关问题