安卓设置界面

标签 android android-fragments android-preferences android-fragmentactivity

我正在寻找构建类似于系统 android 的设置 UI 的东西。我想要在应用程序启动时使用一些复选框首选项、开关首选项、编辑文本首选项,然后当用户选择一个首选项时打开一个 fragment ,但我无法弄清楚这一点。

我已提及Settings指南,但它坚持使用首选项 header 。在显示标题时,我面临着显示文本的不太可能的开销,而文本又会加载 fragment 。

例如,

我的首选项标题类似于:

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

    <!-- These settings headers are only used on tablets. -->

    <header
        android:fragment="${packageName}.${activityClass}$GeneralPreferenceFragment"
        android:title="@string/pref_header_general" />
    <header
        android:fragment="${packageName}.${activityClass}$NotificationPreferenceFragment"
        android:title="@string/pref_header_notifications" />
    <header
        android:fragment="${packageName}.${activityClass}$DataSyncPreferenceFragment"
        android:title="@string/pref_header_data_sync" />

</preference-headers>

为了加载实际数据,我必须使用它。实际数据将有复选框和编辑文本。

如果有人对此提出一些见解,那就太好了。如果我可以在加载屏幕时启动实际的 fragment 数据,那将会有很大的帮助。如果我可以控制在选择 fragment 项时调用哪个 fragment 并调用其他 fragment ,那就更好了。

最佳答案

要使用开关等创建自定义首选项 header ,您需要按照 Android 文档的描述使用 header 扩展 PreferenceActivity,然后重写 PreferenceActivity.setListAdapter 以创建您自己的列表适配器,从而创建自定义 View 。我用实际 Android 设置 Activity 中的代码制作了一个 Pastebin 来帮助您。 http://pastebin.com/RhSndGCQ

@Override
public void onBuildHeaders(List<Header> headers) {
  loadHeadersFromResource(R.xml.settings_headers, headers);
  updateHeaderList(headers);
}

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

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

    private final WifiEnabler mWifiEnabler;
    private final BluetoothEnabler mBluetoothEnabler;
    private final ProfileEnabler mProfileEnabler;

    private AuthenticatorHelper mAuthHelper;

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

    private LayoutInflater mInflater;

    static int getHeaderType(Header header) {
        if (header.fragment == null && header.intent == null) {
            return HEADER_TYPE_CATEGORY;
        } else if (header.id == R.id.wifi_settings
                || header.id == R.id.bluetooth_settings
                || header.id == R.id.profiles_settings) {
            return HEADER_TYPE_SWITCH;
        } 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,
            AuthenticatorHelper authenticatorHelper) {
        super(context, 0, objects);

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

        // Temp Switches provided as placeholder until the adapter replaces these with actual
        // Switches inflated from their layouts. Must be done before adapter is set in super
        mWifiEnabler = new WifiEnabler(context, new Switch(context));
        mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
        mProfileEnabler = new ProfileEnabler(context, null, new Switch(context));
    }

    @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 || headerType == HEADER_TYPE_SWITCH) {
            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_SWITCH:
                    view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
                            false);
                    holder.icon = (ImageView) view.findViewById(R.id.icon);
                    holder.title = (TextView)
                            view.findViewById(com.android.internal.R.id.title);
                    holder.summary = (TextView)
                            view.findViewById(com.android.internal.R.id.summary);
                    holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
                    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(com.android.internal.R.id.title);
                    holder.summary = (TextView)
                            view.findViewById(com.android.internal.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_SWITCH:
                // Would need a different treatment if the main menu had more switches
                if (header.id == R.id.wifi_settings) {
                    mWifiEnabler.setSwitch(holder.switch_);
                } else if (header.id == R.id.bluetooth_settings) {
                    mBluetoothEnabler.setSwitch(holder.switch_);
                } else if (header.id == R.id.profiles_settings) {
                    mProfileEnabler.setSwitch(holder.switch_);
                }
                // No break, fall through on purpose to update common fields

                //$FALL-THROUGH$
            case HEADER_TYPE_NORMAL:
                if (header.extras != null
                        && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
                    String accType = header.extras.getString(
                            ManageAccountsSettings.KEY_ACCOUNT_TYPE);
                    ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
                    lp.width = getContext().getResources().getDimensionPixelSize(
                            R.dimen.header_icon_width);
                    lp.height = lp.width;
                    holder.icon.setLayoutParams(lp);
                    Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
                    holder.icon.setImageDrawable(icon);
                } 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);
                }
                break;
        }

        return view;
    }

    public void resume() {
        mWifiEnabler.resume();
        mBluetoothEnabler.resume();
        mProfileEnabler.resume();
    }

    public void pause() {
        mWifiEnabler.pause();
        mBluetoothEnabler.pause();
        mProfileEnabler.pause();
    }
}

关于安卓设置界面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14825216/

相关文章:

android - 单击 fragment 会调用其背后的 Activity

android - 从 fragment 内部调用 Activity 方法

cordova - Ionic 2 Cordova 和 Typescript(应用程序首选项插件)

android - if 和 else 命令在 android 首选项中

android - 哪个 UI 用于 Cordova Android/iPhone 应用程序开发

java - 在android中下载线程文件?

java - Android自定义进度条组件

java - ArrayList添加元素后为空

android - Fragment 未正确展开布局

java - Android 的 PreferenceScreen 替代方案