More app bar support in GlifLayout

- Add app:suwStickyHeader attribute to GlifLayout to specify a
  custom app bar layout, which can be a Toolbar.
- Create indirection attribute ?attr/suwGlifIconStyle to allow apps
  to override the GLIF icon style.

Test: ./gradlew test
Bug: 68826871
Change-Id: I6384db970582c56431b6085bb172f6ca28099f9d
This commit is contained in:
Maurice Lam 2018-01-02 20:45:07 -08:00
parent 5153bc0ae2
commit 3a3d478a4b
13 changed files with 95 additions and 9 deletions

View file

@ -109,6 +109,7 @@
<item name="suwDividerInsetStart">@dimen/suw_items_glif_icon_divider_inset</item>
<item name="suwDividerInsetStartNoIcon">@dimen/suw_items_glif_text_divider_inset</item>
<item name="suwGlifHeaderGravity">start</item>
<item name="suwGlifIconStyle">@style/SuwGlifIcon</item>
<item name="suwItemDescriptionStyle">@style/SuwItemContainer.Description.Glif</item>
<item name="suwItemDescriptionTitleStyle">@style/SuwItemTitle.GlifDescription</item>
<item name="suwListItemIconColor">@color/suw_list_item_icon_color_dark</item>
@ -144,6 +145,7 @@
<item name="suwDividerInsetStart">@dimen/suw_items_glif_icon_divider_inset</item>
<item name="suwDividerInsetStartNoIcon">@dimen/suw_items_glif_text_divider_inset</item>
<item name="suwGlifHeaderGravity">start</item>
<item name="suwGlifIconStyle">@style/SuwGlifIcon</item>
<item name="suwItemDescriptionStyle">@style/SuwItemContainer.Description.Glif</item>
<item name="suwItemDescriptionTitleStyle">@style/SuwItemTitle.GlifDescription</item>
<item name="suwListItemIconColor">@color/suw_list_item_icon_color_light</item>

View file

@ -21,6 +21,11 @@
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub
android:id="@+id/suw_layout_sticky_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/suw_layout_content"
android:layout_width="match_parent"

View file

@ -23,7 +23,7 @@
<ImageView
android:id="@+id/suw_layout_icon"
style="@style/SuwGlifIcon"
style="?attr/suwGlifIconStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"

View file

@ -22,6 +22,11 @@
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub
android:id="@+id/suw_layout_sticky_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- Ignore UnusedAttribute: scrollIndicators is new in M. Default to no indicators in older
versions. -->
<com.android.setupwizardlib.view.StickyHeaderListView

View file

@ -22,6 +22,11 @@
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub
android:id="@+id/suw_layout_sticky_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- Ignore UnusedAttribute: scrollIndicators is new in M. Default to no indicators in older
versions. -->
<com.android.setupwizardlib.view.BottomScrollView

View file

@ -38,13 +38,14 @@
<!-- Push object to the end of its container, not changing its size. -->
<flag name="end" value="0x00800005" />
</attr>
<attr name="suwGlifIconStyle" format="reference" />
<attr name="suwCardBackground" format="color|reference" />
<attr name="suwFillContentLayoutStyle" format="reference" />
<attr name="suwDividerCondition">
<enum name="either" value="0" />
<enum name="both" value="1" />
</attr>
<attr name="suwFillContentLayoutStyle" format="reference" />
<attr name="suwListItemIconColor" format="color" />
<attr name="suwNavBarBackgroundColor" format="color" />
<attr name="suwNavBarButtonBackground" format="color|reference" />
@ -104,6 +105,7 @@
<attr name="suwColorPrimary" />
<attr name="suwFooter" format="reference" />
<attr name="suwLayoutFullscreen" format="boolean" />
<attr name="suwStickyHeader" format="reference" />
</declare-styleable>
<declare-styleable name="SuwStatusBarBackgroundLayout">

View file

@ -141,6 +141,11 @@ public class GlifLayout extends TemplateLayout {
inflateFooter(footer);
}
final int stickyHeader = a.getResourceId(R.styleable.SuwGlifLayout_suwStickyHeader, 0);
if (stickyHeader != 0) {
inflateStickyHeader(stickyHeader);
}
mLayoutFullscreen = a.getBoolean(R.styleable.SuwGlifLayout_suwLayoutFullscreen, true);
a.recycle();
@ -168,17 +173,31 @@ public class GlifLayout extends TemplateLayout {
/**
* Sets the footer of the layout, which is at the bottom of the content area outside the
* scrolling container. The footer can only be inflated once per layout.
* scrolling container. The footer can only be inflated once per instance of this layout.
*
* @param footer The layout to be inflated as footer.
* @return The root of the inflated footer view.
*/
public View inflateFooter(@LayoutRes int footer) {
ViewStub footerStub = (ViewStub) findManagedViewById(R.id.suw_layout_footer);
ViewStub footerStub = findManagedViewById(R.id.suw_layout_footer);
footerStub.setLayoutResource(footer);
return footerStub.inflate();
}
/**
* Sets the sticky header (i.e. header that doesn't scroll) of the layout, which is at the top
* of the content area outside of the scrolling container. The header can only be inflated once
* per instance of this layout.
*
* @param header The layout to be inflated as the header.
* @return The root of the inflated header view.
*/
public View inflateStickyHeader(@LayoutRes int header) {
ViewStub stickyHeaderStub = findManagedViewById(R.id.suw_layout_sticky_header);
stickyHeaderStub.setLayoutResource(header);
return stickyHeaderStub.inflate();
}
public ScrollView getScrollView() {
final View view = findManagedViewById(R.id.suw_scroll_view);
return view instanceof ScrollView ? (ScrollView) view : null;

View file

@ -103,7 +103,7 @@ public class TemplateLayout extends FrameLayout {
* by this view but not currently added to the view hierarchy. e.g. recycler view or list view
* headers that are not currently shown.
*/
public View findManagedViewById(int id) {
public <T extends View> T findManagedViewById(int id) {
return findViewById(id);
}

View file

@ -108,6 +108,7 @@
<item name="suwDividerInsetStart">@dimen/suw_items_glif_icon_divider_inset</item>
<item name="suwDividerInsetStartNoIcon">@dimen/suw_items_glif_text_divider_inset</item>
<item name="suwGlifHeaderGravity">start</item>
<item name="suwGlifIconStyle">@style/SuwGlifIcon</item>
<item name="suwItemDescriptionStyle">@style/SuwItemContainer.Description.Glif</item>
<item name="suwItemDescriptionTitleStyle">@style/SuwItemTitle.GlifDescription</item>
<item name="suwListItemIconColor">@color/suw_list_item_icon_color_dark</item>
@ -140,6 +141,7 @@
<item name="suwDividerInsetStart">@dimen/suw_items_glif_icon_divider_inset</item>
<item name="suwDividerInsetStartNoIcon">@dimen/suw_items_glif_text_divider_inset</item>
<item name="suwGlifHeaderGravity">start</item>
<item name="suwGlifIconStyle">@style/SuwGlifIcon</item>
<item name="suwItemDescriptionStyle">@style/SuwItemContainer.Description.Glif</item>
<item name="suwItemDescriptionTitleStyle">@style/SuwItemTitle.GlifDescription</item>
<item name="suwListItemIconColor">@color/suw_list_item_icon_color_light</item>

View file

@ -23,6 +23,11 @@
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub
android:id="@+id/suw_layout_sticky_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- Ignore UnusedAttribute: scrollIndicators is new in M. Default to no indicators in older
versions. -->
<com.android.setupwizardlib.view.HeaderRecyclerView

View file

@ -107,10 +107,10 @@ public class GlifRecyclerLayout extends GlifLayout {
}
@Override
public View findManagedViewById(int id) {
public <T extends View> T findManagedViewById(int id) {
final View header = mRecyclerMixin.getHeader();
if (header != null) {
final View view = header.findViewById(id);
final T view = header.findViewById(id);
if (view != null) {
return view;
}

View file

@ -127,10 +127,10 @@ public class SetupWizardRecyclerLayout extends SetupWizardLayout {
}
@Override
public View findManagedViewById(int id) {
public <T extends View> T findManagedViewById(int id) {
final View header = mRecyclerMixin.getHeader();
if (header != null) {
final View view = header.findViewById(id);
final T view = header.findViewById(id);
if (view != null) {
return view;
}

View file

@ -267,6 +267,47 @@ public class GlifLayoutTest {
assertNotNull(layout.findViewById(android.R.id.text1));
}
@Test
public void inflateStickyHeader_shouldAddViewToLayout() {
GlifLayout layout = new GlifLayout(mContext);
final View view = layout.inflateStickyHeader(android.R.layout.simple_list_item_1);
assertEquals(android.R.id.text1, view.getId());
assertNotNull(layout.findViewById(android.R.id.text1));
}
@Config(qualifiers = "sw600dp")
@Test
public void inflateStickyHeader_whenOnTablets_shouldAddViewToLayout() {
inflateStickyHeader_shouldAddViewToLayout();
}
@Test
public void inflateStickyHeader_whenInXml_shouldAddViewToLayout() {
GlifLayout layout = new GlifLayout(
mContext,
Robolectric.buildAttributeSet()
.addAttribute(R.attr.suwStickyHeader, "@android:layout/simple_list_item_1")
.build());
assertNotNull(layout.findViewById(android.R.id.text1));
}
@Test
public void inflateStickyHeader_whenOnBlankTemplate_shouldAddViewToLayout() {
GlifLayout layout = new GlifLayout(mContext, R.layout.suw_glif_blank_template);
final View view = layout.inflateStickyHeader(android.R.layout.simple_list_item_1);
assertEquals(android.R.id.text1, view.getId());
assertNotNull(layout.findViewById(android.R.id.text1));
}
@Config(qualifiers = "sw600dp")
@Test
public void inflateStickyHeader_whenOnBlankTemplateTablet_shouldAddViewToLayout() {
inflateStickyHeader_whenOnBlankTemplate_shouldAddViewToLayout();
}
@Config(sdk = { VERSION_CODES.M, Config.NEWEST_SDK })
@Test
public void createFromXml_shouldSetLayoutFullscreen_whenLayoutFullscreenIsNotSet() {