Merge "HeaderBuilder should have overloaded methods for loading" into pi-preview1-androidx-dev
diff --git a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
index a1bd996..0901724 100644
--- a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
+++ b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
@@ -34,6 +34,7 @@
import android.text.SpannableString;
import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
+import android.util.SparseArray;
import java.util.Calendar;
@@ -60,11 +61,9 @@
public static final String ACTION_TOAST_RANGE_VALUE =
"com.example.androidx.slice.action.TOAST_RANGE_VALUE";
- public static final int LOADING_DELAY_MS = 4000;
-
public static final String[] URI_PATHS = {"message", "wifi", "note", "ride", "toggle",
- "toggle2", "contact", "gallery", "weather", "reservation", "loadlist", "loadlist2",
- "loadgrid", "loadgrid2", "inputrange", "range", "contact2", "subscription"};
+ "toggle2", "contact", "gallery", "weather", "reservation", "loadlist", "loadgrid",
+ "inputrange", "range", "contact2", "subscription"};
/**
* @return Uri with the provided path
@@ -91,6 +90,14 @@
@Override
public Slice onBindSlice(Uri sliceUri) {
String path = sliceUri.getPath();
+ if (!path.equals("/loadlist")) {
+ mListSummaries.clear();
+ mListLastUpdate = 0;
+ }
+ if (!path.equals("/loadgrid")) {
+ mGridSummaries.clear();
+ mGridLastUpdate = 0;
+ }
switch (path) {
// TODO: add list / grid slices with 'see more' options
case "/message":
@@ -116,13 +123,9 @@
case "/reservation":
return createReservationSlice(sliceUri);
case "/loadlist":
- return createLoadingSlice(sliceUri, false /* loadAll */, true /* isList */);
- case "/loadlist2":
- return createLoadingSlice(sliceUri, true /* loadAll */, true /* isList */);
+ return createLoadingListSlice(sliceUri);
case "/loadgrid":
- return createLoadingSlice(sliceUri, false /* loadAll */, false /* isList */);
- case "/loadgrid2":
- return createLoadingSlice(sliceUri, true /* loadAll */, false /* isList */);
+ return createLoadingGridSlice(sliceUri);
case "/inputrange":
return createStarRatingInputRange(sliceUri);
case "/range":
@@ -545,90 +548,84 @@
}
private Handler mHandler = new Handler();
- private Runnable mLoader;
- private boolean mLoaded = false;
+ private SparseArray<String> mListSummaries = new SparseArray<>();
+ private long mListLastUpdate;
+ private SparseArray<String> mGridSummaries = new SparseArray<>();
+ private long mGridLastUpdate;
- private Slice createLoadingSlice(Uri sliceUri, boolean loadAll, boolean isList) {
- if (!mLoaded || mLoader != null) {
- // Need to load content or we're still loading so just return partial
- if (!mLoaded) {
- mLoader = () -> {
- // Note that we've loaded things
- mLoader = null;
- mLoaded = true;
- // Notify to update the slice
- getContext().getContentResolver().notifyChange(sliceUri, null);
- };
- mHandler.postDelayed(mLoader, LOADING_DELAY_MS);
- }
- if (loadAll) {
- return new ListBuilder(getContext(), sliceUri).build();
- }
- return createPartialSlice(sliceUri, true, isList);
- } else {
- mLoaded = false;
- return createPartialSlice(sliceUri, false, isList);
+ private void update(long delay, SparseArray<String> summaries, int id, String s, Uri uri,
+ Runnable r) {
+ mHandler.postDelayed(() -> {
+ summaries.put(id, s);
+ getContext().getContentResolver().notifyChange(uri, null);
+ r.run();
+ }, delay);
+ }
+
+ private Slice createLoadingListSlice(Uri sliceUri) {
+ boolean updating = mListLastUpdate == 0
+ || mListLastUpdate < (System.currentTimeMillis() - 10 * System.currentTimeMillis());
+ if (updating) {
+ Runnable r = () -> mListLastUpdate = System.currentTimeMillis();
+ update(1000, mListSummaries, 0, "44 miles | 1 hour 45 min | $31.41", sliceUri, r);
+ update(1500, mListSummaries, 1, "12 miles | 12 min | $9.00", sliceUri, r);
+ update(1700, mListSummaries, 2, "5 miles | 10 min | $8.00", sliceUri, r);
}
+ Slice s = new ListBuilder(getContext(), sliceUri)
+ .addRow(b -> b
+ .setTitle("Work")
+ .setSubtitle(mListSummaries.get(0, ""), updating)
+ .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_work),
+ ICON_IMAGE))
+ .addRow(b -> b
+ .setTitle("Home")
+ .setSubtitle(mListSummaries.get(1, ""), updating)
+ .addEndItem(
+ Icon.createWithResource(getContext(), R.drawable.ic_home),
+ ICON_IMAGE))
+ .addRow(b -> b
+ .setTitle("School")
+ .setSubtitle(mListSummaries.get(2, ""), updating)
+ .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_school),
+ ICON_IMAGE))
+ .build();
+ return s;
}
- private Slice createPartialSlice(Uri sliceUri, boolean isPartial, boolean isList) {
- Icon icon = Icon.createWithResource(getContext(), R.drawable.ic_star_on);
- PendingIntent intent = getBroadcastIntent(ACTION_TOAST, "star tapped");
- PendingIntent intent2 = getBroadcastIntent(ACTION_TOAST, "toggle tapped");
- if (isPartial) {
- if (isList) {
- return new ListBuilder(getContext(), sliceUri)
- .addRow(b -> createRow(b, "Slice that has content to load",
- "Temporary subtitle", icon, intent, true))
- .addRow(b -> createRow(b, null, null, null, intent, true))
- .addRow(b -> b
- .setTitle("My title")
- .addEndItem(new SliceAction(intent2, "Some action",
- false /* isChecked */),
- true /* isLoading */))
- .build();
- } else {
- return new ListBuilder(getContext(), sliceUri).addGrid(gb -> gb
- .addCell(b -> createCell(b, null, null, null, true))
- .addCell(b -> createCell(b, "Two stars", null, icon, true))
- .addCell(b -> createCell(b, null, null, null, true)))
- .build();
- }
- } else {
- if (isList) {
- return new ListBuilder(getContext(), sliceUri)
- .addRow(b -> createRow(b, "Slice that has content to load",
- "Subtitle loaded", icon, intent, false))
- .addRow(b -> createRow(b, "Loaded row", "Loaded subtitle",
- icon, intent, false))
- .addRow(b -> b
- .setTitle("My title")
- .addEndItem(new SliceAction(intent2, "Some action",
- false /* isChecked */)))
- .build();
- } else {
- return new ListBuilder(getContext(), sliceUri).addGrid(gb -> gb
- .addCell(b -> createCell(b, "One star", "meh", icon, false))
- .addCell(b -> createCell(b, "Two stars", "good", icon, false))
- .addCell(b -> createCell(b, "Three stars", "best", icon, false)))
- .build();
- }
+ private Slice createLoadingGridSlice(Uri sliceUri) {
+ boolean updating = mGridLastUpdate == 0
+ || mGridLastUpdate < (System.currentTimeMillis() - 10 * System.currentTimeMillis());
+ if (updating) {
+ Runnable r = () -> mGridLastUpdate = System.currentTimeMillis();
+ update(2000, mGridSummaries, 0, "Heavy traffic in your area", sliceUri, r);
+ update(3500, mGridSummaries, 1, "Typical conditions with delays up to 28 min",
+ sliceUri, r);
+ update(3000, mGridSummaries, 2, "41 min", sliceUri, r);
+ update(1500, mGridSummaries, 3, "33 min", sliceUri, r);
+ update(1000, mGridSummaries, 4, "12 min", sliceUri, r);
}
- }
-
- private ListBuilder.RowBuilder createRow(ListBuilder.RowBuilder rb, String title,
- String subtitle, Icon icon, PendingIntent content, boolean isLoading) {
- SliceAction primaryAction = new SliceAction(content, icon, title);
- return rb.setTitle(title, isLoading)
- .setSubtitle(subtitle, isLoading)
- .addEndItem(icon, isLoading)
- .setPrimaryAction(primaryAction);
- }
-
- private GridBuilder.CellBuilder createCell(GridBuilder.CellBuilder cb, String text1,
- String text2, Icon icon, boolean isLoading) {
- return cb.addText(text1, isLoading).addText(text2, isLoading).addImage(icon,
- SMALL_IMAGE, isLoading);
+ Slice s = new ListBuilder(getContext(), sliceUri)
+ .setHeader(hb -> hb
+ .setTitle(mGridSummaries.get(0, ""), updating)
+ .setSubtitle(mGridSummaries.get(1, ""), updating))
+ .addGrid(gb -> gb
+ .addCell(cb -> cb
+ .addImage(Icon.createWithResource(getContext(), R.drawable.ic_home),
+ ICON_IMAGE)
+ .addTitleText("Home")
+ .addText(mGridSummaries.get(2, ""), updating))
+ .addCell(cb -> cb
+ .addImage(Icon.createWithResource(getContext(), R.drawable.ic_work),
+ ICON_IMAGE)
+ .addTitleText("Work")
+ .addText(mGridSummaries.get(3, ""), updating))
+ .addCell(cb -> cb
+ .addImage(Icon.createWithResource(getContext(), R.drawable.ic_school),
+ ICON_IMAGE)
+ .addTitleText("School")
+ .addText(mGridSummaries.get(4, ""), updating)))
+ .build();
+ return s;
}
private PendingIntent getIntent(String action) {
diff --git a/samples/SupportSliceDemos/src/main/res/drawable/ic_school.xml b/samples/SupportSliceDemos/src/main/res/drawable/ic_school.xml
new file mode 100644
index 0000000..139d6a4
--- /dev/null
+++ b/samples/SupportSliceDemos/src/main/res/drawable/ic_school.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ Copyright 2018 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M5,13.18v4L12,21l7,-3.82v-4L12,17l-7,-3.82zM12,3L1,9l11,6 9,-4.91V17h2V9L12,3z"/>
+</vector>
diff --git a/slices/builders/api/current.txt b/slices/builders/api/current.txt
index 89275b9..cc12c11 100644
--- a/slices/builders/api/current.txt
+++ b/slices/builders/api/current.txt
@@ -57,8 +57,11 @@
method public androidx.slice.builders.ListBuilder.HeaderBuilder setContentDescription(java.lang.CharSequence);
method public androidx.slice.builders.ListBuilder.HeaderBuilder setPrimaryAction(androidx.slice.builders.SliceAction);
method public androidx.slice.builders.ListBuilder.HeaderBuilder setSubtitle(java.lang.CharSequence);
+ method public androidx.slice.builders.ListBuilder.HeaderBuilder setSubtitle(java.lang.CharSequence, boolean);
method public androidx.slice.builders.ListBuilder.HeaderBuilder setSummarySubtitle(java.lang.CharSequence);
+ method public androidx.slice.builders.ListBuilder.HeaderBuilder setSummarySubtitle(java.lang.CharSequence, boolean);
method public androidx.slice.builders.ListBuilder.HeaderBuilder setTitle(java.lang.CharSequence);
+ method public androidx.slice.builders.ListBuilder.HeaderBuilder setTitle(java.lang.CharSequence, boolean);
}
public static class ListBuilder.InputRangeBuilder extends androidx.slice.builders.TemplateSliceBuilder {
diff --git a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
index 5e8179c..4178040 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
@@ -846,7 +846,15 @@
*/
@NonNull
public HeaderBuilder setTitle(@NonNull CharSequence title) {
- mImpl.setTitle(title);
+ return setTitle(title, false /* isLoading */);
+ }
+
+ /**
+ * Sets the title to be shown in this header.
+ */
+ @NonNull
+ public HeaderBuilder setTitle(@NonNull CharSequence title, boolean isLoading) {
+ mImpl.setTitle(title, isLoading);
return this;
}
@@ -855,7 +863,15 @@
*/
@NonNull
public HeaderBuilder setSubtitle(@NonNull CharSequence subtitle) {
- mImpl.setSubtitle(subtitle);
+ return setSubtitle(subtitle, false /* isLoading */);
+ }
+
+ /**
+ * Sets the subtitle to be shown in this header.
+ */
+ @NonNull
+ public HeaderBuilder setSubtitle(@NonNull CharSequence subtitle, boolean isLoading) {
+ mImpl.setSubtitle(subtitle, isLoading);
return this;
}
@@ -866,7 +882,18 @@
*/
@NonNull
public HeaderBuilder setSummarySubtitle(@NonNull CharSequence summarySubtitle) {
- mImpl.setSummarySubtitle(summarySubtitle);
+ return setSummarySubtitle(summarySubtitle, false /* isLoading */);
+ }
+
+ /**
+ * Sets the summary subtitle to be shown in this header. If unset, the normal subtitle
+ * will be used. The summary is used when the parent template is presented in a
+ * small format.
+ */
+ @NonNull
+ public HeaderBuilder setSummarySubtitle(@NonNull CharSequence summarySubtitle,
+ boolean isLoading) {
+ mImpl.setSummarySubtitle(summarySubtitle, isLoading);
return this;
}
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
index 2ea33e3..7f9a57e 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
@@ -302,19 +302,19 @@
/**
* Sets the title to be shown in this header.
*/
- void setTitle(CharSequence title);
+ void setTitle(CharSequence title, boolean isLoading);
/**
* Sets the subtitle to be shown in this header.
*/
- void setSubtitle(CharSequence subtitle);
+ void setSubtitle(CharSequence subtitle, boolean isLoading);
/**
* Sets the summary subtitle to be shown in this header. If unset, the normal subtitle
* will be used. The summary is used when the parent template is presented in a
* small format.
*/
- void setSummarySubtitle(CharSequence summarySubtitle);
+ void setSummarySubtitle(CharSequence summarySubtitle, boolean isLoading);
/**
* Sets the action to invoke when the header is activated.
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
index 7c283dd..c8750bc 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
@@ -306,21 +306,21 @@
/**
*/
@Override
- public void setTitle(CharSequence title) {
+ public void setTitle(CharSequence title, boolean isLoading) {
}
/**
*/
@Override
- public void setSubtitle(CharSequence subtitle) {
+ public void setSubtitle(CharSequence subtitle, boolean isLoading) {
}
/**
*/
@Override
- public void setSummarySubtitle(CharSequence summarySubtitle) {
+ public void setSummarySubtitle(CharSequence summarySubtitle, boolean isLoading) {
}
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
index 9c0ca5d..778c54b 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
@@ -514,9 +514,9 @@
public static class HeaderBuilderImpl extends TemplateBuilderImpl
implements ListBuilder.HeaderBuilder {
- private CharSequence mTitle;
- private CharSequence mSubtitle;
- private CharSequence mSummarySubtitle;
+ private SliceItem mTitleItem;
+ private SliceItem mSubtitleItem;
+ private SliceItem mSummaryItem;
private SliceAction mPrimaryAction;
private CharSequence mContentDescr;
@@ -536,14 +536,14 @@
*/
@Override
public void apply(Slice.Builder b) {
- if (mTitle != null) {
- b.addText(mTitle, null /* subtype */, HINT_TITLE);
+ if (mTitleItem != null) {
+ b.addItem(mTitleItem);
}
- if (mSubtitle != null) {
- b.addText(mSubtitle, null /* subtype */);
+ if (mSubtitleItem != null) {
+ b.addItem(mSubtitleItem);
}
- if (mSummarySubtitle != null) {
- b.addText(mSummarySubtitle, null /* subtype */, HINT_SUMMARY);
+ if (mSummaryItem != null) {
+ b.addItem(mSummaryItem);
}
if (mContentDescr != null) {
b.addText(mContentDescr, SUBTYPE_CONTENT_DESCRIPTION);
@@ -558,22 +558,32 @@
/**
*/
@Override
- public void setTitle(CharSequence title) {
- mTitle = title;
+ public void setTitle(CharSequence title, boolean isLoading) {
+ mTitleItem = new SliceItem(title, FORMAT_TEXT, null, new String[] {HINT_TITLE});
+ if (isLoading) {
+ mTitleItem.addHint(HINT_PARTIAL);
+ }
}
/**
*/
@Override
- public void setSubtitle(CharSequence subtitle) {
- mSubtitle = subtitle;
+ public void setSubtitle(CharSequence subtitle, boolean isLoading) {
+ mSubtitleItem = new SliceItem(subtitle, FORMAT_TEXT, null, new String[0]);
+ if (isLoading) {
+ mSubtitleItem.addHint(HINT_PARTIAL);
+ }
}
/**
*/
@Override
- public void setSummarySubtitle(CharSequence summarySubtitle) {
- mSummarySubtitle = summarySubtitle;
+ public void setSummarySubtitle(CharSequence summarySubtitle, boolean isLoading) {
+ mSummaryItem = new SliceItem(summarySubtitle, FORMAT_TEXT, null,
+ new String[] {HINT_SUMMARY});
+ if (isLoading) {
+ mSummaryItem.addHint(HINT_PARTIAL);
+ }
}
/**