diff options
12 files changed, 296 insertions, 76 deletions
diff --git a/packages/SystemUI/res/layout/data_usage.xml b/packages/SystemUI/res/layout/data_usage.xml index 63d22b2..8831a05 100644 --- a/packages/SystemUI/res/layout/data_usage.xml +++ b/packages/SystemUI/res/layout/data_usage.xml @@ -17,6 +17,9 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" + android:paddingTop="16dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" android:orientation="vertical" > <TextView diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml index c6a7368..5869bf3 100644 --- a/packages/SystemUI/res/layout/qs_detail.xml +++ b/packages/SystemUI/res/layout/qs_detail.xml @@ -14,39 +14,43 @@ See the License for the specific language governing permissions and limitations under the License. --> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@drawable/qs_detail_background" - android:padding="16dp" > - - <TextView - android:id="@android:id/button1" - style="@style/QSBorderlessButton" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:minWidth="88dp" - android:layout_alignParentBottom="true" - android:layout_alignParentEnd="true" - android:text="@string/quick_settings_done" - android:textAppearance="@style/TextAppearance.QS.DetailButton" /> - - <TextView - android:id="@android:id/button2" - style="@style/QSBorderlessButton" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_marginEnd="8dp" - android:minWidth="132dp" - android:layout_toStartOf="@android:id/button1" - android:text="@string/quick_settings_more_settings" - android:textAppearance="@style/TextAppearance.QS.DetailButton" /> - - <FrameLayout - android:id="@android:id/content" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_above="@android:id/button1" /> + android:background="@drawable/qs_detail_background" + android:paddingBottom="16dp" + android:orientation="vertical"> + + <FrameLayout + android:id="@android:id/content" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingEnd="16dp" + android:gravity="end"> + + <TextView + android:id="@android:id/button2" + style="@style/QSBorderlessButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:minWidth="132dp" + android:text="@string/quick_settings_more_settings" + android:textAppearance="@style/TextAppearance.QS.DetailButton" /> + + <TextView + android:id="@android:id/button1" + style="@style/QSBorderlessButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minWidth="88dp" + android:text="@string/quick_settings_done" + android:textAppearance="@style/TextAppearance.QS.DetailButton" /> -</RelativeLayout>
\ No newline at end of file + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml index b64005f..f61a43c 100644 --- a/packages/SystemUI/res/layout/qs_detail_items.xml +++ b/packages/SystemUI/res/layout/qs_detail_items.xml @@ -17,7 +17,10 @@ <!-- extends FrameLayout --> <com.android.systemui.qs.QSDetailItems xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent" > + android:layout_height="match_parent" + android:paddingTop="16dp" + android:paddingStart="16dp" + android:paddingEnd="16dp"> <LinearLayout android:id="@android:id/list" diff --git a/packages/SystemUI/res/layout/qs_user_detail.xml b/packages/SystemUI/res/layout/qs_user_detail.xml index 1d6df61..91d3a53 100644 --- a/packages/SystemUI/res/layout/qs_user_detail.xml +++ b/packages/SystemUI/res/layout/qs_user_detail.xml @@ -16,14 +16,12 @@ ~ limitations under the License --> -<!-- GridView --> +<!-- PseudoGridView --> <com.android.systemui.qs.tiles.UserDetailView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:sysui="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:verticalSpacing="4dp" - android:horizontalSpacing="4dp" - android:numColumns="3" - android:listSelector="@drawable/ripple_drawable"> - -</com.android.systemui.qs.tiles.UserDetailView>
\ No newline at end of file + sysui:verticalSpacing="4dp" + sysui:horizontalSpacing="4dp" + style="@style/UserDetailView" />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml index 5ceed84..2322f16 100644 --- a/packages/SystemUI/res/layout/qs_user_detail_item.xml +++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml @@ -25,16 +25,17 @@ android:orientation="vertical" android:gravity="top|center_horizontal" android:paddingTop="16dp" - android:paddingBottom="20dp" + android:minHeight="112dp" android:clipChildren="false" android:clipToPadding="false" + android:background="@drawable/ripple_drawable" systemui:activatedFontFamily="sans-serif-medium"> <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture" android:layout_width="@dimen/max_avatar_size" android:layout_height="@dimen/max_avatar_size" - android:layout_marginBottom="12dp" + android:layout_marginBottom="10dp" systemui:frameWidth="2dp" systemui:framePadding="6dp" systemui:activeFrameColor="@color/current_user_border_color"/> diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml index 5daf08e..9e5b1d6 100644 --- a/packages/SystemUI/res/values-sw600dp/styles.xml +++ b/packages/SystemUI/res/values-sw600dp/styles.xml @@ -34,4 +34,8 @@ <item name="android:layout_height">@dimen/search_panel_scrim_height</item> <item name="android:layout_gravity">bottom</item> </style> + + <style name="UserDetailView"> + <item name="numColumns">4</item> + </style> </resources> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 8bd3c39..6ecdca3 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -67,5 +67,10 @@ <declare-styleable name="DateView"> <attr name="datePattern" format="string" /> </declare-styleable> + <declare-styleable name="PseudoGridView"> + <attr name="numColumns" format="integer" /> + <attr name="verticalSpacing" format="dimension" /> + <attr name="horizontalSpacing" format="dimension" /> + </declare-styleable> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 5db6912..baaa379 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -289,4 +289,8 @@ <item name="android:layout_height">@dimen/search_panel_scrim_height</item> <item name="android:layout_gravity">bottom</item> </style> + + <style name="UserDetailView"> + <item name="numColumns">3</item> + </style> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java new file mode 100644 index 0000000..d58663d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2014 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.systemui.qs; + +import com.android.systemui.R; + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; + +import java.lang.ref.WeakReference; + +/** + * A view that arranges it's children in a grid with a fixed number of evenly spaced columns. + * + * {@see android.widget.GridView} + */ +public class PseudoGridView extends ViewGroup { + + private int mNumColumns = 3; + private int mVerticalSpacing; + private int mHorizontalSpacing; + + public PseudoGridView(Context context, AttributeSet attrs) { + super(context, attrs); + + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PseudoGridView); + + final int N = a.getIndexCount(); + for (int i = 0; i < N; i++) { + int attr = a.getIndex(i); + switch (attr) { + case R.styleable.PseudoGridView_numColumns: + mNumColumns = a.getInt(attr, 3); + break; + case R.styleable.PseudoGridView_verticalSpacing: + mVerticalSpacing = a.getDimensionPixelSize(attr, 0); + break; + case R.styleable.PseudoGridView_horizontalSpacing: + mHorizontalSpacing = a.getDimensionPixelSize(attr, 0); + break; + } + } + + a.recycle(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + if (widthMode == MeasureSpec.UNSPECIFIED) { + throw new UnsupportedOperationException("Needs a maximum width"); + } + int width = MeasureSpec.getSize(widthMeasureSpec); + + int childWidth = (width - (mNumColumns - 1) * mHorizontalSpacing) / mNumColumns; + int childWidthSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY); + int childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + int totalHeight = 0; + int children = getChildCount(); + int rows = (children + mNumColumns - 1) / mNumColumns; + for (int row = 0; row < rows; row++) { + int startOfRow = row * mNumColumns; + int endOfRow = Math.min(startOfRow + mNumColumns, children); + int maxHeight = 0; + for (int i = startOfRow; i < endOfRow; i++) { + View child = getChildAt(i); + child.measure(childWidthSpec, childHeightSpec); + maxHeight = Math.max(maxHeight, child.getMeasuredHeight()); + } + int maxHeightSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY); + for (int i = startOfRow; i < endOfRow; i++) { + View child = getChildAt(i); + child.measure(childWidthSpec, maxHeightSpec); + } + totalHeight += maxHeight; + if (row > 0) { + totalHeight += mVerticalSpacing; + } + } + + setMeasuredDimension(width, getDefaultSize(totalHeight, heightMeasureSpec)); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int children = getChildCount(); + int rows = (children + mNumColumns - 1) / mNumColumns; + int y = 0; + for (int row = 0; row < rows; row++) { + int x = 0; + int maxHeight = 0; + int startOfRow = row * mNumColumns; + int endOfRow = Math.min(startOfRow + mNumColumns, children); + for (int i = startOfRow; i < endOfRow; i++) { + View child = getChildAt(i); + int width = child.getMeasuredWidth(); + int height = child.getMeasuredHeight(); + child.layout(x, y, x + width, y + height); + maxHeight = Math.max(maxHeight, height); + x += width + mHorizontalSpacing; + } + y += maxHeight; + if (row > 0) { + y += mVerticalSpacing; + } + } + } + + /** + * Bridges between a ViewGroup and a BaseAdapter. + * <p> + * Usage: {@code ViewGroupAdapterBridge.link(viewGroup, adapter)} + * <br /> + * After this call, the ViewGroup's children will be provided by the adapter. + */ + public static class ViewGroupAdapterBridge extends DataSetObserver { + + private final WeakReference<ViewGroup> mViewGroup; + private final BaseAdapter mAdapter; + private boolean mReleased; + + public static void link(ViewGroup viewGroup, BaseAdapter adapter) { + new ViewGroupAdapterBridge(viewGroup, adapter); + } + + private ViewGroupAdapterBridge(ViewGroup viewGroup, BaseAdapter adapter) { + mViewGroup = new WeakReference<>(viewGroup); + mAdapter = adapter; + mReleased = false; + mAdapter.registerDataSetObserver(this); + refresh(); + } + + private void refresh() { + if (mReleased) { + return; + } + ViewGroup viewGroup = mViewGroup.get(); + if (viewGroup == null) { + release(); + return; + } + final int childCount = viewGroup.getChildCount(); + final int adapterCount = mAdapter.getCount(); + final int N = Math.max(childCount, adapterCount); + for (int i = 0; i < N; i++) { + if (i < adapterCount) { + View oldView = null; + if (i < childCount) { + oldView = viewGroup.getChildAt(i); + } + View newView = mAdapter.getView(i, oldView, viewGroup); + if (oldView == null) { + // We ran out of existing views. Add it at the end. + viewGroup.addView(newView); + } else if (oldView != newView) { + // We couldn't rebind the view. Replace it. + viewGroup.removeViewAt(i); + viewGroup.addView(newView, i); + } + } else { + int lastIndex = viewGroup.getChildCount() - 1; + viewGroup.removeViewAt(lastIndex); + } + } + } + + @Override + public void onChanged() { + refresh(); + } + + @Override + public void onInvalidated() { + release(); + } + + private void release() { + if (!mReleased) { + mReleased = true; + mAdapter.unregisterDataSetObserver(this); + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 59f3b3d..3679b4c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -326,8 +326,11 @@ public class QSPanel extends ViewGroup { if (mFooter.hasFooter()) { h += mFooter.getView().getHeight(); } - mDetail.measure(exactly(width), exactly(h)); - setMeasuredDimension(width, h); + mDetail.measure(exactly(width), MeasureSpec.UNSPECIFIED); + if (mDetail.getMeasuredHeight() < h) { + mDetail.measure(exactly(width), exactly(h)); + } + setMeasuredDimension(width, Math.max(h, mDetail.getMeasuredHeight())); } private static int exactly(int size) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java index 8cff81a..c524edc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java @@ -17,45 +17,24 @@ package com.android.systemui.qs.tiles; import com.android.systemui.R; +import com.android.systemui.qs.PseudoGridView; import com.android.systemui.statusbar.policy.UserSwitcherController; import android.content.Context; -import android.content.Intent; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.GridView; /** * Quick settings detail view for user switching. */ -public class UserDetailView extends GridView { +public class UserDetailView extends PseudoGridView { - public UserDetailView(Context context) { - this(context, null); - } + private Adapter mAdapter; public UserDetailView(Context context, AttributeSet attrs) { - this(context, attrs, android.R.attr.gridViewStyle); - } - - public UserDetailView(Context context, AttributeSet attrs, int defStyleAttr) { - this(context, attrs, defStyleAttr, 0); - } - - public UserDetailView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - - setOnItemClickListener(new OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - UserSwitcherController.UserRecord tag = - (UserSwitcherController.UserRecord) view.getTag(); - ((Adapter)getAdapter()).switchTo(tag); - } - }); + super(context, attrs); } public static UserDetailView inflate(Context context, ViewGroup parent, boolean attach) { @@ -64,10 +43,12 @@ public class UserDetailView extends GridView { } public void createAndSetAdapter(UserSwitcherController controller) { - setAdapter(new Adapter(mContext, controller)); + mAdapter = new Adapter(mContext, controller); + ViewGroupAdapterBridge.link(this, mAdapter); } - public static class Adapter extends UserSwitcherController.BaseUserAdapter { + public static class Adapter extends UserSwitcherController.BaseUserAdapter + implements OnClickListener { private Context mContext; @@ -81,6 +62,9 @@ public class UserDetailView extends GridView { UserSwitcherController.UserRecord item = getItem(position); UserDetailItemView v = UserDetailItemView.convertOrInflate( mContext, convertView, parent); + if (v != convertView) { + v.setOnClickListener(this); + } String name = getName(mContext, item); if (item.picture == null) { v.bind(name, getDrawable(mContext, item)); @@ -91,5 +75,12 @@ public class UserDetailView extends GridView { v.setTag(item); return v; } + + @Override + public void onClick(View view) { + UserSwitcherController.UserRecord tag = + (UserSwitcherController.UserRecord) view.getTag(); + switchTo(tag); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index c48f3f5..a1993f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -465,12 +465,12 @@ public class UserSwitcherController { @Override public View createDetailView(Context context, View convertView, ViewGroup parent) { + UserDetailView v; if (!(convertView instanceof UserDetailView)) { - convertView = UserDetailView.inflate(context, parent, false); - } - UserDetailView v = (UserDetailView) convertView; - if (v.getAdapter() == null) { + v = UserDetailView.inflate(context, parent, false); v.createAndSetAdapter(UserSwitcherController.this); + } else { + v = (UserDetailView) convertView; } return v; } |