4

我發現了類似的問題,但無法找到最新的具體答案。 我使用<preference-header>,根據3.0+的設置設計指導方針(我的目標是4.1.2+)來構建我的標題;我想爲這些標題設置一個自定義佈局。請注意,我不想回到舊版PreferenceScreen方法here,因爲我不支持較舊的Android版本。是否可以自定義首選項標題佈局?

據我研究,這種佈局是由PreferenceActivity類的私有成員舉行,它與一個設置樣式屬性檢索似乎沒有公開訪問:

private int mPreferenceHeaderItemResId = 0; 
... 
@Override 
protected void onCreate(@Nullable Bundle savedInstanceState) { 
... 
TypedArray sa = obtainStyledAttributes(null, 
      com.android.internal.R.styleable.PreferenceActivity, 
      com.android.internal.R.attr.preferenceActivityStyle, 
      0); 
... 
mPreferenceHeaderItemResId = sa.getResourceId(
    com.android.internal.R.styleable.PreferenceActivity_headerLayout, 
      com.android.internal.R.layout.preference_header_item); 
... 
} 

這個資源是那麼傳遞給一個專用適配器來填充標題ListView。

有沒有辦法傳遞不同的佈局資源?

回答

5

UPDATE 2016年4月14日:存在與重新創建問題通過savedInstanceState,但我發現another similar solution從我用setListAdapter方法的代碼(I改性下面的代碼)。


我也解決了這個問題。我不知道以下解決方案是否正確,但速度最快。由於PreferenceActivity是ListActivity的子項,因此您可以覆蓋setListAdapter方法以使用自己的適配器來處理標題項目。這很醜陋,因爲在PreferenceActivity.onCreate()中調用setListAdapter方法並將adapter參數設置爲HeaderAdapter的新實例,所以下面的調整忽略此實例。

@Override 
public void setListAdapter(ListAdapter adapter) { 
    int i, count; 

    if (mHeaders == null) { 
     mHeaders = new ArrayList<>(); 
     // When the saved state provides the list of headers, onBuildHeaders is not called 
     // so we build it from the adapter given, then use our own adapter 

     count = adapter.getCount(); 
     for (i = 0; i < count; ++i) { 
      mHeaders.add((Header) adapter.getItem(i)); 
     } 
    } 

    super.setListAdapter(new CustomHeaderAdapter(this, mHeaders, R.layout.preference_header_item, true)); 
} 

mHeaders屬性被定義爲類成員

private List<Header> mHeaders; 

和onBuildHeaders被分配:

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

我複製並從SDK源改性適配器內部類和佈局:

private static class CustomHeaderAdapter extends ArrayAdapter<Header> { 
    private static class HeaderViewHolder { 
     ImageView icon; 
     TextView title; 
     TextView summary; 
    } 

    private LayoutInflater mInflater; 
    private int mLayoutResId; 
    private boolean mRemoveIconIfEmpty; 

    public CustomHeaderAdapter(Context context, List<Header> objects, int layoutResId, 
         boolean removeIconBehavior) { 
     super(context, 0, objects); 
     mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     mLayoutResId = layoutResId; 
     mRemoveIconIfEmpty = removeIconBehavior; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     HeaderViewHolder holder; 
     View view; 

     if (convertView == null) { 
      view = mInflater.inflate(mLayoutResId, parent, false); 
      holder = new HeaderViewHolder(); 
      holder.icon = (ImageView) view.findViewById(R.id.icon); 
      holder.title = (TextView) view.findViewById(R.id.title); 
      holder.summary = (TextView) view.findViewById(R.id.summary); 
      view.setTag(holder); 
     } else { 
      view = convertView; 
      holder = (HeaderViewHolder) view.getTag(); 
     } 

     // All view fields must be updated every time, because the view may be recycled 
     Header header = getItem(position); 
     if (mRemoveIconIfEmpty) { 
      if (header.iconRes == 0) { 
       holder.icon.setVisibility(View.GONE); 
      } else { 
       holder.icon.setVisibility(View.VISIBLE); 
       holder.icon.setImageResource(header.iconRes); 
      } 
     } else { 
      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); 
     } 

     return view; 
    } 
} 

preference_header_item.xml with minHeight:

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

    <ImageView 
     android:id="@+id/icon" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginStart="6dip" 
     android:layout_marginEnd="6dip" 
     android:layout_gravity="center" /> 

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

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

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

    </RelativeLayout> 

</LinearLayout>