Loading core/java/android/preference/PreferenceFragment.java +16 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); Loading core/java/android/preference/PreferenceScreen.java +39 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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(); } /** Loading Loading @@ -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) { Loading core/java/android/widget/ListView.java +28 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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(); } } } core/java/com/android/internal/widget/WatchHeaderListView.java 0 → 100644 +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; } } } core/res/res/layout-watch/preference_list_fragment_material.xml 0 → 100644 +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
core/java/android/preference/PreferenceFragment.java +16 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); Loading
core/java/android/preference/PreferenceScreen.java +39 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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(); } /** Loading Loading @@ -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) { Loading
core/java/android/widget/ListView.java +28 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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(); } } }
core/java/com/android/internal/widget/WatchHeaderListView.java 0 → 100644 +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; } } }
core/res/res/layout-watch/preference_list_fragment_material.xml 0 → 100644 +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>