DO NOT MERGE: Merge Oreo MR1 into master
Exempt-From-Owner-Approval: Changes already landed internally
Change-Id: Id90b1b88a9de34a4003f0d9192e0ac5bdb862e6f
diff --git a/car-stream-ui-lib/car-stream-ui-lib.mk b/car-stream-ui-lib/car-stream-ui-lib.mk
index 86ad7a6..7f3db8e 100644
--- a/car-stream-ui-lib/car-stream-ui-lib.mk
+++ b/car-stream-ui-lib/car-stream-ui-lib.mk
@@ -52,6 +52,13 @@
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
endif
+# Include support-v7-recyclerview, if not already included
+ifeq (,$(findstring android-support-v7-recyclerview,$(LOCAL_STATIC_JAVA_LIBRARIES)))
+LOCAL_RESOURCE_DIR += frameworks/support/v7/recyclerview/res
+LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.recyclerview
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-recyclerview
+endif
+
# Include car-stream-ui-lib
ifeq (,$(findstring car-stream-ui-lib, $(LOCAL_STATIC_JAVA_LIBRARIES)))
LOCAL_RESOURCE_DIR += \
diff --git a/car-stream-ui-lib/res/layout/car_drawer_activity.xml b/car-stream-ui-lib/res/layout/car_drawer_activity.xml
index 17feb76..4fb9292 100644
--- a/car-stream-ui-lib/res/layout/car_drawer_activity.xml
+++ b/car-stream-ui-lib/res/layout/car_drawer_activity.xml
@@ -64,9 +64,9 @@
<!-- This keeps the toolbar centered within lens_header_height -->
<android.support.v7.widget.Toolbar
android:id="@+id/main_toolbar"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- style="@style/CarToolbarTheme" />
+ style="@style/CarToolbarTheme" />
</FrameLayout>
</FrameLayout>
diff --git a/car-stream-ui-lib/res/values-h480dp/dimens.xml b/car-stream-ui-lib/res/values-h480dp/dimens.xml
index 77f1c76..4da60ed 100644
--- a/car-stream-ui-lib/res/values-h480dp/dimens.xml
+++ b/car-stream-ui-lib/res/values-h480dp/dimens.xml
@@ -18,4 +18,8 @@
<dimen name="action_panel_height">128dp</dimen>
<dimen name="stream_fab_size">100dp</dimen>
<dimen name="stream_button_size">96dp</dimen>
+
+ <!-- Height of items in a list. -->
+ <dimen name="double_line_item_height">96dp</dimen>
+ <dimen name="single_line_item_height">76dp</dimen>
</resources>
diff --git a/car-stream-ui-lib/res/values-h552dp/dimens.xml b/car-stream-ui-lib/res/values-h552dp/dimens.xml
new file mode 100644
index 0000000..66daa2d
--- /dev/null
+++ b/car-stream-ui-lib/res/values-h552dp/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<resources>
+ <!-- Height of items in a list. -->
+ <dimen name="double_line_item_height">128dp</dimen>
+ <dimen name="single_line_item_height">128dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/car-stream-ui-lib/res/values/attrs.xml b/car-stream-ui-lib/res/values/attrs.xml
index 344b1a5..911f891 100644
--- a/car-stream-ui-lib/res/values/attrs.xml
+++ b/car-stream-ui-lib/res/values/attrs.xml
@@ -22,8 +22,17 @@
<attr name="glowColor" format="color" />
<!-- Whether offsetting the list view by the amount of left scroll bar -->
<attr name="offsetScrollBar" format="boolean" />
- <!-- Whether or not the list view is offset by the width of the scroll bar. -->
+ <!-- Whether or not to show a diving line between each item of the list. -->
<attr name="showDivider" format="boolean" />
+ <!-- An optional id that specifies a child View whose starting edge will be used to
+ determine the start position of the dividing line. -->
+ <attr name="alignDividerStartTo" format="reference" />
+ <!-- An optional id that specifies a child View whose ending edge will be used to
+ determine the end position of the dividing line. -->
+ <attr name="alignDividerEndTo" format="reference" />
+ <!-- A starting margin before the drawing of the dividing line. This margin will be an
+ offset from the view specified by "alignDividerStartTo" if given. -->
+ <attr name="dividerStartMargin" format="dimension" />
<!-- The width of the container for the scroll -->
<attr name="scrollbarContainerWidth" format="dimension" />
<!-- The width of the margin on the right side of the list -->
diff --git a/car-stream-ui-lib/res/values/dimens.xml b/car-stream-ui-lib/res/values/dimens.xml
index 3425277..3555501 100644
--- a/car-stream-ui-lib/res/values/dimens.xml
+++ b/car-stream-ui-lib/res/values/dimens.xml
@@ -99,7 +99,7 @@
<!-- Keylines for content within a card. -->
<dimen name="stream_card_keyline_1">24dp</dimen>
<dimen name="stream_card_keyline_2">96dp</dimen>
- <dimen name="stream_card_keyline_3">176dp</dimen>
+ <dimen name="stream_card_keyline_3">128dp</dimen>
<!-- The top margin before the start of content in an application. -->
<dimen name="lens_header_height">96dp</dimen>
@@ -138,4 +138,18 @@
<dimen name="search_suggestion_height">64dp</dimen>
<dimen name="searchview_margin_left">152dp</dimen>
<dimen name="searchview_margin_right">264dp</dimen>
+
+ <!-- The space on each side of the screen. Some common function widgets, like scroll bar,
+ can go into this space -->
+ <dimen name="side_margin">148dp</dimen>
+
+ <!-- Common icon size for car app -->
+ <dimen name="car_icon_size">44dp</dimen>
+
+ <!-- Touch target size for round or square affordance -->
+ <dimen name="car_touch_target">106dp</dimen>
+
+ <!-- Height of items in a list. -->
+ <dimen name="double_line_item_height">256dp</dimen>
+ <dimen name="single_line_item_height">256dp</dimen>
</resources>
diff --git a/car-stream-ui-lib/src/com/android/car/app/CarDrawerActivity.java b/car-stream-ui-lib/src/com/android/car/app/CarDrawerActivity.java
index c8bf22a..2c67562 100644
--- a/car-stream-ui-lib/src/com/android/car/app/CarDrawerActivity.java
+++ b/car-stream-ui-lib/src/com/android/car/app/CarDrawerActivity.java
@@ -94,6 +94,12 @@
setupDrawerToggling();
}
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mDrawerLayout.closeDrawer(Gravity.LEFT, false /* animation */);
+ }
+
private void setToolbarTitleFrom(CarDrawerAdapter adapter) {
if (adapter.getTitle() != null) {
mToolbar.setTitle(adapter.getTitle());
diff --git a/car-stream-ui-lib/src/com/android/car/view/PagedListView.java b/car-stream-ui-lib/src/com/android/car/view/PagedListView.java
index f0e93cd..6f5c294 100644
--- a/car-stream-ui-lib/src/com/android/car/view/PagedListView.java
+++ b/car-stream-ui-lib/src/com/android/car/view/PagedListView.java
@@ -16,11 +16,13 @@
package com.android.car.view;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
+import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
@@ -29,9 +31,7 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.FrameLayout;
-import android.widget.TextView;
import com.android.car.stream.ui.R;
@@ -48,6 +48,7 @@
* user holds down a pagination button.
*/
private static final int PAGINATION_HOLD_DELAY_MS = 400;
+ private static final int INVALID_RESOURCE_ID = -1;
private final CarRecyclerView mRecyclerView;
private final CarLayoutManager mLayoutManager;
@@ -85,7 +86,7 @@
* </pre>
*/
public interface ItemCap {
- public static final int UNLIMITED = -1;
+ int UNLIMITED = -1;
/**
* Sets the maximum number of items available in the adapter. A value less than '0'
@@ -125,19 +126,13 @@
FrameLayout maxWidthLayout = (FrameLayout) findViewById(R.id.max_width_layout);
LayoutParams params = (LayoutParams) maxWidthLayout.getLayoutParams();
params.leftMargin = scrollContainerWidth;
- int rightMargin = a.getDimensionPixelSize(R.styleable.PagedListView_rightMargin, 0);
- params.rightMargin = rightMargin;
+ params.rightMargin = a.getDimensionPixelSize(R.styleable.PagedListView_rightMargin, 0);
maxWidthLayout.setLayoutParams(params);
}
- boolean showDivider = a.getBoolean(R.styleable.PagedListView_showDivider, true);
- mDecor = showDivider
- ? new DividerDecoration(getContext()) : new NoDividerDecoration(getContext());
-
mRecyclerView = (CarRecyclerView) findViewById(R.id.recycler_view);
boolean fadeLastItem = a.getBoolean(R.styleable.PagedListView_fadeLastItem, false);
mRecyclerView.setFadeLastItem(fadeLastItem);
boolean offsetRows = a.getBoolean(R.styleable.PagedListView_offsetRows, false);
- a.recycle();
mMaxPages = getDefaultMaxPages();
@@ -145,11 +140,22 @@
mLayoutManager.setOffsetRows(offsetRows);
mLayoutManager.setItemsChangedListener(mItemsChangedListener);
mRecyclerView.setLayoutManager(mLayoutManager);
- mRecyclerView.addItemDecoration(mDecor);
mRecyclerView.setOnScrollListener(mOnScrollListener);
mRecyclerView.getRecycledViewPool().setMaxRecycledViews(0, 12);
mRecyclerView.setItemAnimator(new CarItemAnimator(mLayoutManager));
+ if (a.getBoolean(R.styleable.PagedListView_showDivider, true)) {
+ int dividerStartMargin = a.getDimensionPixelSize(
+ R.styleable.PagedListView_dividerStartMargin, 0);
+ int dividerStartId = a.getResourceId(R.styleable.PagedListView_alignDividerStartTo,
+ INVALID_RESOURCE_ID);
+ int dividerEndId = a.getResourceId(R.styleable.PagedListView_alignDividerEndTo,
+ INVALID_RESOURCE_ID);
+
+ mRecyclerView.addItemDecoration(new DividerDecoration(context, dividerStartMargin,
+ dividerStartId, dividerEndId));
+ }
+
mScrollBarView = (PagedScrollBarView) findViewById(R.id.paged_scroll_view);
mScrollBarView.setPaginationListener(new PagedScrollBarView.PaginationListener() {
@Override
@@ -166,6 +172,8 @@
setAutoDayNightMode();
updatePaginationButtons(false /*animate*/);
+
+ a.recycle();
}
@Override
@@ -253,16 +261,6 @@
mMaxPages = getDefaultMaxPages();
}
- public void setDefaultItemDecoration(DividerDecoration decor) {
- removeDefaultItemDecoration();
- mDecor = decor;
- addItemDecoration(mDecor);
- }
-
- public void removeDefaultItemDecoration() {
- mRecyclerView.removeItemDecoration(mDecor);
- }
-
public void addItemDecoration(@NonNull RecyclerView.ItemDecoration decor) {
mRecyclerView.addItemDecoration(decor);
}
@@ -271,19 +269,26 @@
mRecyclerView.removeItemDecoration(decor);
}
+ /**
+ * Sets the scrollbars of this PagedListView to change from light to dark colors depending on
+ * whether or not device is in night mode.
+ */
public void setAutoDayNightMode() {
mScrollBarView.setAutoDayNightMode();
- mDecor.updateDividerColor();
}
+ /**
+ * Sets the scrollbars of this PagedListView to be light colors.
+ */
public void setLightMode() {
mScrollBarView.setLightMode();
- mDecor.updateDividerColor();
}
+ /**
+ * Sets the scrollbars of this PagedListView to be dark colors.
+ */
public void setDarkMode() {
mScrollBarView.setDarkMode();
- mDecor.updateDividerColor();
}
public void setOnScrollBarListener(OnScrollBarListener listener) {
@@ -474,96 +479,67 @@
public void onLeaveBottom() {}
}
+ /**
+ * A {@link android.support.v7.widget.RecyclerView.ItemDecoration} that will draw a dividing
+ * line between each item in the RecyclerView that it is added to.
+ */
public static class DividerDecoration extends RecyclerView.ItemDecoration {
- protected final Paint mPaint;
- protected final int mDividerHeight;
- protected final Context mContext;
+ private final Paint mPaint;
+ private final int mDividerHeight;
+ private final int mDividerStartMargin;
+ @IdRes private final int mDividerStartId;
+ @IdRes private final int mDvidierEndId;
+ /**
+ * @param dividerStartMargin The start offset of the dividing line. This offset will be
+ * relative to {@code dividerStartId} if that value is given.
+ * @param dividerStartId A child view id whose starting edge will be used as the starting
+ * edge of the dividing line. If this value is
+ * {@link #INVALID_RESOURCE_ID}, the the top container of each
+ * child view will be used.
+ * @param dividerEndId A child view id whose ending edge will be used as the starting edge
+ * of the dividing lin.e If this value is {@link #INVALID_RESOURCE_ID},
+ * then the top container view of each child will be used.
+ */
+ private DividerDecoration(Context context, int dividerStartMargin,
+ @IdRes int dividerStartId, @IdRes int dividerEndId) {
+ mDividerStartMargin = dividerStartMargin;
+ mDividerStartId = dividerStartId;
+ mDvidierEndId = dividerEndId;
- public DividerDecoration(Context context) {
- mContext = context;
+ Resources res = context.getResources();
mPaint = new Paint();
- updateDividerColor();
- mDividerHeight = mContext.getResources()
- .getDimensionPixelSize(R.dimen.car_divider_height);
+ mPaint.setColor(res.getColor(R.color.car_list_divider));
+ mDividerHeight = res.getDimensionPixelSize(R.dimen.car_divider_height);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
- final int left = getLeft(parent.getChildAt(0));
- final int right = parent.getWidth() - parent.getPaddingRight();
- int top;
- int bottom;
+ for (int i = 0, childCount = parent.getChildCount(); i < childCount; i++) {
+ View container = parent.getChildAt(i);
+ View startChild = mDividerStartId != INVALID_RESOURCE_ID
+ ? container.findViewById(mDividerStartId)
+ : container;
- c.drawRect(left, 0, right, mDividerHeight, mPaint);
+ View endChild = mDvidierEndId != INVALID_RESOURCE_ID
+ ? container.findViewById(mDvidierEndId)
+ : container;
- final int childCount = parent.getChildCount();
- for (int i = 0; i < childCount; i++) {
- final View child = parent.getChildAt(i);
- final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
- .getLayoutParams();
- bottom = child.getBottom() - params.bottomMargin;
- top = bottom - mDividerHeight;
- if (top > 0) {
+ if (startChild == null || endChild == null) {
+ continue;
+ }
+
+ int left = mDividerStartMargin + startChild.getLeft();
+ int right = endChild.getRight();
+ int bottom = container.getBottom();
+ int top = bottom - mDividerHeight;
+
+ // Draw a divider line between each item. No need to draw the line for the last
+ // item.
+ if (i != childCount - 1) {
c.drawRect(left, top, right, bottom, mPaint);
}
}
}
-
- /**
- * Updates the list divider color which may have changed due to a day night transition.
- */
- public void updateDividerColor() {
- mPaint.setColor(mContext.getResources().getColor(R.color.car_list_divider));
- }
-
- /**
- * Find the left edge of the decoration line. It should be left aligned with the left edge
- * of the first {@link android.widget.TextView}.
- */
- private int getLeft(View root) {
- if (root == null) {
- return 0;
- }
- View view = findTextView(root);
- if (view == null) {
- view = root;
- }
- int left = 0;
- while (view != null && view != root) {
- left += view.getLeft();
- view = (View) view.getParent();
- }
- return left;
- }
-
- private TextView findTextView(View root) {
- if (root == null) {
- return null;
- }
- if (root instanceof TextView) {
- return (TextView) root;
- }
- if (root instanceof ViewGroup) {
- ViewGroup parent = (ViewGroup) root;
- final int childCount = parent.getChildCount();
- for(int i = 0; i < childCount; i++) {
- TextView tv = findTextView(parent.getChildAt(i));
- if (tv != null) {
- return tv;
- }
- }
- }
- return null;
- }
- }
-
- public static class NoDividerDecoration extends DividerDecoration {
- public NoDividerDecoration(Context context) {
- super(context);
- }
-
- @Override
- public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {}
}
}