Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f704097d authored by Michael Kwan's avatar Michael Kwan Committed by android-build-merger
Browse files

Add titles to PreferenceFragments and PreferenceScreens for watches.

am: 744be16f

Change-Id: I54847a5ef3ddb4e09cc835433d80e121cf32b725
parents 893ada03 744be16f
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -27,12 +27,14 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;

/**
 * Shows a hierarchy of {@link Preference} objects as
@@ -366,6 +368,20 @@ public abstract class PreferenceFragment extends Fragment implements
    private void bindPreferences() {
        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        if (preferenceScreen != null) {
            View root = getView();
            if (root != null) {
                View titleView = root.findViewById(android.R.id.title);
                if (titleView instanceof TextView) {
                    CharSequence title = preferenceScreen.getTitle();
                    if (TextUtils.isEmpty(title)) {
                        titleView.setVisibility(View.GONE);
                    } else {
                        ((TextView) titleView).setText(title);
                        titleView.setVisibility(View.VISIBLE);
                    }
                }
            }

            preferenceScreen.bind(getListView());
        }
        onBindPreferences();
+39 −4
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package android.preference;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,6 +33,7 @@ import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

/**
 * Represents a top-level {@link Preference} that
@@ -92,12 +95,32 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi

    private ListView mListView;

    private int mLayoutResId = com.android.internal.R.layout.preference_list_fragment;
    private Drawable mDividerDrawable;
    private boolean mDividerSpecified;

    /**
     * Do NOT use this constructor, use {@link PreferenceManager#createPreferenceScreen(Context)}.
     * @hide-
     */
    public PreferenceScreen(Context context, AttributeSet attrs) {
        super(context, attrs, com.android.internal.R.attr.preferenceScreenStyle);

        TypedArray a = context.obtainStyledAttributes(null,
                com.android.internal.R.styleable.PreferenceScreen,
                com.android.internal.R.attr.preferenceScreenStyle,
                0);

        mLayoutResId = a.getResourceId(
                com.android.internal.R.styleable.PreferenceScreen_screenLayout,
                mLayoutResId);
        if (a.hasValueOrEmpty(com.android.internal.R.styleable.PreferenceScreen_divider)) {
            mDividerDrawable =
                    a.getDrawable(com.android.internal.R.styleable.PreferenceScreen_divider);
            mDividerSpecified = true;
        }

        a.recycle();
    }

    /**
@@ -163,19 +186,31 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi

        LayoutInflater inflater = (LayoutInflater)
                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View childPrefScreen = inflater.inflate(
                com.android.internal.R.layout.preference_list_fragment, null);
        View childPrefScreen = inflater.inflate(mLayoutResId, null);
        View titleView = childPrefScreen.findViewById(android.R.id.title);
        mListView = (ListView) childPrefScreen.findViewById(android.R.id.list);
        if (mDividerSpecified) {
            mListView.setDivider(mDividerDrawable);
        }

        bind(mListView);

        // Set the title bar if title is available, else no title bar
        final CharSequence title = getTitle();
        Dialog dialog = mDialog = new Dialog(context, context.getThemeResId());
        if (TextUtils.isEmpty(title)) {
            if (titleView != null) {
                titleView.setVisibility(View.GONE);
            }
            dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        } else {
            if (titleView instanceof TextView) {
                ((TextView) titleView).setText(title);
                titleView.setVisibility(View.VISIBLE);
            } else {
                dialog.setTitle(title);
            }
        }
        dialog.setContentView(childPrefScreen);
        dialog.setOnDismissListener(this);
        if (state != null) {
+28 −8
Original line number Diff line number Diff line
@@ -112,8 +112,8 @@ public class ListView extends AbsListView {
        public boolean isSelectable;
    }

    private ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList();
    private ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList();
    ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList();
    ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList();

    Drawable mDivider;
    int mDividerHeight;
@@ -279,7 +279,7 @@ public class ListView extends AbsListView {
        // Wrap the adapter if it wasn't already wrapped.
        if (mAdapter != null) {
            if (!(mAdapter instanceof HeaderViewListAdapter)) {
                mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
                wrapHeaderListAdapterInternal();
            }

            // In the case of re-adding a header view, or adding one later on,
@@ -373,7 +373,7 @@ public class ListView extends AbsListView {
        // Wrap the adapter if it wasn't already wrapped.
        if (mAdapter != null) {
            if (!(mAdapter instanceof HeaderViewListAdapter)) {
                mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
                wrapHeaderListAdapterInternal();
            }

            // In the case of re-adding a footer view, or adding one later on,
@@ -476,7 +476,7 @@ public class ListView extends AbsListView {
        mRecycler.clear();

        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
            mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);
        } else {
            mAdapter = adapter;
        }
@@ -2228,7 +2228,7 @@ public class ListView extends AbsListView {
     * after the header views.
     */
    public void setSelectionAfterHeaderView() {
        final int count = mHeaderViewInfos.size();
        final int count = getHeaderViewsCount();
        if (count > 0) {
            mNextSelectedPosition = 0;
            return;
@@ -3356,7 +3356,7 @@ public class ListView extends AbsListView {
            bounds.right = mRight - mLeft - mPaddingRight;

            final int count = getChildCount();
            final int headerCount = mHeaderViewInfos.size();
            final int headerCount = getHeaderViewsCount();
            final int itemCount = mItemCount;
            final int footerLimit = (itemCount - mFooterViewInfos.size());
            final boolean headerDividers = mHeaderDividersEnabled;
@@ -3940,7 +3940,7 @@ public class ListView extends AbsListView {
        if (drawDividers) {
            final boolean fillForMissingDividers = isOpaque() && !super.isOpaque();
            final int itemCount = mItemCount;
            final int headerCount = mHeaderViewInfos.size();
            final int headerCount = getHeaderViewsCount();
            final int footerLimit = (itemCount - mFooterViewInfos.size());
            final boolean isHeader = (itemIndex < headerCount);
            final boolean isFooter = (itemIndex >= footerLimit);
@@ -4052,4 +4052,24 @@ public class ListView extends AbsListView {

        encoder.addProperty("recycleOnMeasure", recycleOnMeasure());
    }

    /** @hide */
    protected HeaderViewListAdapter wrapHeaderListAdapterInternal(
            ArrayList<ListView.FixedViewInfo> headerViewInfos,
            ArrayList<ListView.FixedViewInfo> footerViewInfos,
            ListAdapter adapter) {
        return new HeaderViewListAdapter(headerViewInfos, footerViewInfos, adapter);
    }

    /** @hide */
    protected void wrapHeaderListAdapterInternal() {
        mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, mAdapter);
    }

    /** @hide */
    protected void dispatchDataSetObserverOnChangedInternal() {
        if (mDataSetObserver != null) {
            mDataSetObserver.onChanged();
        }
    }
}
+215 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.internal.widget;

import android.annotation.IdRes;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.HeaderViewListAdapter;

import java.util.ArrayList;

import com.android.internal.util.Predicate;

public class WatchHeaderListView extends ListView {
    private View mTopPanel;

    public WatchHeaderListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public WatchHeaderListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public WatchHeaderListView(
            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected HeaderViewListAdapter wrapHeaderListAdapterInternal(
            ArrayList<ListView.FixedViewInfo> headerViewInfos,
            ArrayList<ListView.FixedViewInfo> footerViewInfos,
            ListAdapter adapter) {
        return new WatchHeaderListAdapter(headerViewInfos, footerViewInfos, adapter);
    }

    @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        if (mTopPanel == null) {
            setTopPanel(child);
        } else {
            throw new IllegalStateException("WatchHeaderListView can host only one header");
        }
    }

    public void setTopPanel(View v) {
        mTopPanel = v;
        wrapAdapterIfNecessary();
    }

    @Override
    public void setAdapter(ListAdapter adapter) {
        super.setAdapter(adapter);
        wrapAdapterIfNecessary();
    }

    @Override
    protected View findViewTraversal(@IdRes int id) {
        View v = super.findViewTraversal(id);
        if (v == null && mTopPanel != null && !mTopPanel.isRootNamespace()) {
            return mTopPanel.findViewById(id);
        }
        return v;
    }

    @Override
    protected View findViewWithTagTraversal(Object tag) {
        View v = super.findViewWithTagTraversal(tag);
        if (v == null && mTopPanel != null && !mTopPanel.isRootNamespace()) {
            return mTopPanel.findViewWithTag(tag);
        }
        return v;
    }

    @Override
    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
        View v = super.findViewByPredicateTraversal(predicate, childToSkip);
        if (v == null && mTopPanel != null && mTopPanel != childToSkip
                && !mTopPanel.isRootNamespace()) {
            return mTopPanel.findViewByPredicate(predicate);
        }
        return v;
    }

    @Override
    public int getHeaderViewsCount() {
        return mTopPanel == null ? super.getHeaderViewsCount() : super.getHeaderViewsCount() + 1;
    }

    private void wrapAdapterIfNecessary() {
        ListAdapter adapter = getAdapter();
        if (adapter != null && mTopPanel != null) {
            if (!(adapter instanceof WatchHeaderListAdapter)) {
                wrapHeaderListAdapterInternal();
            }

            ((WatchHeaderListAdapter) getAdapter()).setTopPanel(mTopPanel);
            dispatchDataSetObserverOnChangedInternal();
        }
    }

    private static class WatchHeaderListAdapter extends HeaderViewListAdapter {
        private View mTopPanel;

        public WatchHeaderListAdapter(
                ArrayList<ListView.FixedViewInfo> headerViewInfos,
                ArrayList<ListView.FixedViewInfo> footerViewInfos,
                ListAdapter adapter) {
            super(headerViewInfos, footerViewInfos, adapter);
        }

        public void setTopPanel(View v) {
            mTopPanel = v;
        }

        private int getTopPanelCount() {
            return mTopPanel == null ? 0 : 1;
        }

        @Override
        public int getCount() {
            return super.getCount() + getTopPanelCount();
        }

        @Override
        public boolean areAllItemsEnabled() {
            return mTopPanel == null && super.areAllItemsEnabled();
        }

        @Override
        public boolean isEnabled(int position) {
            if (mTopPanel != null) {
                if (position == 0) {
                    return false;
                } else {
                    return super.isEnabled(position - 1);
                }
            }

            return super.isEnabled(position);
        }

        @Override
        public Object getItem(int position) {
            if (mTopPanel != null) {
                if (position == 0) {
                    return null;
                } else {
                    return super.getItem(position - 1);
                }
            }

            return super.getItem(position);
        }

        @Override
        public long getItemId(int position) {
            int numHeaders = getHeadersCount() + getTopPanelCount();
            if (getWrappedAdapter() != null && position >= numHeaders) {
                int adjPosition = position - numHeaders;
                int adapterCount = getWrappedAdapter().getCount();
                if (adjPosition < adapterCount) {
                    return getWrappedAdapter().getItemId(adjPosition);
                }
            }
            return -1;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (mTopPanel != null) {
                if (position == 0) {
                    return mTopPanel;
                } else {
                    return super.getView(position - 1, convertView, parent);
                }
            }

            return super.getView(position, convertView, parent);
        }

        @Override
        public int getItemViewType(int position) {
            int numHeaders = getHeadersCount() + getTopPanelCount();
            if (getWrappedAdapter() != null && position >= numHeaders) {
                int adjPosition = position - numHeaders;
                int adapterCount = getWrappedAdapter().getCount();
                if (adjPosition < adapterCount) {
                    return getWrappedAdapter().getItemViewType(adjPosition);
                }
            }

            return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
        }
    }
}
+93 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2016 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="@android:color/transparent"
    android:layout_removeBorders="true">

    <FrameLayout
        android:id="@android:id/list_container"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1">
        <com.android.internal.widget.WatchHeaderListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            style="?attr/preferenceFragmentListStyle"
            android:scrollbarStyle="@integer/preference_fragment_scrollbarStyle"
            android:clipToPadding="false"
            android:drawSelectorOnTop="false"
            android:cacheColorHint="@android:color/transparent"
            android:scrollbarAlwaysDrawVerticalTrack="true">
             <TextView
                android:id="@android:id/title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingStart="@dimen/dialog_padding_material"
                android:paddingEnd="@dimen/dialog_padding_material"
                android:paddingBottom="8dp"
                android:textAppearance="@style/TextAppearance.Material.Title"
                android:gravity="center" />
        </com.android.internal.widget.WatchHeaderListView>
    </FrameLayout>

    <TextView android:id="@android:id/empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="@dimen/preference_fragment_padding_side"
        android:gravity="center"
        android:visibility="gone" />

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

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

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

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