PreferenceActivity的简单自定义

最近触及修改源生的Settings。用到了PreferenceActivity、以及preference控件。简单讲一下PreferenceActivity的自定义。


1.分左右屏。

PreferenceActivity继承ListActivity。在在frameworks中找到其布局文件

<?xml version="1.0" encoding="UTF-8"?>


-<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">


-<LinearLayout android:layout_width="match_parent" android:layout_height="0px" android:orientation="horizontal" android:layout_weight="1">


-<LinearLayout android:layout_width="0px" android:layout_height="match_parent" android:orientation="vertical" android:layout_weight="@android:integer/preferences_left_pane_weight" android:layout_marginStart="@android:dimen/preference_screen_side_margin" android:layout_marginEnd="@android:dimen/preference_screen_side_margin_negative" android:id="@android:id/headers">

<ListView android:layout_width="match_parent" android:layout_height="0px" android:layout_weight="1" android:id="@android:id/list" android:scrollbarAlwaysDrawVerticalTrack="true" android:listPreferredItemHeight="48dp" android:cacheColorHint="@android:color/transparent" android:drawSelectorOnTop="false" android:scrollbarStyle="@android:integer/preference_screen_header_scrollbarStyle" android:clipToPadding="false" android:paddingBottom="@android:dimen/preference_screen_header_vertical_padding" android:paddingTop="@android:dimen/preference_screen_header_vertical_padding" android:paddingEnd="@android:dimen/preference_screen_header_padding_side" android:paddingStart="@android:dimen/preference_screen_header_padding_side"/>

<FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0" android:id="@android:id/list_footer"/>

</LinearLayout>


-<LinearLayout android:layout_width="0px" android:layout_height="match_parent" android:orientation="vertical" android:layout_weight="@android:integer/preferences_right_pane_weight" android:id="@android:id/prefs_frame" android:visibility="gone" style="@android:attr/preferencePanelStyle">

<!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an empty layout or just padding, and PreferenceActivity will put the breadcrumbs in the action bar. -->


<include layout="@android:layout/breadcrumbs_in_fragment"/>

<android.preference.PreferenceFrameLayout android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" android:id="@android:id/prefs"/>

</LinearLayout>

</LinearLayout>


-<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0" android:id="@android:id/button_bar" android:visibility="gone">

<Button android:layout_width="150dip" android:layout_height="wrap_content" android:id="@android:id/back_button" android:text="@android:string/back_button_label" android:layout_alignParentStart="true" android:layout_margin="5dip"/>


-<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_alignParentEnd="true">

<Button android:layout_width="150dip" android:layout_height="wrap_content" android:id="@android:id/skip_button" android:visibility="gone" android:text="@android:string/skip_button_label" android:layout_margin="5dip"/>

<Button android:layout_width="150dip" android:layout_height="wrap_content" android:id="@android:id/next_button" android:text="@android:string/next_button_label" android:layout_margin="5dip"/>

</LinearLayout>

</RelativeLayout>

</LinearLayout>

可以看出主要是一个ListView  和  android.preference.PreferenceFrameLayout这两个部分。

在手机中,Settings是由多级界面组成的,通过代码的控制,一级界面即这个ListView。二级界面、三级界面等进行具体设置的页面由这个PreferenceFrameLayout控制,这个PreferenceFrameLayout显然是Fragment的容器。

在平板中往往都是左边显示标题,右边显示具体设置。


看一下PreferenceActivity的onCreate()的部分源码。

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

        setContentView(com.android.internal.R.layout.preference_list_content);

        mListFooter = (FrameLayout)findViewById(com.android.internal.R.id.list_footer);
        mPrefsContainer = (ViewGroup) findViewById(com.android.internal.R.id.prefs_frame);
        boolean hidingHeaders = onIsHidingHeaders();
        mSinglePane = hidingHeaders || !onIsMultiPane();
        String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
        Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
        int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
        int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0);

        if (savedInstanceState != null) {
            // We are restarting from a previous saved state; used that to
            // initialize, instead of starting fresh.
            ArrayList<Header> headers = savedInstanceState.getParcelableArrayList(HEADERS_TAG);
            if (headers != null) {
                mHeaders.addAll(headers);
                int curHeader = savedInstanceState.getInt(CUR_HEADER_TAG,
                        (int) HEADER_ID_UNDEFINED);
                if (curHeader >= 0 && curHeader < mHeaders.size()) {
                    setSelectedHeader(mHeaders.get(curHeader));
                }
            }

        } else {
            if (initialFragment != null && mSinglePane) {
                // If we are just showing a fragment, we want to run in
                // new fragment mode, but don't need to compute and show
                // the headers.
                switchToHeader(initialFragment, initialArguments);
                if (initialTitle != 0) {
                    CharSequence initialTitleStr = getText(initialTitle);
                    CharSequence initialShortTitleStr = initialShortTitle != 0
                            ? getText(initialShortTitle) : null;
                    showBreadCrumbs(initialTitleStr, initialShortTitleStr);
                }

            } else {
                // We need to try to build the headers.
                onBuildHeaders(mHeaders);

                // If there are headers, then at this point we need to show
                // them and, depending on the screen, we may also show in-line
                // the currently selected preference fragment.
                if (mHeaders.size() > 0) {
                    if (!mSinglePane) {
                        if (initialFragment == null) {
                            Header h = onGetInitialHeader();
                            switchToHeader(h);
                        } else {
                            switchToHeader(initialFragment, initialArguments);
                        }
                    }
                }
            }
        }
…………………………………………
}

可以看到boolean mSinglePane控制了这两个组件的显示与隐藏。

如果需要手动控制分屏。可以覆写onIsMultiPane()这个方法,设定返回值。false为多级界面、true为一个界面分成两块。

    public boolean onIsMultiPane() {
        boolean preferMultiPane = getResources().getBoolean(
                com.android.internal.R.bool.preferences_prefer_dual_pane);
        return preferMultiPane;
    }


2.获取标题

通常采取覆写onBindHeader这个方法

@Override
 public void onBuildHeaders(List<Header> target) {
        // Should be overloaded by subclasses
loadHeadersFromResource(R.xml.headers,target)
    }



loadHeadersFromResource这个方法实现了对headers.xml文件的解析。并将数据存放在一个List<Header>对象中。

3.修改标题栏
源码存放中有一个HeaderAdapter类,用于将解析完的标题适配进先前提到的ListVIew中。

如果希望对这个ListView界面进行修改,可以用自定义的Adapter进行替换。


在我们的代码中可以先找到这个ListView。并获取其Adapter及Adapter的数据。

最用用自定义Adapter将数据重新放入ListView。

ListView lv =(ListView) findViewById(android.R.id.list); //找到ListView
List<Header> mHeader = new ArrayList<Header>();
while(lv.getAdapter.getItem != null){
    mHeader.add(lv.getAdapter.getItem);
}
MyAdapter adapter = new MyAdapter(this,mHeader);  //自定义Adapter
lv.setAdapter(adapter);




注意,这段代码一定要在super.onCreate();之后执行。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值