2013-02-01 34 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

相關問題