Adithya
Adithya

Reputation: 2975

Android Settings UI

I am looking to build something similar to the settings UI of system android. I want something like a few checkboxpreferences, switchpreferences, edittextpreferences on the launch of application and then when user selects one preference open a fragment but i am just not able to figure that out.

I have referred Settings guide but it insists on using preference header. While displaying headers there is an unlikely overhead i am facing of displaying texts which in turn will load fragments.

For example,

My preference header is something like :

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

and just to load the actual data, i am having to use it. The actual data will have checkboxes and edittexts.

It would be great if someone gave some insights on this. It would be of great help if i could launch the actual fragment data on loading of screen. Better if i could have control of what fragment to call and call other fragments when a fragment item is selected.

Upvotes: 2

Views: 2689

Answers (1)

mark.kedzierski
mark.kedzierski

Reputation: 663

To create custom preference headers, with switches and such, you need to extend PreferenceActivity with Headers as the Android docs describe and then override PreferenceActivity.setListAdapter to create your own list adapter, which creates the custom views. I made a pastebin with the code from the actual android settings activity to help you out. 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();
    }
}

Upvotes: 5

Related Questions