Android的 - 接头类别preferenceActivity用preferenceFragment [英] Android - Headers categories in PreferenceActivity with PreferenceFragment

查看:181
本文介绍了Android的 - 接头类别preferenceActivity用preferenceFragment的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想显示preference屏幕就像一个在Android设置应用程序:用头,preferenceActivity,preferenceFragment和头文件类别

我wan't在平板电脑这样的结果:

而这一次在智能手机上:

它的工作原理,如果我只使用基本的头,但如果我尝试添加的类别,它适用于智能手机和崩溃的平板电脑,在那里我得到的异常显示java.lang.NullPointerException:姓名== NULL

 致命异常:主要
java.lang.RuntimeException的:无法启动的活动ComponentInfo{fr.ifremer.testandroid/fr.ifremer.testandroid.models.$p$pferences.Main$p$pferenceActivity}:显示java.lang.NullPointerException:姓名== NULL
    在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110)
    在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
    在android.app.ActivityThread.access $ 700(ActivityThread.java:140)
    在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1237)
    在android.os.Handler.dispatchMessage(Handler.java:99)
    在android.os.Looper.loop(Looper.java:137)
    在android.app.ActivityThread.main(ActivityThread.java:4921)
    在java.lang.reflect.Method.invokeNative(本机方法)
    在java.lang.reflect.Method.invoke(Method.java:511)
    在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1038)
    在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
    在dalvik.system.NativeStart.main(本机方法)
致:显示java.lang.NullPointerException:姓名== NULL
    在java.lang.VMClassLoader.findLoadedClass(本机方法)
    在java.lang.ClassLoader.findLoadedClass(ClassLoader.java:354)
    在java.lang.ClassLoader.loadClass(ClassLoader.java:491)
    在java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    在android.app.Fragment.instantiate(Fragment.java:574)
    在安卓preference preferenceActivity.switchToHeaderInner(preferenceActivity.java:1222)。
    。在安卓preference preferenceActivity.switchToHeader(preferenceActivity.java:1255)
    在安卓preference preferenceActivity.onCreate(preferenceActivity.java:630)。
    在fr.ifremer.testandroid.models.$p$pferences.Main$p$pferenceActivity.onCreate(Main$p$pferenceActivity.java:19)
    在android.app.Activity.performCreate(Activity.java:5206)
    在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
    在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
    ... 11更多
 

贝娄是code所涉及的组件。我从Android设置应用程序的源得到了他们大部分。

你知道吗?

在此先感谢


主要preferenceActivity:

 公共类主要preferenceActivity扩展preferenceActivity {

    私有静态列表<头> _headers;

    @覆盖
    公共无效onBuildHeaders(名单<头>头){

        _headers =头;
        loadHeadersFromResource(R.xml preference_headers,头);
    }

    @覆盖
    公共无效setListAdapter(ListAdapter适配器){

        如果(适配器== NULL){
            super.setListAdapter(空);
        } 其他 {
            super.setListAdapter(新HeaderAdapter(这一点,_headers));
        }
    }
}
 

preferencesFragment:

 公共类preferencesFragment扩展preferenceFragment {

    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);

        字符串设置= getArguments()的getString(设置)。

        如果(settings.equals(假摔)){

            加preferencesFromResource(R.xml preference_dive_tile。);
        }
        否则如果(settings.equals(MAP)){

            加preferencesFromResource(R.xml preference_map_tile。);
        }
    }
}
 

preference_headers.xml:

 < XML版本=1.0编码=UTF-8&GT?;
< preference报头的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android>

    <头
        机器人:ID =@ + ID / header_section_1
        机器人:标题=第1/>

    <头
        机器人:片段=。fr.ifremer.testandroid.models preferences preferencesFragment。
        机器人:总结=DIVE摘要
        机器人:标题=潜水冠军>
        <额外
            机器人:名称=设置
            机器人:值=DIVE/>
    < /头>
    <头
        机器人:片段=。fr.ifremer.testandroid.models preferences preferencesFragment。
        机器人:总结=MAP摘要
        机器人:标题=地图标题>
        <额外
            机器人:名称=设置
            机器人:值=地图/>
    < /头>

< / preference报头>
 

最后但并非最不重要的,HeaderAdapter:

 公共类HeaderAdapter扩展ArrayAdapter<头> {

    静态最终诠释HEADER_TYPE_CATEGORY = 0;
    静态最终诠释HEADER_TYPE_NORMAL = 1;
    私有静态最终诠释HEADER_TYPE_COUNT = HEADER_TYPE_NORMAL + 1;

    私人LayoutInflater mInflater;

    私有静态类HeaderViewHolder {
        ImageView的图标;
        TextView的称号;
        TextView的总结;
    }

    公共HeaderAdapter(上下文的背景下,名单,其中,头>对象){

        超(背景下,0,对象);

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

    静态INT getHeaderType(头球冲顶){

        如果(header.fragment == NULL和放大器;&安培; header.intent == NULL)返回HEADER_TYPE_CATEGORY;
        否则返回HEADER_TYPE_NORMAL;
    }

    @覆盖
    公众诠释getItemViewType(INT位置){
        标题标题=的getItem(位置);
        返回getHeaderType(头);
    }

    @覆盖
    公共布尔areAllItemsEnabled(){返回false; / *因为类* /}

    @覆盖
    公共布尔的IsEnabled(INT位置){返回getItemViewType(位置)= HEADER_TYPE_CATEGORY!; }

    @覆盖
    公众诠释getViewTypeCount(){返回HEADER_TYPE_COUNT; }

    @覆盖
    公共布尔hasStableIds(){返回true; }

    @覆盖
    公共查看getView(INT位置,查看convertView,ViewGroup中父){

        HeaderViewHolder持有人;
        标题标题=的getItem(位置);
        INT headerType = getHeaderType(头);
        查看查看= NULL;

        如果(convertView == NULL){

            持有人=新HeaderViewHolder();

            开关(headerType){

                案例HEADER_TYPE_CATEGORY:

                    鉴于=新的TextView(的getContext(),空,android.R.attr.listSeparatorTextViewStyle);
                    holder.title =(TextView的)观点;
                    打破;

                案例HEADER_TYPE_NORMAL:

                    鉴于= mInflater.inflate(R.layout preference_header_item,父母,假的。);
                    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(保持器);
        }
        其他 {

            鉴于= convertView;
            支架=(HeaderViewHolder)view.getTag();
        }

        //所有的视场必须在每次更新,因为视图可以回收
        开关(headerType){

            案例HEADER_TYPE_CATEGORY:

                holder.title.setText(header.getTitle(的getContext()getResources())。);
                打破;

            案例HEADER_TYPE_NORMAL:

                holder.icon.setImageResource(header.iconRes);

                holder.title.setText(header.getTitle(的getContext()getResources())。);
                的CharSequence摘要= header.getSummary(的getContext()getResources());

                如果(!TextUtils.isEmpty(摘要)){

                    holder.summary.setVisibility(View.VISIBLE);
                    holder.summary.setText(摘要);
                }
                其他 {
                    holder.summary.setVisibility(View.GONE);
                }
                打破;
        }

        返回查看;
    }
}
 

解决方案

也许第一个标题是默认选择的菜单。如果是这样,它应该有片段属性来显示它的右侧。

I would like to display a preference screen like the one in the Android settings app : using headers, PreferenceActivity, PreferenceFragment and headers categories.

I wan't this result on a tablet :

And this one on a smartphone :

It works if I just use the basic headers, but if I try to add categories, it works on the smartphone, and crash on the tablet, where I get the exception "java.lang.NullPointerException: name == null" :

FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{fr.ifremer.testandroid/fr.ifremer.testandroid.models.preferences.MainPreferenceActivity}: java.lang.NullPointerException: name == null
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
    at android.app.ActivityThread.access$700(ActivityThread.java:140)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4921)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException: name == null
    at java.lang.VMClassLoader.findLoadedClass(Native Method)
    at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:491)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    at android.app.Fragment.instantiate(Fragment.java:574)
    at android.preference.PreferenceActivity.switchToHeaderInner(PreferenceActivity.java:1222)
    at android.preference.PreferenceActivity.switchToHeader(PreferenceActivity.java:1255)
    at android.preference.PreferenceActivity.onCreate(PreferenceActivity.java:630)
    at fr.ifremer.testandroid.models.preferences.MainPreferenceActivity.onCreate(MainPreferenceActivity.java:19)
    at android.app.Activity.performCreate(Activity.java:5206)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
    ... 11 more

Bellow are the pieces of code involved. I got them mostly from the Android settings app source.

Any idea ?

Thanks in advance


MainPreferenceActivity :

public class MainPreferenceActivity extends PreferenceActivity {

    private static List<Header> _headers;

    @Override
    public void onBuildHeaders(List<Header> headers) {

        _headers = headers;
        loadHeadersFromResource(R.xml.preference_headers, headers);
    }

    @Override
    public void setListAdapter(ListAdapter adapter) {

        if (adapter == null) {
            super.setListAdapter(null);
        } else {
            super.setListAdapter(new HeaderAdapter(this, _headers));
        }
    }
}

PreferencesFragment :

public class PreferencesFragment extends PreferenceFragment {

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

        String settings = getArguments().getString("settings");

        if (settings.equals("DIVE")) {

            addPreferencesFromResource(R.xml.preference_dive_tile);
        }
        else if (settings.equals("MAP")) {

            addPreferencesFromResource(R.xml.preference_map_tile);
        }
    }
}

preference_headers.xml :

<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >

    <header
        android:id="@+id/header_section_1"
        android:title="Section 1" />

    <header
        android:fragment="fr.ifremer.testandroid.models.preferences.PreferencesFragment"
        android:summary="DIVE summary"
        android:title="DIVE title" >
        <extra
            android:name="settings"
            android:value="DIVE" />
    </header>
    <header
        android:fragment="fr.ifremer.testandroid.models.preferences.PreferencesFragment"
        android:summary="MAP summary"
        android:title="MAP title" >
        <extra
            android:name="settings"
            android:value="MAP" />
    </header>

</preference-headers>

Last but not least, HeaderAdapter :

public 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 LayoutInflater mInflater;

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

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

        super(context, 0, objects);

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

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

    @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(R.id.title);
                    holder.summary = (TextView) view.findViewById(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;
    }
}

解决方案

Maybe first header is default selected menu. If so, it should have fragment attribute to show it right side.

这篇关于Android的 - 接头类别preferenceActivity用preferenceFragment的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆