Merge "Fix build for VDC" into mnc-ub-dev
diff --git a/design/api/current.txt b/design/api/current.txt
index d354ec0..39518ba 100644
--- a/design/api/current.txt
+++ b/design/api/current.txt
@@ -89,8 +89,8 @@
public static abstract class BottomSheetBehavior.BottomSheetCallback {
ctor public BottomSheetBehavior.BottomSheetCallback();
- method public abstract void onSlide(float);
- method public abstract void onStateChanged(int);
+ method public abstract void onSlide(android.view.View, float);
+ method public abstract void onStateChanged(android.view.View, int);
}
protected static class BottomSheetBehavior.SavedState extends android.view.View.BaseSavedState {
diff --git a/design/src/android/support/design/widget/BottomSheetBehavior.java b/design/src/android/support/design/widget/BottomSheetBehavior.java
index bb9fe79..aa39ddd 100644
--- a/design/src/android/support/design/widget/BottomSheetBehavior.java
+++ b/design/src/android/support/design/widget/BottomSheetBehavior.java
@@ -22,6 +22,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
import android.support.design.R;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.NestedScrollingChild;
@@ -52,19 +53,21 @@
/**
* Called when the bottom sheet changes its state.
*
- * @param newState The new state. This will be one of {@link #STATE_DRAGGING},
- * {@link #STATE_SETTLING}, {@link #STATE_EXPANDED},
- * {@link #STATE_COLLAPSED}, or {@link #STATE_HIDDEN}.
+ * @param bottomSheet The bottom sheet view.
+ * @param newState The new state. This will be one of {@link #STATE_DRAGGING},
+ * {@link #STATE_SETTLING}, {@link #STATE_EXPANDED},
+ * {@link #STATE_COLLAPSED}, or {@link #STATE_HIDDEN}.
*/
- public abstract void onStateChanged(@State int newState);
+ public abstract void onStateChanged(@NonNull View bottomSheet, @State int newState);
/**
* Called when the bottom sheet is being dragged.
*
+ * @param bottomSheet The bottom sheet view.
* @param slideOffset The new offset of this bottom sheet within its range, from 0 to 1
* when it is moving upward, and from 0 to -1 when it moving downward.
*/
- public abstract void onSlide(float slideOffset);
+ public abstract void onSlide(@NonNull View bottomSheet, float slideOffset);
}
/**
@@ -322,8 +325,9 @@
return;
}
mState = state;
- if (mCallback != null) {
- mCallback.onStateChanged(state);
+ View bottomSheet = mViewRef.get();
+ if (bottomSheet != null && mCallback != null) {
+ mCallback.onStateChanged(bottomSheet, state);
}
}
@@ -434,11 +438,13 @@
};
private void dispatchOnSlide(int top) {
- if (mCallback != null) {
+ View bottomSheet = mViewRef.get();
+ if (bottomSheet != null && mCallback != null) {
if (top > mMaxOffset) {
- mCallback.onSlide((float) (mMaxOffset - top) / mPeekHeight);
+ mCallback.onSlide(bottomSheet, (float) (mMaxOffset - top) / mPeekHeight);
} else {
- mCallback.onSlide((float) (mMaxOffset - top) / ((mMaxOffset - mMinOffset)));
+ mCallback.onSlide(bottomSheet,
+ (float) (mMaxOffset - top) / ((mMaxOffset - mMinOffset)));
}
}
}
diff --git a/design/src/android/support/design/widget/BottomSheetDialog.java b/design/src/android/support/design/widget/BottomSheetDialog.java
index 3399de0..52c4004 100644
--- a/design/src/android/support/design/widget/BottomSheetDialog.java
+++ b/design/src/android/support/design/widget/BottomSheetDialog.java
@@ -135,14 +135,15 @@
private BottomSheetBehavior.BottomSheetCallback mBottomSheetCallback
= new BottomSheetBehavior.BottomSheetCallback() {
@Override
- public void onStateChanged(@BottomSheetBehavior.State int newState) {
+ public void onStateChanged(@NonNull View bottomSheet,
+ @BottomSheetBehavior.State int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
@Override
- public void onSlide(float slideOffset) {
+ public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
};
diff --git a/design/tests/src/android/support/design/widget/BottomSheetBehaviorTest.java b/design/tests/src/android/support/design/widget/BottomSheetBehaviorTest.java
index 7659c7c..65da332 100644
--- a/design/tests/src/android/support/design/widget/BottomSheetBehaviorTest.java
+++ b/design/tests/src/android/support/design/widget/BottomSheetBehaviorTest.java
@@ -19,6 +19,7 @@
import org.hamcrest.Matcher;
import org.junit.Test;
+import android.support.annotation.NonNull;
import android.support.design.test.R;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.IdlingResource;
@@ -55,7 +56,8 @@
}
@Override
- public void onStateChanged(@BottomSheetBehavior.State int newState) {
+ public void onStateChanged(@NonNull View bottomSheet,
+ @BottomSheetBehavior.State int newState) {
boolean wasIdle = mIsIdle;
mIsIdle = isIdleState(newState);
if (!wasIdle && mIsIdle && mResourceCallback != null) {
@@ -64,7 +66,7 @@
}
@Override
- public void onSlide(float slideOffset) {
+ public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
@Override
diff --git a/v17/leanback/api/current.txt b/v17/leanback/api/current.txt
index 0df488f..d90f9f6 100644
--- a/v17/leanback/api/current.txt
+++ b/v17/leanback/api/current.txt
@@ -1030,9 +1030,12 @@
method public android.content.Intent getIntent();
method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getSubActions();
method public java.lang.CharSequence getTitle();
+ method public boolean hasAnyEditable();
+ method public boolean hasEditableActivatorView();
method public boolean hasMultilineDescription();
method public boolean hasNext();
method public boolean hasSubActions();
+ method public boolean hasTextEditable();
method public boolean infoOnly();
method public boolean isChecked();
method public boolean isDescriptionEditable();
@@ -1071,36 +1074,36 @@
public static abstract class GuidedAction.BuilderBase {
ctor public GuidedAction.BuilderBase(android.content.Context);
method protected final void applyValues(android.support.v17.leanback.widget.GuidedAction);
- method public abstract T build();
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> checkSetId(int);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> checked(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> clickAction(long);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> description(java.lang.CharSequence);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> description(int);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> descriptionEditInputType(int);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> descriptionEditable(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> descriptionInputType(int);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editDescription(java.lang.CharSequence);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editDescription(int);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editInputType(int);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editTitle(java.lang.CharSequence);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editTitle(int);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> editable(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> enabled(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> focusable(boolean);
+ method public B checkSetId(int);
+ method public B checked(boolean);
+ method public B clickAction(long);
+ method public B description(java.lang.CharSequence);
+ method public B description(int);
+ method public B descriptionEditInputType(int);
+ method public B descriptionEditable(boolean);
+ method public B descriptionInputType(int);
+ method public B editDescription(java.lang.CharSequence);
+ method public B editDescription(int);
+ method public B editInputType(int);
+ method public B editTitle(java.lang.CharSequence);
+ method public B editTitle(int);
+ method public B editable(boolean);
+ method public B enabled(boolean);
+ method public B focusable(boolean);
method public android.content.Context getContext();
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> hasNext(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> icon(android.graphics.drawable.Drawable);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> icon(int);
- method public deprecated android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> iconResourceId(int, android.content.Context);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> id(long);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> infoOnly(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> inputType(int);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> intent(android.content.Intent);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> multilineDescription(boolean);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> subActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> title(java.lang.CharSequence);
- method public android.support.v17.leanback.widget.GuidedAction.BuilderBase<T> title(int);
+ method public B hasEditableActivatorView(boolean);
+ method public B hasNext(boolean);
+ method public B icon(android.graphics.drawable.Drawable);
+ method public B icon(int);
+ method public deprecated B iconResourceId(int, android.content.Context);
+ method public B id(long);
+ method public B infoOnly(boolean);
+ method public B inputType(int);
+ method public B intent(android.content.Intent);
+ method public B multilineDescription(boolean);
+ method public B subActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
+ method public B title(java.lang.CharSequence);
+ method public B title(int);
}
public class GuidedActionEditText extends android.widget.EditText implements android.support.v17.leanback.widget.ImeKeyMonitor {
@@ -1124,6 +1127,7 @@
method public void onAnimateItemFocused(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
method public void onAnimateItemPressed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
method public void onAnimateItemPressedCancelled(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
+ method public void onBindActivatorView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
method public void onBindCheckMarkView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
method public void onBindChevronView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
method public void onBindViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
@@ -1137,12 +1141,14 @@
method public int onProvideItemLayoutId();
method public int onProvideItemLayoutId(int);
method public int onProvideLayoutId();
+ method public boolean onUpdateActivatorView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
method public void onUpdateExpandedViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
method public void setAsButtonActions();
method public void setEditingMode(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean);
method public void setExpandedViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
method protected void setupImeOptions(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
method public void startExpandedTransition(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
+ field public static final int VIEW_TYPE_DATE_PICKER = 1; // 0x1
field public static final int VIEW_TYPE_DEFAULT = 0; // 0x0
}
@@ -1160,10 +1166,32 @@
method public android.widget.ImageView getIconView();
method public android.widget.TextView getTitleView();
method public boolean isInEditing();
+ method public boolean isInEditingActivatorView();
method public boolean isInEditingDescription();
+ method public boolean isInEditingText();
+ method public boolean isInEditingTitle();
method public boolean isSubAction();
}
+ public class GuidedDatePickerAction extends android.support.v17.leanback.widget.GuidedAction {
+ ctor public GuidedDatePickerAction();
+ method public long getDate();
+ method public java.lang.String getDatePickerFormat();
+ method public void setDate(long);
+ }
+
+ public static final class GuidedDatePickerAction.Builder extends android.support.v17.leanback.widget.GuidedDatePickerAction.BuilderBase {
+ ctor public GuidedDatePickerAction.Builder(android.content.Context);
+ method public android.support.v17.leanback.widget.GuidedDatePickerAction build();
+ }
+
+ public static abstract class GuidedDatePickerAction.BuilderBase extends android.support.v17.leanback.widget.GuidedAction.BuilderBase {
+ ctor public GuidedDatePickerAction.BuilderBase(android.content.Context);
+ method protected final void applyDatePickerValues(android.support.v17.leanback.widget.GuidedDatePickerAction);
+ method public B date(long);
+ method public B datePickerFormat(java.lang.String);
+ }
+
public class HeaderItem {
ctor public HeaderItem(long, java.lang.String);
ctor public HeaderItem(java.lang.String);
@@ -1945,67 +1973,47 @@
package android.support.v17.leanback.widget.picker {
- public class DatePicker extends android.support.v17.leanback.widget.picker.Picker {
- ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
- method public java.lang.String getDatePickerFormat();
- method public java.util.Calendar getMaxDate();
- method public java.util.Calendar getMinDate();
- method public void setDatePickerFormat(java.lang.String);
- method public void setMaxDate(long);
- method public void setMinDate(long);
- method public void updateDate(int, int, int, boolean);
- }
-
public class Picker extends android.widget.FrameLayout {
ctor public Picker(android.content.Context, android.util.AttributeSet, int);
- method public void addPickerValueListener(android.support.v17.leanback.widget.picker.Picker.PickerValueListener);
- method public int getActiveColumn();
+ method public void addOnValueChangedListener(android.support.v17.leanback.widget.picker.Picker.PickerValueListener);
+ method public float getActivatedVisibleItemCount();
method public android.support.v17.leanback.widget.picker.PickerColumn getColumnAt(int);
method public int getColumnsCount();
- method protected int getPickerId();
method protected int getPickerItemHeightPixels();
- method protected int getPickerItemLayoutId();
- method protected int getPickerItemTextViewId();
- method protected int getPickerSeparatorLayoutId();
- method protected int getRootLayoutId();
- method protected java.lang.String getSeparator();
- method public float getVisiblePickerItems();
- method public float getVisiblePickerItemsInExpand();
- method public boolean isExpanded();
- method public boolean isToggleExpandOnClick();
- method public void onColumnValueChange(int, int);
- method public void removePickerValueListener(android.support.v17.leanback.widget.picker.Picker.PickerValueListener);
- method public void setActiveColumn(int);
- method public void setColumns(java.util.ArrayList<android.support.v17.leanback.widget.picker.PickerColumn>);
- method public void setExpanded(boolean);
- method public void setToggleExpandOnClick(boolean);
- method public void setVisiblePickerItems(float);
- method public void setVisiblePickerItemsInExpand(float);
- method public void updateAdapter(int);
- method public void updateValue(int, int, boolean);
+ method public final int getPickerItemLayoutId();
+ method public final int getPickerItemTextViewId();
+ method public int getSelectedColumn();
+ method public final java.lang.CharSequence getSeparator();
+ method public float getVisibleItemCount();
+ method public void onColumnValueChanged(int, int);
+ method public void removeOnValueChangedListener(android.support.v17.leanback.widget.picker.Picker.PickerValueListener);
+ method public void setActivatedVisibleItemCount(float);
+ method public void setColumnAt(int, android.support.v17.leanback.widget.picker.PickerColumn);
+ method public void setColumnValue(int, int, boolean);
+ method public void setColumns(java.util.List<android.support.v17.leanback.widget.picker.PickerColumn>);
+ method public final void setPickerItemTextViewId(int);
+ method public void setSelectedColumn(int);
+ method public final void setSeparator(java.lang.CharSequence);
+ method public void setVisibleItemCount(float);
}
public static abstract interface Picker.PickerValueListener {
method public abstract void onValueChanged(android.support.v17.leanback.widget.picker.Picker, int);
}
- public class PickerColumn implements android.os.Parcelable {
+ public class PickerColumn {
ctor public PickerColumn();
- ctor public PickerColumn(android.os.Parcel);
- method public int describeContents();
method public int getCurrentValue();
- method public int getItemsCount();
+ method public java.lang.CharSequence getEntryAt(int);
+ method public java.lang.String getEntryFormat();
+ method public int getItemCount();
method public int getMaxValue();
method public int getMinValue();
- method public java.lang.String getValueLabelAt(int);
- method public java.lang.String getValueLabelFormat();
- method public boolean setCurrentValue(int);
- method public boolean setMaxValue(int);
- method public boolean setMinValue(int);
- method public void setValueLabelFormat(java.lang.String);
- method public void setValueStaticLabels(java.lang.String[]);
- method public void writeToParcel(android.os.Parcel, int);
- field public static android.os.Parcelable.Creator<android.support.v17.leanback.widget.picker.PickerColumn> CREATOR;
+ method public void setCurrentValue(int);
+ method public void setEntries(java.lang.CharSequence[]);
+ method public void setEntryFormat(java.lang.String);
+ method public void setMaxValue(int);
+ method public void setMinValue(int);
}
}
diff --git a/v17/leanback/res/layout/lb_guidance.xml b/v17/leanback/res/layout/lb_guidance.xml
index 28c0220..59f8ac5 100644
--- a/v17/leanback/res/layout/lb_guidance.xml
+++ b/v17/leanback/res/layout/lb_guidance.xml
@@ -20,6 +20,7 @@
android:layout_height="match_parent" >
<RelativeLayout
+ android:id="@+id/guidance_container"
style="?attr/guidanceContainerStyle" >
<ImageView
diff --git a/v17/leanback/res/layout/lb_guidedactions_datepicker_item.xml b/v17/leanback/res/layout/lb_guidedactions_datepicker_item.xml
new file mode 100644
index 0000000..98278d9
--- /dev/null
+++ b/v17/leanback/res/layout/lb_guidedactions_datepicker_item.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+<!-- Layout for an action item displayed in the 2 pane actions fragment. -->
+<android.support.v17.leanback.widget.NonOverlappingLinearLayoutWithForeground
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ style="?attr/guidedActionItemContainerStyle" >
+
+ <ImageView
+ android:id="@+id/guidedactions_item_icon"
+ style="?attr/guidedActionItemIconStyle"
+ tools:ignore="ContentDescription" />
+
+ <TextView
+ android:id="@+id/guidedactions_item_title"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ style="?attr/guidedActionItemTitleStyle" />
+
+ <android.support.v17.leanback.widget.picker.DatePicker
+ android:id="@+id/guidedactions_activator_item"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</android.support.v17.leanback.widget.NonOverlappingLinearLayoutWithForeground>
diff --git a/v17/leanback/res/values/styles.xml b/v17/leanback/res/values/styles.xml
index 1f7f3dd..6d7c74b 100644
--- a/v17/leanback/res/values/styles.xml
+++ b/v17/leanback/res/values/styles.xml
@@ -384,6 +384,7 @@
<!-- Style for the title view in a GuidanceStylist's default layout. -->
<style name="Widget.Leanback.GuidanceTitleStyle">
+ <item name="android:importantForAccessibility">no</item>
<item name="android:layout_toStartOf">@id/guidance_icon</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
@@ -402,6 +403,7 @@
<!-- Style for the description view in a GuidanceStylist's default layout. -->
<style name="Widget.Leanback.GuidanceDescriptionStyle">
+ <item name="android:importantForAccessibility">no</item>
<item name="android:layout_below">@id/guidance_title</item>
<item name="android:layout_toStartOf">@id/guidance_icon</item>
<item name="android:layout_width">wrap_content</item>
@@ -419,6 +421,7 @@
<!-- Style for the breadcrumb view in a GuidanceStylist's default layout. -->
<style name="Widget.Leanback.GuidanceBreadcrumbStyle">
+ <item name="android:importantForAccessibility">no</item>
<item name="android:layout_above">@id/guidance_title</item>
<item name="android:layout_toStartOf">@id/guidance_icon</item>
<item name="android:layout_width">wrap_content</item>
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
index 604fcc1..8042242 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
@@ -1031,6 +1031,7 @@
mAdapterGroup.addAdpter(mAdapter, mButtonAdapter);
mAdapterGroup.addAdpter(mSubAdapter, null);
mAdapterGroup.setEditListener(editListener);
+ mActionsStylist.setEditListener(editListener);
mActionsStylist.getActionsGridView().setAdapter(mAdapter);
if (mActionsStylist.getSubActionsGridView() != null) {
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
index b4110e9..b76c990 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
@@ -1033,6 +1033,7 @@
mAdapterGroup.addAdpter(mAdapter, mButtonAdapter);
mAdapterGroup.addAdpter(mSubAdapter, null);
mAdapterGroup.setEditListener(editListener);
+ mActionsStylist.setEditListener(editListener);
mActionsStylist.getActionsGridView().setAdapter(mAdapter);
if (mActionsStylist.getSubActionsGridView() != null) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
index 3fcdbba..7284a53 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
@@ -20,6 +20,7 @@
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v17.leanback.R;
+import android.text.TextUtils;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@@ -154,6 +155,7 @@
mBreadcrumbView = (TextView) guidanceView.findViewById(R.id.guidance_breadcrumb);
mDescriptionView = (TextView) guidanceView.findViewById(R.id.guidance_description);
mIconView = (ImageView) guidanceView.findViewById(R.id.guidance_icon);
+ View guidanceContainer = guidanceView.findViewById(R.id.guidance_container);
// We allow any of the cached subviews to be null, so that subclasses can choose not to
// display a particular piece of information.
@@ -169,6 +171,16 @@
if (mIconView != null) {
mIconView.setImageDrawable(guidance.getIconDrawable());
}
+ if (guidanceContainer != null) {
+ CharSequence contentDescription = guidanceContainer.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ guidanceContainer.setContentDescription(new StringBuilder()
+ .append(guidance.getBreadcrumb()).append('\n')
+ .append(guidance.getTitle()).append('\n')
+ .append(guidance.getDescription())
+ .toString());
+ }
+ }
return guidanceView;
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
index c5bf7a5..977c201 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
@@ -38,7 +38,7 @@
* user input on selection, in which case they will be displayed with a chevron indicator.
* <p>
* GuidedAction recommends to use {@link Builder}. When application subclass GuidedAction, it
- * can subclass {@link BuilderBase}, implement {@link BuilderBase#build()} where it should
+ * can subclass {@link BuilderBase}, implement its own builder() method where it should
* call {@link BuilderBase#applyValues(GuidedAction)}.
*/
public class GuidedAction extends Action {
@@ -97,12 +97,17 @@
*/
public static final long ACTION_ID_NO = -9;
+ static final int EDITING_NONE = 0;
+ static final int EDITING_TITLE = 1;
+ static final int EDITING_DESCRIPTION = 2;
+ static final int EDITING_ACTIVATOR_VIEW = 3;
+
/**
* Base builder class to build a {@link GuidedAction} object. When subclass GuidedAction, you
- * can override this BuilderBase class, implements {@link #build()} and call
+ * can override this BuilderBase class, implements your build() method which should call
* {@link #applyValues(GuidedAction)}. When using GuidedAction directly, use {@link Builder}.
*/
- public abstract static class BuilderBase<T extends GuidedAction> {
+ public abstract static class BuilderBase<B extends BuilderBase> {
private Context mContext;
private long mId;
private CharSequence mTitle;
@@ -114,8 +119,7 @@
private boolean mMultilineDescription;
private boolean mHasNext;
private boolean mInfoOnly;
- private boolean mEditable = false;
- private boolean mDescriptionEditable = false;
+ private int mEditable = EDITING_NONE;
private int mInputType = InputType.TYPE_CLASS_TEXT;
private int mDescriptionInputType = InputType.TYPE_CLASS_TEXT;
private int mEditInputType = InputType.TYPE_CLASS_TEXT;
@@ -143,12 +147,6 @@
}
/**
- * Builds the GuidedAction corresponding to this Builder.
- * @return the GuidedAction as configured through this BuilderBase.
- */
- public abstract T build();
-
- /**
* Subclass of BuilderBase should call this function to apply values.
* @param action GuidedAction to apply BuilderBase values.
*/
@@ -164,7 +162,6 @@
// Subclass values
action.mIntent = mIntent;
action.mEditable = mEditable;
- action.mDescriptionEditable = mDescriptionEditable;
action.mInputType = mInputType;
action.mDescriptionInputType = mDescriptionInputType;
action.mEditInputType = mEditInputType;
@@ -187,7 +184,7 @@
* {@link GuidedAction#ACTION_ID_YES} {@link GuidedAction#ACTION_ID_NO}.
* @return The same BuilderBase object.
*/
- public BuilderBase<T> clickAction(long id) {
+ public B clickAction(long id) {
if (id == ACTION_ID_OK) {
mId = ACTION_ID_OK;
mTitle = mContext.getString(android.R.string.ok);
@@ -207,7 +204,7 @@
mId = ACTION_ID_NO;
mTitle = mContext.getString(android.R.string.no);
}
- return this;
+ return (B) this;
}
/**
@@ -215,9 +212,9 @@
* it is typically used to determine what to do when an action is clicked.
* @param id The ID to associate with this action.
*/
- public BuilderBase<T> id(long id) {
+ public B id(long id) {
mId = id;
- return this;
+ return (B) this;
}
/**
@@ -225,9 +222,9 @@
* action to be taken on click, e.g. "Continue" or "Cancel".
* @param title The title for this action.
*/
- public BuilderBase<T> title(CharSequence title) {
+ public B title(CharSequence title) {
mTitle = title;
- return this;
+ return (B) this;
}
/**
@@ -235,9 +232,9 @@
* action to be taken on click, e.g. "Continue" or "Cancel".
* @param titleResourceId The resource id of title for this action.
*/
- public BuilderBase<T> title(@StringRes int titleResourceId) {
+ public B title(@StringRes int titleResourceId) {
mTitle = getContext().getString(titleResourceId);
- return this;
+ return (B) this;
}
/**
@@ -245,9 +242,9 @@
* replaces the string of title.
* @param editTitle The optional title text to edit when TextView is activated.
*/
- public BuilderBase<T> editTitle(CharSequence editTitle) {
+ public B editTitle(CharSequence editTitle) {
mEditTitle = editTitle;
- return this;
+ return (B) this;
}
/**
@@ -256,9 +253,9 @@
* @param editTitleResourceId String resource id of the optional title text to edit when
* TextView is activated.
*/
- public BuilderBase<T> editTitle(@StringRes int editTitleResourceId) {
+ public B editTitle(@StringRes int editTitleResourceId) {
mEditTitle = getContext().getString(editTitleResourceId);
- return this;
+ return (B) this;
}
/**
@@ -266,9 +263,9 @@
* providing extra information on what the action will do.
* @param description The description for this action.
*/
- public BuilderBase<T> description(CharSequence description) {
+ public B description(CharSequence description) {
mDescription = description;
- return this;
+ return (B) this;
}
/**
@@ -276,9 +273,9 @@
* providing extra information on what the action will do.
* @param descriptionResourceId String resource id of the description for this action.
*/
- public BuilderBase<T> description(@StringRes int descriptionResourceId) {
+ public B description(@StringRes int descriptionResourceId) {
mDescription = getContext().getString(descriptionResourceId);
- return this;
+ return (B) this;
}
/**
@@ -286,9 +283,9 @@
* description replaces the string of description.
* @param description The description to edit for this action.
*/
- public BuilderBase<T> editDescription(CharSequence description) {
+ public B editDescription(CharSequence description) {
mEditDescription = description;
- return this;
+ return (B) this;
}
/**
@@ -297,9 +294,9 @@
* @param descriptionResourceId String resource id of the description to edit for this
* action.
*/
- public BuilderBase<T> editDescription(@StringRes int descriptionResourceId) {
+ public B editDescription(@StringRes int descriptionResourceId) {
mEditDescription = getContext().getString(descriptionResourceId);
- return this;
+ return (B) this;
}
/**
@@ -307,18 +304,18 @@
* directly when the action is clicked.
* @param intent The intent associated with this action.
*/
- public BuilderBase<T> intent(Intent intent) {
+ public B intent(Intent intent) {
mIntent = intent;
- return this;
+ return (B) this;
}
/**
* Sets the action's icon drawable.
* @param icon The drawable for the icon associated with this action.
*/
- public BuilderBase<T> icon(Drawable icon) {
+ public B icon(Drawable icon) {
mIcon = icon;
- return this;
+ return (B) this;
}
/**
@@ -330,7 +327,7 @@
* @deprecated Use {@link #icon(int)}.
*/
@Deprecated
- public BuilderBase<T> iconResourceId(@DrawableRes int iconResourceId, Context context) {
+ public B iconResourceId(@DrawableRes int iconResourceId, Context context) {
return icon(ContextCompat.getDrawable(context, iconResourceId));
}
@@ -340,7 +337,7 @@
* {@link #icon(Drawable)}.
* @param iconResourceId The resource ID for the icon associated with this action.
*/
- public BuilderBase<T> icon(@DrawableRes int iconResourceId) {
+ public B icon(@DrawableRes int iconResourceId) {
return icon(ContextCompat.getDrawable(getContext(), iconResourceId));
}
@@ -349,24 +346,48 @@
* checked, or belong to a check set.
* @param editable Whether this action is editable.
*/
- public BuilderBase<T> editable(boolean editable) {
- mEditable = editable;
+ public B editable(boolean editable) {
+ if (!editable && mEditable == EDITING_TITLE) {
+ mEditable = EDITING_NONE;
+ return (B) this;
+ }
+ mEditable = EDITING_TITLE;
if (mChecked || mCheckSetId != NO_CHECK_SET) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
- return this;
+ return (B) this;
}
/**
* Indicates whether this action's description is editable
* @param editable Whether this action description is editable.
*/
- public BuilderBase<T> descriptionEditable(boolean editable) {
- mDescriptionEditable = editable;
+ public B descriptionEditable(boolean editable) {
+ if (!editable && mEditable == EDITING_DESCRIPTION) {
+ mEditable = EDITING_NONE;
+ return (B) this;
+ }
+ mEditable = EDITING_DESCRIPTION;
if (mChecked || mCheckSetId != NO_CHECK_SET) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
- return this;
+ return (B) this;
+ }
+
+ /**
+ * Indicates whether this action has a view can be activated to edit, e.g. a DatePicker.
+ * @param editable Whether this action has view can be activated to edit.
+ */
+ public B hasEditableActivatorView(boolean editable) {
+ if (!editable && mEditable == EDITING_ACTIVATOR_VIEW) {
+ mEditable = EDITING_NONE;
+ return (B) this;
+ }
+ mEditable = EDITING_ACTIVATOR_VIEW;
+ if (mChecked || mCheckSetId != NO_CHECK_SET) {
+ throw new IllegalArgumentException("Editable actions cannot also be checked");
+ }
+ return (B) this;
}
/**
@@ -374,9 +395,9 @@
*
* @param inputType InputType for the action title not in editing.
*/
- public BuilderBase<T> inputType(int inputType) {
+ public B inputType(int inputType) {
mInputType = inputType;
- return this;
+ return (B) this;
}
/**
@@ -384,9 +405,9 @@
*
* @param inputType InputType for the action description not in editing.
*/
- public BuilderBase<T> descriptionInputType(int inputType) {
+ public B descriptionInputType(int inputType) {
mDescriptionInputType = inputType;
- return this;
+ return (B) this;
}
@@ -395,9 +416,9 @@
*
* @param inputType InputType for the action title in editing.
*/
- public BuilderBase<T> editInputType(int inputType) {
+ public B editInputType(int inputType) {
mEditInputType = inputType;
- return this;
+ return (B) this;
}
/**
@@ -405,9 +426,9 @@
*
* @param inputType InputType for the action description in editing.
*/
- public BuilderBase<T> descriptionEditInputType(int inputType) {
+ public B descriptionEditInputType(int inputType) {
mDescriptionEditInputType = inputType;
- return this;
+ return (B) this;
}
@@ -415,12 +436,12 @@
* Indicates whether this action is initially checked.
* @param checked Whether this action is checked.
*/
- public BuilderBase<T> checked(boolean checked) {
+ public B checked(boolean checked) {
mChecked = checked;
- if (mEditable || mDescriptionEditable) {
+ if (mEditable != EDITING_NONE) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
- return this;
+ return (B) this;
}
/**
@@ -430,12 +451,12 @@
* @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
* radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
*/
- public BuilderBase<T> checkSetId(int checkSetId) {
+ public B checkSetId(int checkSetId) {
mCheckSetId = checkSetId;
- if (mEditable || mDescriptionEditable) {
+ if (mEditable != EDITING_NONE) {
throw new IllegalArgumentException("Editable actions cannot also be in check sets");
}
- return this;
+ return (B) this;
}
/**
@@ -443,36 +464,36 @@
* appropriately.
* @param multilineDescription Whether this action has a multiline description.
*/
- public BuilderBase<T> multilineDescription(boolean multilineDescription) {
+ public B multilineDescription(boolean multilineDescription) {
mMultilineDescription = multilineDescription;
- return this;
+ return (B) this;
}
/**
* Indicates whether this action has a next state and should display a chevron.
* @param hasNext Whether this action has a next state.
*/
- public BuilderBase<T> hasNext(boolean hasNext) {
+ public B hasNext(boolean hasNext) {
mHasNext = hasNext;
- return this;
+ return (B) this;
}
/**
* Indicates whether this action is for information purposes only and cannot be clicked.
* @param infoOnly Whether this action has a next state.
*/
- public BuilderBase<T> infoOnly(boolean infoOnly) {
+ public B infoOnly(boolean infoOnly) {
mInfoOnly = infoOnly;
- return this;
+ return (B) this;
}
/**
* Indicates whether this action is enabled. If not enabled, an action cannot be clicked.
* @param enabled Whether the action is enabled.
*/
- public BuilderBase<T> enabled(boolean enabled) {
+ public B enabled(boolean enabled) {
mEnabled = enabled;
- return this;
+ return (B) this;
}
/**
@@ -480,9 +501,9 @@
* @param focusable
* @return The same BuilderBase object.
*/
- public BuilderBase<T> focusable(boolean focusable) {
+ public B focusable(boolean focusable) {
mFocusable = focusable;
- return this;
+ return (B) this;
}
/**
@@ -490,16 +511,16 @@
* @param subActions
* @return The same BuilderBase object.
*/
- public BuilderBase<T> subActions(List<GuidedAction> subActions) {
+ public B subActions(List<GuidedAction> subActions) {
mSubActions = subActions;
- return this;
+ return (B) this;
}
}
/**
* Builds a {@link GuidedAction} object.
*/
- public static class Builder extends BuilderBase<GuidedAction> {
+ public static class Builder extends BuilderBase<Builder> {
/**
* @deprecated Use {@link GuidedAction.Builder#GuidedAction.Builder(Context)}.
@@ -517,7 +538,10 @@
super(context);
}
- @Override
+ /**
+ * Builds the GuidedAction corresponding to this Builder.
+ * @return The GuidedAction as configured through this Builder.
+ */
public GuidedAction build() {
GuidedAction action = new GuidedAction();
applyValues(action);
@@ -528,8 +552,7 @@
private CharSequence mEditTitle;
private CharSequence mEditDescription;
- private boolean mEditable;
- private boolean mDescriptionEditable;
+ private int mEditable;
private int mInputType;
private int mDescriptionInputType;
private int mEditInputType;
@@ -642,11 +665,20 @@
}
/**
+ * Returns whether this action has any editable part, e.g. editable title, editable description
+ * or editable activate view.
+ * @return true if this action has any editable part, false otherwise.
+ */
+ public boolean hasAnyEditable() {
+ return mEditable != EDITING_NONE;
+ }
+
+ /**
* Returns whether this action title is editable.
* @return true if the action title is editable, false otherwise.
*/
public boolean isEditable() {
- return mEditable;
+ return mEditable == EDITING_TITLE;
}
/**
@@ -654,7 +686,23 @@
* @return true if the action description is editable, false otherwise.
*/
public boolean isDescriptionEditable() {
- return mDescriptionEditable;
+ return mEditable == EDITING_DESCRIPTION;
+ }
+
+ /**
+ * Returns if this action has editable title or editable description.
+ * @return True if this action has editable title or editable description, false otherwise.
+ */
+ public boolean hasTextEditable() {
+ return mEditable == EDITING_TITLE || mEditable == EDITING_DESCRIPTION;
+ }
+
+ /**
+ * Returns whether this action can be activated to edit, e.g. a DatePicker.
+ * @return true if the action can be activated to edit.
+ */
+ public boolean hasEditableActivatorView() {
+ return mEditable == EDITING_ACTIVATOR_VIEW;
}
/**
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapter.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapter.java
index e0fad0a..ee44656 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapter.java
@@ -108,9 +108,13 @@
GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder)
getRecyclerView().getChildViewHolder(v);
GuidedAction action = avh.getAction();
- if (action.isEditable() || action.isDescriptionEditable()) {
+ if (action.hasTextEditable()) {
if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme by click");
mGroup.openIme(GuidedActionAdapter.this, avh);
+ } else if (action.hasEditableActivatorView()) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "toggle editing mode by click");
+ getGuidedActionsStylist().setEditingMode(avh, avh.getAction(),
+ !avh.isInEditingActivatorView());
} else {
handleCheckedActions(avh);
if (action.isEnabled() && !action.infoOnly()) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapterGroup.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapterGroup.java
index 858a0ed..6fa3d89 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapterGroup.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionAdapterGroup.java
@@ -95,7 +95,7 @@
(GuidedActionsStylist.ViewHolder) adapter.getGuidedActionsStylist()
.getActionsGridView().findViewHolderForPosition(index);
if (vh != null) {
- if (vh.getAction().isEditable() || vh.getAction().isDescriptionEditable()) {
+ if (vh.getAction().hasTextEditable()) {
if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme of next Action");
// open Ime on next action.
openIme(adapter, vh);
@@ -122,7 +122,7 @@
public void openIme(GuidedActionAdapter adapter, GuidedActionsStylist.ViewHolder avh) {
adapter.getGuidedActionsStylist().setEditingMode(avh, avh.getAction(), true);
View v = avh.getEditingView();
- if (v == null) {
+ if (v == null || !avh.isInEditingText()) {
return;
}
InputMethodManager mgr = (InputMethodManager)
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
index 2a95dfe..835d512 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
@@ -30,7 +30,10 @@
import android.support.v17.leanback.R;
import android.support.v17.leanback.transition.TransitionHelper;
import android.support.v17.leanback.transition.TransitionListener;
+import android.support.v17.leanback.widget.GuidedActionAdapter.EditListener;
import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v17.leanback.widget.picker.DatePicker;
+import android.support.v17.leanback.widget.picker.Picker;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
@@ -39,6 +42,7 @@
import android.util.Log;
import android.util.TypedValue;
import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
import android.view.inputmethod.EditorInfo;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -53,16 +57,22 @@
import android.widget.ImageView;
import android.widget.TextView;
+import java.util.Calendar;
import java.util.Collections;
import java.util.List;
+import static android.support.v17.leanback.widget.GuidedAction.EDITING_NONE;
+import static android.support.v17.leanback.widget.GuidedAction.EDITING_TITLE;
+import static android.support.v17.leanback.widget.GuidedAction.EDITING_DESCRIPTION;
+import static android.support.v17.leanback.widget.GuidedAction.EDITING_ACTIVATOR_VIEW;
+
/**
* GuidedActionsStylist is used within a {@link android.support.v17.leanback.app.GuidedStepFragment}
* to supply the right-side panel where users can take actions. It consists of a container for the
* list of actions, and a stationary selector view that indicates visually the location of focus.
* GuidedActionsStylist has two different layouts: default is for normal actions including text,
- * radio, checkbox etc, the other when {@link #setAsButtonActions()} is called is recommended for
- * button actions such as "yes", "no".
+ * radio, checkbox, DatePicker, etc, the other when {@link #setAsButtonActions()} is called is
+ * recommended for button actions such as "yes", "no".
* <p>
* Many aspects of the base GuidedActionsStylist can be customized through theming; see the
* theme attributes below. Note that these attributes are not set on individual elements in layout
@@ -72,8 +82,16 @@
* <p>
* If these hooks are insufficient, this class may also be subclassed. Subclasses may wish to
* override the {@link #onProvideLayoutId} method to change the layout used to display the
- * list container and selector, or the {@link #onProvideItemLayoutId} method to change the layout
- * used to display each action.
+ * list container and selector; override {@link #onProvideItemLayoutId(int)} and
+ * {@link #getItemViewType(GuidedAction)} method to change the layout used to display each action.
+ * <p>
+ * To support a "click to activate" view similar to DatePicker, app needs:
+ * <li> Override {@link #onProvideItemLayoutId(int)} and {@link #getItemViewType(GuidedAction)},
+ * provides a layout id for the action.
+ * <li> The layout must include a widget with id "guidedactions_activator_item", the widget is
+ * toggled edit mode by {@link View#setActivated(boolean)}.
+ * <li> Override {@link #onBindActivatorView(ViewHolder, GuidedAction)} to populate values into View.
+ * <li> Override {@link #onUpdateActivatorView(ViewHolder, GuidedAction)} to update action.
* <p>
* Note: If an alternate list layout is provided, the following view IDs must be supplied:
* <ul>
@@ -136,6 +154,11 @@
public static final int VIEW_TYPE_DEFAULT = 0;
/**
+ * ViewType for DatePicker.
+ */
+ public static final int VIEW_TYPE_DATE_PICKER = 1;
+
+ /**
* ViewHolder caches information about the action item layouts' subviews. Subclasses of {@link
* GuidedActionsStylist} may also wish to subclass this in order to add fields.
* @see GuidedAction
@@ -146,11 +169,11 @@
private View mContentView;
private TextView mTitleView;
private TextView mDescriptionView;
+ private View mActivatorView;
private ImageView mIconView;
private ImageView mCheckmarkView;
private ImageView mChevronView;
- private boolean mInEditing;
- private boolean mInEditingDescription;
+ private int mEditingMode = EDITING_NONE;
private final boolean mIsSubAction;
/**
@@ -168,6 +191,7 @@
mContentView = v.findViewById(R.id.guidedactions_item_content);
mTitleView = (TextView) v.findViewById(R.id.guidedactions_item_title);
+ mActivatorView = v.findViewById(R.id.guidedactions_activator_item);
mDescriptionView = (TextView) v.findViewById(R.id.guidedactions_item_description);
mIconView = (ImageView) v.findViewById(R.id.guidedactions_item_icon);
mCheckmarkView = (ImageView) v.findViewById(R.id.guidedactions_item_checkmark);
@@ -235,26 +259,56 @@
}
/**
- * Returns true if the TextView is in editing title or description, false otherwise.
+ * Returns true if in editing title, description, or activator View, false otherwise.
*/
public boolean isInEditing() {
- return mInEditing;
+ return mEditingMode != EDITING_NONE;
+ }
+
+ /**
+ * Returns true if in editing title, description, so IME would be open.
+ * @return True if in editing title, description, so IME would be open, false otherwise.
+ */
+ public boolean isInEditingText() {
+ return mEditingMode == EDITING_TITLE || mEditingMode == EDITING_DESCRIPTION;
+ }
+
+ /**
+ * Returns true if the TextView is in editing title, false otherwise.
+ */
+ public boolean isInEditingTitle() {
+ return mEditingMode == EDITING_TITLE;
}
/**
* Returns true if the TextView is in editing description, false otherwise.
*/
public boolean isInEditingDescription() {
- return mInEditingDescription;
+ return mEditingMode == EDITING_DESCRIPTION;
}
/**
- * @return Current editing title view or description view or null if not in editing.
+ * Returns true if is in editing activator view with id guidedactions_activator_item, false
+ * otherwise.
+ */
+ public boolean isInEditingActivatorView() {
+ return mEditingMode == EDITING_ACTIVATOR_VIEW;
+ }
+
+ /**
+ * @return Current editing title view or description view or activator view or null if not
+ * in editing.
*/
public View getEditingView() {
- if (mInEditing) {
- return mInEditingDescription ? mDescriptionView : mTitleView;
- } else {
+ switch(mEditingMode) {
+ case EDITING_TITLE:
+ return mTitleView;
+ case EDITING_DESCRIPTION:
+ return mDescriptionView;
+ case EDITING_ACTIVATOR_VIEW:
+ return mActivatorView;
+ case EDITING_NONE:
+ default:
return null;
}
}
@@ -297,6 +351,8 @@
private int mVerticalPadding;
private int mDisplayHeight;
+ private EditListener mEditListener;
+
private GuidedAction mExpandedAction = null;
private Object mExpandTransition;
@@ -428,6 +484,9 @@
* @return View type that used in {@link #onProvideItemLayoutId(int)}.
*/
public int getItemViewType(GuidedAction action) {
+ if (action instanceof GuidedDatePickerAction) {
+ return VIEW_TYPE_DATE_PICKER;
+ }
return VIEW_TYPE_DEFAULT;
}
@@ -451,19 +510,24 @@
/**
* Provides the resource ID of the layout defining the view for an individual guided actions.
* Subclasses may override to provide their own customized layouts. The base implementation
- * returns {@link android.support.v17.leanback.R.layout#lb_guidedactions_item}. If overridden,
- * the substituted layout should contain matching IDs for any views that should be managed by
- * the base class; this can be achieved by starting with a copy of the base layout file. Note
- * that in order for the item to support editing, the title view should both subclass {@link
- * android.widget.EditText} and implement {@link ImeKeyMonitor}; see {@link
- * GuidedActionEditText}.
+ * supports:
+ * <li>{@link android.support.v17.leanback.R.layout#lb_guidedactions_item}
+ * <li>{{@link android.support.v17.leanback.R.layout#lb_guidedactions_datepicker_item}. If
+ * overridden, the substituted layout should contain matching IDs for any views that should be
+ * managed by the base class; this can be achieved by starting with a copy of the base layout
+ * file. Note that in order for the item to support editing, the title view should both subclass
+ * {@link android.widget.EditText} and implement {@link ImeKeyMonitor}; see
+ * {@link GuidedActionEditText}.
+ *
* @param viewType View type returned by {@link #getItemViewType(GuidedAction)}
* @return The resource ID of the layout to be inflated to define the view to display an
- * individual GuidedAction.
+ * individual GuidedAction.
*/
public int onProvideItemLayoutId(int viewType) {
if (viewType == VIEW_TYPE_DEFAULT) {
return onProvideItemLayoutId();
+ } else if (viewType == VIEW_TYPE_DATE_PICKER) {
+ return R.layout.lb_guidedactions_datepicker_item;
} else {
throw new RuntimeException("ViewType " + viewType +
" not supported in GuidedActionsStylist");
@@ -549,6 +613,9 @@
vh.mDescriptionView.setMaxLines(mDescriptionMinLines);
}
}
+ if (vh.mActivatorView != null) {
+ onBindActivatorView(vh, action);
+ }
setEditingMode(vh, action, false);
if (action.isFocusable()) {
vh.itemView.setFocusable(true);
@@ -580,8 +647,7 @@
}
public void setEditingMode(ViewHolder vh, GuidedAction action, boolean editing) {
- if (editing != vh.mInEditing) {
- vh.mInEditing = editing;
+ if (editing != vh.isInEditing() && !isInExpandTransition()) {
onEditingModeChange(vh, action, editing);
}
}
@@ -604,12 +670,15 @@
descriptionView.setVisibility(View.VISIBLE);
descriptionView.setInputType(action.getDescriptionEditInputType());
}
- vh.mInEditingDescription = true;
- } else {
- vh.mInEditingDescription = false;
+ vh.mEditingMode = EDITING_DESCRIPTION;
+ } else if (action.isEditable()){
if (titleView != null) {
titleView.setInputType(action.getEditInputType());
}
+ vh.mEditingMode = EDITING_TITLE;
+ } else if (vh.mActivatorView != null) {
+ onEditActivatorView(vh, action, editing);
+ vh.mEditingMode = EDITING_ACTIVATOR_VIEW;
}
} else {
if (titleView != null) {
@@ -618,18 +687,22 @@
if (descriptionView != null) {
descriptionView.setText(action.getDescription());
}
- if (vh.mInEditingDescription) {
+ if (vh.mEditingMode == EDITING_DESCRIPTION) {
if (descriptionView != null) {
descriptionView.setVisibility(TextUtils.isEmpty(action.getDescription()) ?
View.GONE : View.VISIBLE);
descriptionView.setInputType(action.getDescriptionInputType());
}
- vh.mInEditingDescription = false;
- } else {
+ } else if (vh.mEditingMode == EDITING_TITLE) {
if (titleView != null) {
titleView.setInputType(action.getInputType());
}
+ } else if (vh.mEditingMode == EDITING_ACTIVATOR_VIEW) {
+ if (vh.mActivatorView != null) {
+ onEditActivatorView(vh, action, editing);
+ }
}
+ vh.mEditingMode = EDITING_NONE;
}
}
@@ -716,6 +789,76 @@
}
/**
+ * Performs binding activator view value to action. Default implementation supports
+ * GuidedDatePickerAction, subclass may override to add support of other views.
+ * @param vh ViewHolder of activator view.
+ * @param action GuidedAction to bind.
+ */
+ public void onBindActivatorView(ViewHolder vh, GuidedAction action) {
+ if (action instanceof GuidedDatePickerAction) {
+ GuidedDatePickerAction dateAction = (GuidedDatePickerAction) action;
+ DatePicker dateView = (DatePicker) vh.mActivatorView;
+ dateView.setDatePickerFormat(dateAction.getDatePickerFormat());
+ Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(((GuidedDatePickerAction) action).getDate());
+ dateView.updateDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH),
+ c.get(Calendar.DAY_OF_MONTH), false);
+ }
+ }
+
+ /**
+ * Performs updating GuidedAction from activator view. Default implementation supports
+ * GuidedDatePickerAction, subclass may override to add support of other views.
+ * @param vh ViewHolder of activator view.
+ * @param action GuidedAction to update.
+ * @return True if value has been updated, false otherwise.
+ */
+ public boolean onUpdateActivatorView(ViewHolder vh, GuidedAction action) {
+ if (action instanceof GuidedDatePickerAction) {
+ GuidedDatePickerAction dateAction = (GuidedDatePickerAction) action;
+ DatePicker dateView = (DatePicker) vh.mActivatorView;
+ if (dateAction.getDate() != dateView.getDate()) {
+ dateAction.setDate(dateView.getDate());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets listener for reporting view being edited.
+ * @hide
+ */
+ public void setEditListener(EditListener listener) {
+ mEditListener = listener;
+ }
+
+ void onEditActivatorView(final ViewHolder vh, final GuidedAction action,
+ boolean editing) {
+ if (editing) {
+ vh.mActivatorView.requestFocus();
+ setExpandedViewHolder(vh);
+ vh.mActivatorView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!isInExpandTransition()) {
+ setEditingMode(vh, action, false);
+ }
+ }
+ });
+ } else {
+ if (onUpdateActivatorView(vh, action)) {
+ if (mEditListener != null) {
+ mEditListener.onGuidedActionEdited(action);
+ }
+ }
+ vh.itemView.requestFocus();
+ setExpandedViewHolder(null);
+ vh.mActivatorView.setOnClickListener(null);
+ }
+ }
+
+ /**
* Sets states of chevron view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}.
* Subclass may override.
*
@@ -750,7 +893,7 @@
* hide the other items in main list. When null, collapse the sub actions list.
*/
public void setExpandedViewHolder(ViewHolder avh) {
- if (mSubActionsGridView == null || isInExpandTransition()) {
+ if (isInExpandTransition()) {
return;
}
if (isExpandTransitionSupported()) {
@@ -804,12 +947,15 @@
onUpdateExpandedViewHolder(avh);
return;
}
+ boolean isSubActionTransition = focusAvh.getAction().hasSubActions();
Object set = TransitionHelper.createTransitionSet(false);
+ float slideDistance = isSubActionTransition ? focusAvh.itemView.getHeight() :
+ focusAvh.itemView.getHeight() * 0.5f;
Object slideAndFade = TransitionHelper.createFadeAndShortSlide(Gravity.TOP | Gravity.BOTTOM,
- (float) focusAvh.itemView.getHeight());
+ slideDistance);
Object changeFocusItemTransform = TransitionHelper.createChangeTransform();
Object changeFocusItemBounds = TransitionHelper.createChangeBounds(false);
- Object fadeGrid = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
+ Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
TransitionHelper.FADE_OUT);
Object changeGridBounds = TransitionHelper.createChangeBounds(false);
if (avh == null) {
@@ -817,7 +963,7 @@
TransitionHelper.setStartDelay(changeFocusItemTransform, 100);
TransitionHelper.setStartDelay(changeFocusItemBounds, 100);
} else {
- TransitionHelper.setStartDelay(fadeGrid, 100);
+ TransitionHelper.setStartDelay(fade, 100);
TransitionHelper.setStartDelay(changeGridBounds, 100);
TransitionHelper.setStartDelay(changeFocusItemTransform, 50);
TransitionHelper.setStartDelay(changeFocusItemBounds, 50);
@@ -827,19 +973,25 @@
.getChildViewHolder(mActionsGridView.getChildAt(i));
if (vh == focusAvh) {
// going to expand/collapse this one.
- TransitionHelper.include(changeFocusItemTransform, vh.itemView);
- TransitionHelper.include(changeFocusItemBounds, vh.itemView);
+ if (isSubActionTransition) {
+ TransitionHelper.include(changeFocusItemTransform, vh.itemView);
+ TransitionHelper.include(changeFocusItemBounds, vh.itemView);
+ }
} else {
// going to slide this item to top / bottom.
TransitionHelper.include(slideAndFade, vh.itemView);
+ TransitionHelper.exclude(fade, vh.itemView, true);
}
}
- TransitionHelper.include(fadeGrid, mSubActionsGridView);
TransitionHelper.include(changeGridBounds, mSubActionsGridView);
TransitionHelper.addTransition(set, slideAndFade);
- TransitionHelper.addTransition(set, changeFocusItemTransform);
- TransitionHelper.addTransition(set, changeFocusItemBounds);
- TransitionHelper.addTransition(set, fadeGrid);
+ // note that we don't run ChangeBounds for activating view due to the rounding problem
+ // of multiple level views ChangeBounds animation causing vertical jittering.
+ if (isSubActionTransition) {
+ TransitionHelper.addTransition(set, changeFocusItemTransform);
+ TransitionHelper.addTransition(set, changeFocusItemBounds);
+ }
+ TransitionHelper.addTransition(set, fade);
TransitionHelper.addTransition(set, changeGridBounds);
mExpandTransition = set;
TransitionHelper.addTransitionListener(mExpandTransition, new TransitionListener() {
@@ -917,7 +1069,7 @@
updateChevronAndVisibility(vh);
}
if (mSubActionsGridView != null) {
- if (avh != null) {
+ if (avh != null && avh.getAction().hasSubActions()) {
ViewGroup.MarginLayoutParams lp =
(ViewGroup.MarginLayoutParams) mSubActionsGridView.getLayoutParams();
lp.topMargin = avh.itemView.getTop();
@@ -928,7 +1080,7 @@
mSubActionsGridView.setSelectedPosition(0);
((GuidedActionAdapter) mSubActionsGridView.getAdapter())
.setActions(avh.getAction().getSubActions());
- } else {
+ } else if (mSubActionsGridView.getVisibility() == View.VISIBLE) {
mSubActionsGridView.setVisibility(View.INVISIBLE);
ViewGroup.MarginLayoutParams lp =
(ViewGroup.MarginLayoutParams) mSubActionsGridView.getLayoutParams();
@@ -946,9 +1098,17 @@
if (mExpandedAction == null) {
vh.itemView.setVisibility(View.VISIBLE);
vh.itemView.setTranslationY(0);
+ if (vh.mActivatorView != null) {
+ vh.mActivatorView.setActivated(false);
+ }
} else if (vh.getAction() == mExpandedAction) {
vh.itemView.setVisibility(View.VISIBLE);
- vh.itemView.setTranslationY(- vh.itemView.getHeight());
+ if (vh.getAction().hasSubActions()) {
+ vh.itemView.setTranslationY(- vh.itemView.getHeight());
+ } else if (vh.mActivatorView != null) {
+ vh.itemView.setTranslationY(0);
+ vh.mActivatorView.setActivated(true);
+ }
} else {
vh.itemView.setVisibility(View.INVISIBLE);
vh.itemView.setTranslationY(0);
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedDatePickerAction.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedDatePickerAction.java
new file mode 100644
index 0000000..9daed2a
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedDatePickerAction.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 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 android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.support.v17.leanback.widget.picker.DatePicker;
+
+import java.util.Calendar;
+
+/**
+ * Subclass of GuidedAction that can choose a date. The Action is editable by default; to make it
+ * read only, call hasEditableActivatorView(false) on the Builder.
+ */
+public class GuidedDatePickerAction extends GuidedAction {
+
+ /**
+ * Base Builder class to build GuidedDatePickerAction. Subclass this BuilderBase when app needs
+ * to subclass GuidedDatePickerAction, implement your build() which should call
+ * {@link #applyDatePickerValues(GuidedDatePickerAction)}. When using GuidedDatePickerAction
+ * directly, use {@link Builder}.
+ */
+ public abstract static class BuilderBase<B extends BuilderBase>
+ extends GuidedAction.BuilderBase<B> {
+
+ private String mDatePickerFormat;
+ private long mDate;
+
+ public BuilderBase(Context context) {
+ super(context);
+ Calendar c = Calendar.getInstance();
+ mDate = c.getTimeInMillis();
+ hasEditableActivatorView(true);
+ }
+
+ /**
+ * Sets format of date Picker. When the format is not specified,
+ * a default format of current locale will be used.
+ * @param format Format of showing Date, e.g. "YMD"
+ * @return This Builder object.
+ */
+ public B datePickerFormat(String format) {
+ mDatePickerFormat = format;
+ return (B) this;
+ }
+
+ /**
+ * Sets a Date for date picker, see {@link Calendar#getTimeInMillis()}.
+ * @param date See {@link Calendar#getTimeInMillis()}.
+ * @return This Builder Object.
+ */
+ public B date(long date) {
+ mDate = date;
+ return (B) this;
+ }
+
+ /**
+ * Apply values to GuidedDatePickerAction.
+ * @param action GuidedDatePickerAction to apply values.
+ */
+ protected final void applyDatePickerValues(GuidedDatePickerAction action) {
+ super.applyValues(action);
+ action.mDatePickerFormat = mDatePickerFormat;
+ action.mDate = mDate;
+ }
+
+ }
+
+ /**
+ * Builder class to build a GuidedDatePickerAction.
+ */
+ public final static class Builder extends BuilderBase<Builder> {
+ public Builder(Context context) {
+ super(context);
+ }
+
+ /**
+ * Builds the GuidedDatePickerAction corresponding to this Builder.
+ * @return The GuidedDatePickerAction as configured through this Builder.
+ */
+ public GuidedDatePickerAction build() {
+ GuidedDatePickerAction action = new GuidedDatePickerAction();
+ applyDatePickerValues(action);
+ return action;
+ }
+ }
+
+ private String mDatePickerFormat;
+ private long mDate;
+
+ /**
+ * Returns format of date Picker or null if not specified. When the
+ * format is not specified, a default format of current locale will be used.
+ * @return Format of showing Date, e.g. "YMD". Returns null if using current locale's default.
+ */
+ public String getDatePickerFormat() {
+ return mDatePickerFormat;
+ }
+
+ /**
+ * Get current value of DatePicker;
+ * @return Current value of DatePicker;
+ */
+ public long getDate() {
+ return mDate;
+ }
+
+ /**
+ * Sets current value of DatePicker;
+ * @param date New value to update current value of DatePicker;
+ */
+ public void setDate(long date) {
+ mDate = date;
+ }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/picker/DatePicker.java b/v17/leanback/src/android/support/v17/leanback/widget/picker/DatePicker.java
index 00c6f3c..209b7e6 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/picker/DatePicker.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/picker/DatePicker.java
@@ -39,8 +39,8 @@
* @attr ref R.styleable#lbDatePicker_android_maxDate
* @attr ref R.styleable#lbDatePicker_android_minDate
* @attr ref R.styleable#lbDatePicker_datePickerFormat
+ * @hide
*/
-
public class DatePicker extends Picker {
static final String LOG_TAG = "DatePicker";
@@ -62,23 +62,20 @@
Calendar mCurrentDate;
Calendar mTempDate;
+ public DatePicker(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
public DatePicker(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
updateCurrentLocale();
+ setSeparator(mConstant.dateSeparator);
final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
R.styleable.lbDatePicker);
String minDate = attributesArray.getString(R.styleable.lbDatePicker_android_minDate);
String maxDate = attributesArray.getString(R.styleable.lbDatePicker_android_maxDate);
- String datePickerFormat = attributesArray
- .getString(R.styleable.lbDatePicker_datePickerFormat);
- if (TextUtils.isEmpty(datePickerFormat)) {
- datePickerFormat = new String(
- android.text.format.DateFormat.getDateFormatOrder(context));
- }
- setDatePickerFormat(datePickerFormat);
-
mTempDate.clear();
if (!TextUtils.isEmpty(minDate)) {
if (!parseDate(minDate, mTempDate)) {
@@ -87,7 +84,7 @@
} else {
mTempDate.set(1900, 0, 1);
}
- setMinDate(mTempDate.getTimeInMillis());
+ mMinDate.setTimeInMillis(mTempDate.getTimeInMillis());
mTempDate.clear();
if (!TextUtils.isEmpty(maxDate)) {
@@ -97,8 +94,15 @@
} else {
mTempDate.set(2100, 0, 1);
}
- setMaxDate(mTempDate.getTimeInMillis());
+ mMaxDate.setTimeInMillis(mTempDate.getTimeInMillis());
+ String datePickerFormat = attributesArray
+ .getString(R.styleable.lbDatePicker_datePickerFormat);
+ if (TextUtils.isEmpty(datePickerFormat)) {
+ datePickerFormat = new String(
+ android.text.format.DateFormat.getDateFormatOrder(context));
+ }
+ setDatePickerFormat(datePickerFormat);
}
private boolean parseDate(String date, Calendar outDate) {
@@ -112,10 +116,14 @@
}
/**
- * Changes format of showing dates, e.g. 'YMD'.
+ * Changes format of showing dates. For example "YMD".
* @param datePickerFormat Format of showing dates.
*/
public void setDatePickerFormat(String datePickerFormat) {
+ if (TextUtils.isEmpty(datePickerFormat)) {
+ datePickerFormat = new String(
+ android.text.format.DateFormat.getDateFormatOrder(getContext()));
+ }
datePickerFormat = datePickerFormat.toUpperCase();
if (TextUtils.equals(mDatePickerFormat, datePickerFormat)) {
return;
@@ -132,14 +140,14 @@
}
columns.add(mYearColumn = new PickerColumn());
mColYearIndex = i;
- mYearColumn.setValueLabelFormat("%d");
+ mYearColumn.setEntryFormat("%d");
break;
case 'M':
if (mMonthColumn != null) {
throw new IllegalArgumentException("datePicker format error");
}
columns.add(mMonthColumn = new PickerColumn());
- mMonthColumn.setValueStaticLabels(mConstant.months);
+ mMonthColumn.setEntries(mConstant.months);
mColMonthIndex = i;
break;
case 'D':
@@ -147,7 +155,7 @@
throw new IllegalArgumentException("datePicker format error");
}
columns.add(mDayColumn = new PickerColumn());
- mDayColumn.setValueLabelFormat("%02d");
+ mDayColumn.setEntryFormat("%02d");
mColDayIndex = i;
break;
default:
@@ -159,20 +167,14 @@
}
/**
- * Get format of showing dates, e.g. 'YMD'. Default value is from
- * {@link android.text.format.DateFormat#getDateFormatOrder}.
+ * Get format of showing dates. For example "YMD". Default value is from
+ * {@link android.text.format.DateFormat#getDateFormatOrder(Context)}.
* @return Format of showing dates.
*/
public String getDatePickerFormat() {
return mDatePickerFormat;
}
- @Override
- protected String getSeparator() {
- return mConstant.dateSeparator;
- }
-
-
private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
if (oldCalendar == null) {
return Calendar.getInstance(locale);
@@ -192,13 +194,13 @@
mCurrentDate = getCalendarForLocale(mCurrentDate, mConstant.locale);
if (mMonthColumn != null) {
- mMonthColumn.setValueStaticLabels(mConstant.months);
- updateAdapter(mColMonthIndex);
+ mMonthColumn.setEntries(mConstant.months);
+ setColumnAt(mColMonthIndex, mMonthColumn);
}
}
@Override
- public void onColumnValueChange(int column, int newVal) {
+ public final void onColumnValueChanged(int column, int newVal) {
mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
// take care of wrapping of days and months to update greater fields
int oldVal = getColumnAt(column).getCurrentValue();
@@ -248,10 +250,8 @@
*
* @return The minimal supported date.
*/
- public Calendar getMinDate() {
- final Calendar minDate = Calendar.getInstance();
- minDate.setTimeInMillis(mMinDate.getTimeInMillis());
- return minDate;
+ public long getMinDate() {
+ return mMinDate.getTimeInMillis();
}
/**
@@ -284,10 +284,18 @@
*
* @return The maximal supported date.
*/
- public Calendar getMaxDate() {
- final Calendar maxDate = Calendar.getInstance();
- maxDate.setTimeInMillis(mMaxDate.getTimeInMillis());
- return maxDate;
+ public long getMaxDate() {
+ return mMaxDate.getTimeInMillis();
+ }
+
+ /**
+ * Gets current date value in milliseconds since January 1, 1970 00:00:00 in
+ * {@link TimeZone#getDefault()} time zone.
+ *
+ * @return Current date values.
+ */
+ public long getDate() {
+ return mCurrentDate.getTimeInMillis();
}
private void setDate(int year, int month, int dayOfMonth) {
@@ -321,72 +329,88 @@
|| mCurrentDate.get(Calendar.DAY_OF_MONTH) != month);
}
+ private static boolean updateMin(PickerColumn column, int value) {
+ if (value != column.getMinValue()) {
+ column.setMinValue(value);
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean updateMax(PickerColumn column, int value) {
+ if (value != column.getMaxValue()) {
+ column.setMaxValue(value);
+ return true;
+ }
+ return false;
+ }
+
private void updateSpinners(boolean animation) {
// set the spinner ranges respecting the min and max dates
boolean dayRangeChanged = false;
boolean monthRangeChanged = false;
if (mCurrentDate.equals(mMinDate)) {
if (mDayColumn != null) {
- dayRangeChanged |= mDayColumn.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
- dayRangeChanged |= mDayColumn
- .setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+ dayRangeChanged |= updateMin(mDayColumn, mCurrentDate.get(Calendar.DAY_OF_MONTH));
+ dayRangeChanged |=
+ updateMax(mDayColumn, mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
}
if (mMonthColumn != null) {
- monthRangeChanged |= mMonthColumn.setMinValue(mCurrentDate.get(Calendar.MONTH));
+ monthRangeChanged |= updateMin(mMonthColumn, mCurrentDate.get(Calendar.MONTH));
monthRangeChanged |=
- mMonthColumn.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
+ updateMax(mMonthColumn, mCurrentDate.getActualMaximum(Calendar.MONTH));
}
} else if (mCurrentDate.equals(mMaxDate)) {
if (mDayColumn != null) {
- dayRangeChanged |= mDayColumn
- .setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
- dayRangeChanged |= mDayColumn.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+ dayRangeChanged |=
+ updateMin(mDayColumn, mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
+ dayRangeChanged |= updateMax(mDayColumn, mCurrentDate.get(Calendar.DAY_OF_MONTH));
}
if (mMonthColumn != null) {
monthRangeChanged |=
- mMonthColumn.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
- monthRangeChanged |= mMonthColumn.setMaxValue(mCurrentDate.get(Calendar.MONTH));
+ updateMin(mMonthColumn, mCurrentDate.getActualMinimum(Calendar.MONTH));
+ monthRangeChanged |= updateMax(mMonthColumn, mCurrentDate.get(Calendar.MONTH));
}
} else {
if (mDayColumn != null) {
- dayRangeChanged |= mDayColumn
- .setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
- dayRangeChanged |= mDayColumn
- .setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+ dayRangeChanged |=
+ updateMin(mDayColumn, mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
+ dayRangeChanged |=
+ updateMax(mDayColumn, mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
}
if (mMonthColumn != null) {
monthRangeChanged |=
- mMonthColumn.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
+ updateMin(mMonthColumn, mCurrentDate.getActualMinimum(Calendar.MONTH));
monthRangeChanged |=
- mMonthColumn.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
+ updateMax(mMonthColumn, mCurrentDate.getActualMaximum(Calendar.MONTH));
}
}
// year spinner range does not change based on the current date
boolean yearRangeChanged = false;
if (mYearColumn != null) {
- yearRangeChanged |= mYearColumn.setMinValue(mMinDate.get(Calendar.YEAR));
- yearRangeChanged |= mYearColumn.setMaxValue(mMaxDate.get(Calendar.YEAR));
+ yearRangeChanged |= updateMin(mYearColumn, mMinDate.get(Calendar.YEAR));
+ yearRangeChanged |= updateMax(mYearColumn, mMaxDate.get(Calendar.YEAR));
}
if (dayRangeChanged) {
- updateAdapter(mColDayIndex);
+ setColumnAt(mColDayIndex, mDayColumn);
}
if (monthRangeChanged) {
- updateAdapter(mColMonthIndex);
+ setColumnAt(mColMonthIndex, mMonthColumn);
}
if (yearRangeChanged) {
- updateAdapter(mColYearIndex);
+ setColumnAt(mColYearIndex, mYearColumn);
}
// set the spinner values
if (mYearColumn != null) {
- updateValue(mColYearIndex, mCurrentDate.get(Calendar.YEAR), animation);
+ setColumnValue(mColYearIndex, mCurrentDate.get(Calendar.YEAR), animation);
}
if (mMonthColumn != null) {
- updateValue(mColMonthIndex, mCurrentDate.get(Calendar.MONTH), animation);
+ setColumnValue(mColMonthIndex, mCurrentDate.get(Calendar.MONTH), animation);
}
if (mDayColumn != null) {
- updateValue(mColDayIndex, mCurrentDate.get(Calendar.DAY_OF_MONTH), animation);
+ setColumnValue(mColDayIndex, mCurrentDate.get(Calendar.DAY_OF_MONTH), animation);
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java b/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
index 1157a11..8e5bcdc 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
@@ -36,28 +36,19 @@
/**
* Picker is a widget showing multiple customized {@link PickerColumn}s. The PickerColumns are
- * initialized in {@link #setColumns(ArrayList)}. Call {@link #updateAdapter(int)} if the column
- * value range or labels change. Call {@link #updateValue(int, int, boolean)} to update the current
- * value of PickerColumn.
+ * initialized in {@link #setColumns(List)}. Call {@link #setColumnAt(int, PickerColumn)} if the
+ * column value range or labels change. Call {@link #setColumnValue(int, int, boolean)} to update
+ * the current value of PickerColumn.
* <p>
* Picker has two states and will change height:
- * <li>{@link #isExpanded()} is true: Picker shows typically three items vertically (see
- * {@link #getVisiblePickerItemsInExpand()}}. Columns other than {@link #getActiveColumn()} still
+ * <li>{@link #isActivated()} is true: Picker shows typically three items vertically (see
+ * {@link #getActivatedVisibleItemCount()}}. Columns other than {@link #getSelectedColumn()} still
* shows one item if the Picker is focused. On a touch screen device, the Picker will not get focus
* so it always show three items on all columns. On a non-touch device (a TV), the Picker will show
* three items only on currently activated column. If the Picker has focus, it will intercept DPAD
* directions and select activated column.
- * <li>{@link #isExpanded()} is false: Picker shows one item vertically (see
- * {@link #getVisiblePickerItems()}) on all columns. The size of Picker shrinks.
- * <li>The expand mode will be toggled if the Picker has focus and {@link #isToggleExpandOnClick()}
- * is true. Summarize Typically use cases:
- * <li>On a touch screen based device, the Picker focusableInTouchMode=false. It won't get focus, it
- * wont toggle expand mode on click or touch, should call {@link #setExpanded(boolean)} with true,
- * so that user always sees three items on all columns.
- * <li>On a TV: the Picker focusable=true. It will get focus and toggle into expand mode when user
- * clicks on it, toggle can be disabled by {@link #setToggleExpandOnClick(boolean)} with false. Only
- * the activated column shows multiple items and the activated column is selected by DPAD left or
- * right.
+ * <li>{@link #isActivated()} is false: Picker shows one item vertically (see
+ * {@link #getVisibleItemCount()}) on all columns. The size of Picker shrinks.
*/
public class Picker extends FrameLayout {
@@ -65,7 +56,6 @@
public void onValueChanged(Picker picker, int column);
}
- private String mSeparator;
private ViewGroup mRootView;
private ViewGroup mPickerView;
private List<VerticalGridView> mColumnViews = new ArrayList<VerticalGridView>();
@@ -79,62 +69,57 @@
private Interpolator mDecelerateInterpolator;
private Interpolator mAccelerateInterpolator;
private ArrayList<PickerValueListener> mListeners;
- private boolean mExpanded;
- private float mVisibleItemsInExpand = 3;
+ private float mVisibleItemsActivated = 3;
private float mVisibleItems = 1;
- private int mActivatedColumn = 0;
- private boolean mToggleExpandOnClick = true;
+ private int mSelectedColumn = 0;
+
+ private CharSequence mSeparator;
+ private int mPickerItemLayoutId = R.layout.lb_picker_item;
+ private int mPickerItemTextViewId = 0;
/**
- * Classes extending {@link Picker} can choose to override this method to
- * supply the separator string
+ * Gets separator string between columns.
*/
- protected String getSeparator() {
+ public final CharSequence getSeparator() {
return mSeparator;
}
/**
- * Classes extending {@link Picker} can choose to override this method to
- * supply the {@link Picker}'s root layout id
+ * Sets separator String between Picker columns.
+ * @param seperator Separator String between Picker columns.
*/
- protected int getRootLayoutId() {
- return R.layout.lb_picker;
- }
-
- /**
- * Classes extending {@link Picker} can choose to override this method to
- * supply the {@link Picker}'s id from within the layout provided by
- * {@link Picker#getRootLayoutId()}
- */
- protected int getPickerId() {
- return R.id.picker;
- }
-
- /**
- * Classes extending {@link Picker} can choose to override this method to
- * supply the {@link Picker}'s separator's layout id
- */
- protected int getPickerSeparatorLayoutId() {
- return R.layout.lb_picker_separator;
+ public final void setSeparator(CharSequence seperator) {
+ mSeparator = seperator;
}
/**
* Classes extending {@link Picker} can choose to override this method to
* supply the {@link Picker}'s item's layout id
*/
- protected int getPickerItemLayoutId() {
- return R.layout.lb_picker_item;
+ public final int getPickerItemLayoutId() {
+ return mPickerItemLayoutId;
}
/**
- * Classes extending {@link Picker} can choose to override this method to
- * supply the {@link Picker}'s item's {@link TextView}'s id from within the
+ * Returns the {@link Picker}'s item's {@link TextView}'s id from within the
* layout provided by {@link Picker#getPickerItemLayoutId()} or 0 if the
* layout provided by {@link Picker#getPickerItemLayoutId()} is a {link
* TextView}.
*/
- protected int getPickerItemTextViewId() {
- return 0;
+ public final int getPickerItemTextViewId() {
+ return mPickerItemTextViewId;
+ }
+
+ /**
+ * Sets the {@link Picker}'s item's {@link TextView}'s id from within the
+ * layout provided by {@link Picker#getPickerItemLayoutId()} or 0 if the
+ * layout provided by {@link Picker#getPickerItemLayoutId()} is a {link
+ * TextView}.
+ * @param textViewId View id of TextView inside a Picker item, or 0 if the Picker item is a
+ * TextView.
+ */
+ public final void setPickerItemTextViewId(int textViewId) {
+ mPickerItemTextViewId = textViewId;
}
/**
@@ -164,15 +149,15 @@
mAccelerateInterpolator = new AccelerateInterpolator(2.5F);
LayoutInflater inflater = LayoutInflater.from(getContext());
- mRootView = (ViewGroup) inflater.inflate(getRootLayoutId(), this, true);
- mPickerView = (ViewGroup) mRootView.findViewById(getPickerId());
+ mRootView = (ViewGroup) inflater.inflate(R.layout.lb_picker, this, true);
+ mPickerView = (ViewGroup) mRootView.findViewById(R.id.picker);
}
/**
* Get nth PickerColumn.
* @param colIndex Index of PickerColumn.
- * @return PickerColumn at colIndex or null if {@link #setColumns(ArrayList)} is not called yet.
+ * @return PickerColumn at colIndex or null if {@link #setColumns(List)} is not called yet.
*/
public PickerColumn getColumnAt(int colIndex) {
if (mColumns == null) {
@@ -183,7 +168,7 @@
/**
* Get number of PickerColumns.
- * @return Number of PickerColumns or 0 if {@link #setColumns(ArrayList)} is not called yet.
+ * @return Number of PickerColumns or 0 if {@link #setColumns(List)} is not called yet.
*/
public int getColumnsCount() {
if (mColumns == null) {
@@ -196,12 +181,12 @@
* Set columns and create Views.
* @param columns PickerColumns to be shown in the Picker.
*/
- public void setColumns(ArrayList<PickerColumn> columns) {
+ public void setColumns(List<PickerColumn> columns) {
mColumnViews.clear();
mPickerView.removeAllViews();
mColumns = new ArrayList<PickerColumn>(columns);
- if (mActivatedColumn > mColumns.size() - 1) {
- mActivatedColumn = mColumns.size() - 1;
+ if (mSelectedColumn > mColumns.size() - 1) {
+ mSelectedColumn = mColumns.size() - 1;
}
LayoutInflater inflater = LayoutInflater.from(getContext());
int totalCol = getColumnsCount();
@@ -225,7 +210,7 @@
// add a separator if not the last element
if (i != totalCol - 1 && getSeparator() != null) {
TextView separator = (TextView) inflater.inflate(
- getPickerSeparatorLayoutId(), mPickerView, false);
+ R.layout.lb_picker_separator, mPickerView, false);
separator.setText(getSeparator());
mPickerView.addView(separator);
}
@@ -240,8 +225,10 @@
* When column labels change or column range changes, call this function to re-populate the
* selection list.
* @param columnIndex Index of column to update.
+ * @param column New column to update.
*/
- public void updateAdapter(int columnIndex) {
+ public void setColumnAt(int columnIndex, PickerColumn column) {
+ mColumns.set(columnIndex, column);
VerticalGridView columnView = mColumnViews.get(columnIndex);
PickerScrollArrayAdapter adapter = (PickerScrollArrayAdapter) columnView.getAdapter();
if (adapter != null && !columnView.isComputingLayout()) {
@@ -255,8 +242,10 @@
* @param value New value of the column.
* @param runAnimation True to scroll to the value or false otherwise.
*/
- public void updateValue(int columnIndex, int value, boolean runAnimation) {
- if (mColumns.get(columnIndex).setCurrentValue(value)) {
+ public void setColumnValue(int columnIndex, int value, boolean runAnimation) {
+ PickerColumn column = mColumns.get(columnIndex);
+ if (column.getCurrentValue() != value) {
+ column.setCurrentValue(value);
notifyValueChanged(columnIndex);
VerticalGridView columnView = mColumnViews.get(columnIndex);
if (columnView != null) {
@@ -278,14 +267,22 @@
}
}
- public void addPickerValueListener(PickerValueListener listener) {
+ /**
+ * Register a callback to be invoked when the picker's value has changed.
+ * @param listener The callback to ad
+ */
+ public void addOnValueChangedListener(PickerValueListener listener) {
if (mListeners == null) {
mListeners = new ArrayList<Picker.PickerValueListener>();
}
mListeners.add(listener);
}
- public void removePickerValueListener(PickerValueListener listener) {
+ /**
+ * Remove a previously installed value changed callback
+ * @param listener The callback to remove.
+ */
+ public void removeOnValueChangedListener(PickerValueListener listener) {
if (mListeners != null) {
mListeners.remove(listener);
}
@@ -307,7 +304,7 @@
private void setOrAnimateAlpha(View view, boolean selected, int colIndex,
boolean animate) {
- boolean columnShownAsActivated = colIndex == mActivatedColumn || !isFocused();
+ boolean columnShownAsActivated = colIndex == mSelectedColumn || !isFocused();
if (selected) {
// set alpha for main item (selected) in the column
if (columnShownAsActivated) {
@@ -344,15 +341,17 @@
/**
* Classes extending {@link Picker} can override this function to supply the
- * behavior when a list has been scrolled. Subclass may call {@link #updateValue(int, int,
- * boolean)} and or {@link #updateAdapter(int)}. Subclass should not directly call
+ * behavior when a list has been scrolled. Subclass may call {@link #setColumnValue(int, int,
+ * boolean)} and or {@link #setColumnAt(int,PickerColumn)}. Subclass should not directly call
* {@link PickerColumn#setCurrentValue(int)} which does not update internal state or notify
* listeners.
* @param columnIndex index of which column was changed.
* @param newValue A new value desired to be set on the column.
*/
- public void onColumnValueChange(int columnIndex, int newValue) {
- if (mColumns.get(columnIndex).setCurrentValue(newValue)) {
+ public void onColumnValueChanged(int columnIndex, int newValue) {
+ PickerColumn column = mColumns.get(columnIndex);
+ if (column.getCurrentValue() != newValue) {
+ column.setCurrentValue(newValue);
notifyValueChanged(columnIndex);
}
}
@@ -402,7 +401,7 @@
public void onBindViewHolder(ViewHolder holder, int position) {
if (holder.textView != null && mData != null) {
- holder.textView.setText(mData.getValueLabelAt(mData.getMinValue() + position));
+ holder.textView.setText(mData.getEntryAt(mData.getMinValue() + position));
}
setOrAnimateAlpha(holder.itemView,
(mColumnViews.get(mColIndex).getSelectedPosition() == position),
@@ -415,7 +414,7 @@
}
public int getItemCount() {
- return mData == null ? 0 : mData.getItemsCount();
+ return mData == null ? 0 : mData.getItemCount();
}
}
@@ -432,7 +431,7 @@
updateColumnAlpha(colIndex, true);
if (child != null) {
int newValue = mColumns.get(colIndex).getMinValue() + position;
- onColumnValueChange(colIndex, newValue);
+ onColumnValueChanged(colIndex, newValue);
}
}
@@ -440,7 +439,7 @@
@Override
public boolean dispatchKeyEvent(android.view.KeyEvent event) {
- if (isExpanded()) {
+ if (isActivated()) {
final int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
@@ -449,20 +448,20 @@
if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL?
keyCode == KeyEvent.KEYCODE_DPAD_LEFT :
keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ) {
- if (mActivatedColumn < getColumnsCount() - 1) {
- setActiveColumn(mActivatedColumn + 1);
+ if (mSelectedColumn < getColumnsCount() - 1) {
+ setSelectedColumn(mSelectedColumn + 1);
}
} else {
- if (mActivatedColumn > 0) {
- setActiveColumn(mActivatedColumn - 1);
+ if (mSelectedColumn > 0) {
+ setSelectedColumn(mSelectedColumn - 1);
}
}
}
break;
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
- if (event.getAction() == KeyEvent.ACTION_DOWN && mActivatedColumn >= 0) {
- VerticalGridView gridView = mColumnViews.get(mActivatedColumn);
+ if (event.getAction() == KeyEvent.ACTION_DOWN && mSelectedColumn >= 0) {
+ VerticalGridView gridView = mColumnViews.get(mSelectedColumn);
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
int newPosition = gridView.getSelectedPosition() - 1;
if (newPosition >= 0) {
@@ -500,90 +499,82 @@
private void updateColumnSize(VerticalGridView columnView) {
ViewGroup.LayoutParams lp = columnView.getLayoutParams();
- lp.height = (int) (getPickerItemHeightPixels() * (isExpanded() ?
- getVisiblePickerItemsInExpand() : getVisiblePickerItems()));
+ lp.height = (int) (getPickerItemHeightPixels() * (isActivated() ?
+ getActivatedVisibleItemCount() : getVisibleItemCount()));
columnView.setLayoutParams(lp);
}
/**
- * Returns number of visible items showing in a column when it's expanded, it's 3 by default.
- * @return Number of visible items showing in a column when it's expanded.
+ * Returns number of visible items showing in a column when it's activated. The default value
+ * is 3.
+ * @return Number of visible items showing in a column when it's activated.
*/
- public float getVisiblePickerItemsInExpand() {
- return mVisibleItemsInExpand;
+ public float getActivatedVisibleItemCount() {
+ return mVisibleItemsActivated;
}
/**
- * Change number of visible items showing in a column when it's expanded.
- * @param visiblePickerItems Number of visible items showing in a column when it's expanded.
+ * Changes number of visible items showing in a column when it's activated. The default value
+ * is 3.
+ * @param visiblePickerItems Number of visible items showing in a column when it's activated.
*/
- public void setVisiblePickerItemsInExpand(float visiblePickerItems) {
+ public void setActivatedVisibleItemCount(float visiblePickerItems) {
if (visiblePickerItems <= 0) {
throw new IllegalArgumentException();
}
- if (mVisibleItemsInExpand != visiblePickerItems) {
- mVisibleItemsInExpand = visiblePickerItems;
- if (isExpanded()) {
+ if (mVisibleItemsActivated != visiblePickerItems) {
+ mVisibleItemsActivated = visiblePickerItems;
+ if (isActivated()) {
updateColumnSize();
}
}
}
/**
- * Returns number of visible items showing in a column when it's not expanded, it's 1 by
- * default.
- * @return Number of visible items showing in a column when it's not expanded.
+ * Returns number of visible items showing in a column when it's not activated. The default
+ * value is 1.
+ * @return Number of visible items showing in a column when it's not activated.
*/
- public float getVisiblePickerItems() {
+ public float getVisibleItemCount() {
return 1;
}
/**
- * Change number of visible items showing in a column when it's not expanded, it's 1 by default.
- * @param pickerItems Number of visible items showing in a column when it's not expanded.
+ * Changes number of visible items showing in a column when it's not activated. The default
+ * value is 1.
+ * @param pickerItems Number of visible items showing in a column when it's not activated.
*/
- public void setVisiblePickerItems(float pickerItems) {
+ public void setVisibleItemCount(float pickerItems) {
if (pickerItems <= 0) {
throw new IllegalArgumentException();
}
if (mVisibleItems != pickerItems) {
mVisibleItems = pickerItems;
- if (!isExpanded()) {
+ if (!isActivated()) {
updateColumnSize();
}
}
}
- /**
- * Change expanded state of Picker, the height LayoutParams will be changed.
- * @see #getVisiblePickerItemsInExpand()
- * @see #getVisiblePickerItems()
- * @param expanded New expanded state of Picker.
- */
- public void setExpanded(boolean expanded) {
- if (mExpanded != expanded) {
- mExpanded = expanded;
+ @Override
+ public void setActivated(boolean activated) {
+ if (activated != isActivated()) {
+ super.setActivated(activated);
updateColumnSize();
+ } else {
+ super.setActivated(activated);
}
}
/**
- * Returns true if the Picker is currently expanded, false otherwise.
- * @return True if the Picker is currently expanded, false otherwise.
- */
- public boolean isExpanded() {
- return mExpanded;
- }
-
- /**
- * Change current activated column. Shows multiple items on activate column if Picker has
- * focus. Show multiple items on all column if Picker has no focus (e.g. a Touchscreen
+ * Change current selected column. Picker shows multiple items on selected column if Picker has
+ * focus. Picker shows multiple items on all column if Picker has no focus (e.g. a Touchscreen
* screen).
* @param columnIndex Index of column to activate.
*/
- public void setActiveColumn(int columnIndex) {
- if (mActivatedColumn != columnIndex) {
- mActivatedColumn = columnIndex;
+ public void setSelectedColumn(int columnIndex) {
+ if (mSelectedColumn != columnIndex) {
+ mSelectedColumn = columnIndex;
for (int i = 0; i < mColumnViews.size(); i++) {
updateColumnAlpha(i, true);
}
@@ -594,35 +585,8 @@
* Get current activated column index.
* @return Current activated column index.
*/
- public int getActiveColumn() {
- return mActivatedColumn;
- }
-
- /**
- * Enable or disable toggle on click when Picker has focus.
- * @param toggleExpandOnClick True to enable toggle on click when Picker has focus, false
- * otherwise.
- */
- public void setToggleExpandOnClick(boolean toggleExpandOnClick) {
- mToggleExpandOnClick = toggleExpandOnClick;
- }
-
- /**
- * Returns true if toggle on click is enabled when Picker has focus, false otherwise.
- * @return True if toggle on click is enabled when Picker has focus, false otherwise.
- */
- public boolean isToggleExpandOnClick() {
- return mToggleExpandOnClick;
- }
-
- @Override
- public boolean performClick() {
- if (isFocused() && isToggleExpandOnClick()) {
- setExpanded(!isExpanded());
- super.performClick();
- return true;
- }
- return super.performClick();
+ public int getSelectedColumn() {
+ return mSelectedColumn;
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/picker/PickerColumn.java b/v17/leanback/src/android/support/v17/leanback/widget/picker/PickerColumn.java
index c4c0c57..f2a2c5a 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/picker/PickerColumn.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/picker/PickerColumn.java
@@ -14,54 +14,40 @@
package android.support.v17.leanback.widget.picker;
-import android.os.Parcel;
-import android.os.Parcelable;
-
/**
* Picker column class used by {@link Picker}, defines a contiguous value ranges and associated
* labels. A PickerColumn has a minValue and maxValue to choose between. The Picker column has
* a current value.
- * The labels can be dynamically generated from value by {@link #setValueLabelFormat(String)} or
- * a list of static labels set by {@link #setValueStaticLabels(String[])}.
+ * The labels can be dynamically generated from value by {@link #setEntryFormat(String)} or
+ * a list of static labels set by {@link #setEntries(CharSequence[])}.
*/
-public class PickerColumn implements Parcelable {
+public class PickerColumn {
private int mCurrentValue;
private int mMinValue;
private int mMaxValue;
- private String[] mStaticLabels;
- private String mValueFormat;
+ private CharSequence[] mStaticEntrys;
+ private String mEntryFormat;
public PickerColumn() {
}
- public PickerColumn(Parcel source) {
- mValueFormat = source.readString();
- int count = source.readInt();
- if (count > 0) {
- mStaticLabels = new String[count];
- source.readStringArray(mStaticLabels);
- }
- mCurrentValue = source.readInt();
- mMinValue = source.readInt();
- mMaxValue = source.readInt();
- }
-
/**
- * Set string format to display label for value, e.g. "%02d". The string format is only
- * used when {@link #setValueStaticLabels(String[])} is not called.
- * @param valueFormat String format to display label for value.
+ * Set string format to display label for value. For example "%02d".
+ * {@link #setEntries(CharSequence[])} overrides the format.
+ *
+ * @param valueFormat String format to display label for value between minValue and maxValue.
*/
- public void setValueLabelFormat(String valueFormat) {
- mValueFormat = valueFormat;
+ public void setEntryFormat(String valueFormat) {
+ mEntryFormat = valueFormat;
}
/**
- * Return string format to display label for value, e.g. "%02d".
+ * Return string format to display label for value. For example "%02d".
* @return String format to display label for value.
*/
- public String getValueLabelFormat() {
- return mValueFormat;
+ public String getEntryFormat() {
+ return mEntryFormat;
}
/**
@@ -69,21 +55,22 @@
* labels[labels.length - 1].
* @param labels Static labels for each value between minValue and maxValue.
*/
- public void setValueStaticLabels(String[] labels) {
- mStaticLabels = labels;
+ public void setEntries(CharSequence[] labels) {
+ mStaticEntrys = labels;
}
/**
- * Get a label for value. The label can be static ({@link #setValueStaticLabels(String[])} or
- * dynamically generated (@link {@link #setValueLabelFormat(String)}.
+ * Get a label for value. The label can be static ({@link #setEntries(CharSequence[])}
+ * or dynamically generated (@link {@link #setEntryFormat(String)}.
+ *
* @param value Value between minValue and maxValue.
* @return Label for the value.
*/
- public String getValueLabelAt(int value) {
- if (mStaticLabels == null) {
- return String.format(mValueFormat, value);
+ public CharSequence getEntryAt(int value) {
+ if (mStaticEntrys == null) {
+ return String.format(mEntryFormat, value);
}
- return mStaticLabels[value];
+ return mStaticEntrys[value];
}
/**
@@ -96,97 +83,49 @@
/**
* Sets current value of the Column.
- * @return True if current value has changed.
*/
- public boolean setCurrentValue(int value) {
- if (mCurrentValue != value) {
- mCurrentValue = value;
- return true;
- }
- return false;
+ public void setCurrentValue(int value) {
+ mCurrentValue = value;
}
/**
- * Get total items count between minValue(inclusive) and maxValue (inclusive).
- * @return Total items count between minValue(inclusive) and maxValue (inclusive).
+ * Get total items count between minValue and maxValue.
+ * @return Total items count between minValue and maxValue.
*/
- public int getItemsCount() {
+ public int getItemCount() {
return mMaxValue - mMinValue + 1;
}
/**
- * Returns minimal value (inclusive) of the Column.
- * @return Minimal value (inclusive) of the Column.
+ * Returns minimal value of the Column.
+ * @return Minimal value of the Column.
*/
public int getMinValue() {
return mMinValue;
}
/**
- * Returns maximum value (inclusive) of the Column.
- * @return Maximum value (inclusive) of the Column.
+ * Returns maximum value of the Column.
+ * @return Maximum value of the Column.
*/
public int getMaxValue() {
return mMaxValue;
}
/**
- * Sets minimal value (inclusive) of the Column.
+ * Sets minimal value of the Column.
* @param minValue New minimal value to set.
- * @return True if minimal value changes.
*/
- public boolean setMinValue(int minValue) {
- if (minValue != mMinValue) {
- mMinValue = minValue;
- return true;
- }
- return false;
+ public void setMinValue(int minValue) {
+ mMinValue = minValue;
}
/**
- * Sets maximum value (inclusive) of the Column.
+ * Sets maximum value of the Column.
* @param maxValue New maximum value to set.
- * @return True if maximum value changes.
*/
- public boolean setMaxValue(int maxValue) {
- if (maxValue != mMaxValue) {
- mMaxValue = maxValue;
- return true;
- }
- return false;
- }
-
- public static Parcelable.Creator<PickerColumn>
- CREATOR = new Parcelable.Creator<PickerColumn>() {
-
- @Override
- public PickerColumn createFromParcel(Parcel source) {
- return new PickerColumn(source);
- }
-
- @Override
- public PickerColumn[] newArray(int size) {
- return new PickerColumn[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mValueFormat);
- if (mStaticLabels != null) {
- dest.writeInt(mStaticLabels.length);
- dest.writeStringArray(mStaticLabels);
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mCurrentValue);
- dest.writeInt(mMinValue);
- dest.writeInt(mMaxValue);
+ public void setMaxValue(int maxValue) {
+ mMaxValue = maxValue;
}
}
diff --git a/v4/api/current.txt b/v4/api/current.txt
index c9a72b1..15e7868 100644
--- a/v4/api/current.txt
+++ b/v4/api/current.txt
@@ -1106,8 +1106,8 @@
method public static int XYZToColor(double, double, double);
method public static void XYZToLAB(double, double, double, double[]);
method public static int blendARGB(int, int, float);
- method public static void blendHSL(float[], float[], float[], float);
- method public static void blendLAB(double[], double[], double[], double);
+ method public static void blendHSL(float[], float[], float, float[]);
+ method public static void blendLAB(double[], double[], double, double[]);
method public static double calculateContrast(int, int);
method public static double calculateLuminance(int);
method public static int calculateMinimumAlpha(int, int, float);
diff --git a/v4/java/android/support/v4/graphics/ColorUtils.java b/v4/java/android/support/v4/graphics/ColorUtils.java
index 2a3074e..85768f6 100644
--- a/v4/java/android/support/v4/graphics/ColorUtils.java
+++ b/v4/java/android/support/v4/graphics/ColorUtils.java
@@ -22,7 +22,6 @@
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
-import android.util.TypedValue;
/**
* A set of color-related utility methods, building upon those available in {@code Color}.
@@ -75,11 +74,7 @@
*/
@FloatRange(from = 0.0, to = 1.0)
public static double calculateLuminance(@ColorInt int color) {
- double[] result = TEMP_ARRAY.get();
- if (result == null) {
- result = new double[3];
- TEMP_ARRAY.set(result);
- }
+ final double[] result = getTempDouble3Array();
colorToXYZ(color, result);
// Luminance is the Y component
return result[1] / 100;
@@ -114,10 +109,10 @@
* have a contrast value of at least {@code minContrastRatio} when compared to
* {@code background}.
*
- * @param foreground the foreground color.
- * @param background the background color. Should be opaque.
- * @param minContrastRatio the minimum contrast ratio.
- * @return the alpha value in the range 0-255, or -1 if no value could be calculated.
+ * @param foreground the foreground color
+ * @param background the opaque background color
+ * @param minContrastRatio the minimum contrast ratio
+ * @return the alpha value in the range 0-255, or -1 if no value could be calculated
*/
public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background,
float minContrastRatio) {
@@ -162,19 +157,19 @@
/**
* Convert RGB components to HSL (hue-saturation-lightness).
* <ul>
- * <li>hsl[0] is Hue [0 .. 360)</li>
- * <li>hsl[1] is Saturation [0...1]</li>
- * <li>hsl[2] is Lightness [0...1]</li>
+ * <li>outHsl[0] is Hue [0 .. 360)</li>
+ * <li>outHsl[1] is Saturation [0...1]</li>
+ * <li>outHsl[2] is Lightness [0...1]</li>
* </ul>
*
- * @param r red component value [0..255]
- * @param g green component value [0..255]
- * @param b blue component value [0..255]
- * @param hsl 3 element array which holds the resulting HSL components.
+ * @param r red component value [0..255]
+ * @param g green component value [0..255]
+ * @param b blue component value [0..255]
+ * @param outHsl 3-element array which holds the resulting HSL components
*/
public static void RGBToHSL(@IntRange(from = 0x0, to = 0xFF) int r,
@IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
- @NonNull float[] hsl) {
+ @NonNull float[] outHsl) {
final float rf = r / 255f;
final float gf = g / 255f;
final float bf = b / 255f;
@@ -206,24 +201,24 @@
h += 360f;
}
- hsl[0] = constrain(h, 0f, 360f);
- hsl[1] = constrain(s, 0f, 1f);
- hsl[2] = constrain(l, 0f, 1f);
+ outHsl[0] = constrain(h, 0f, 360f);
+ outHsl[1] = constrain(s, 0f, 1f);
+ outHsl[2] = constrain(l, 0f, 1f);
}
/**
* Convert the ARGB color to its HSL (hue-saturation-lightness) components.
* <ul>
- * <li>hsl[0] is Hue [0 .. 360)</li>
- * <li>hsl[1] is Saturation [0...1]</li>
- * <li>hsl[2] is Lightness [0...1]</li>
+ * <li>outHsl[0] is Hue [0 .. 360)</li>
+ * <li>outHsl[1] is Saturation [0...1]</li>
+ * <li>outHsl[2] is Lightness [0...1]</li>
* </ul>
*
- * @param color the ARGB color to convert. The alpha component is ignored.
- * @param hsl 3 element array which holds the resulting HSL components.
+ * @param color the ARGB color to convert. The alpha component is ignored
+ * @param outHsl 3-element array which holds the resulting HSL components
*/
- public static void colorToHSL(@ColorInt int color, @NonNull float[] hsl) {
- RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hsl);
+ public static void colorToHSL(@ColorInt int color, @NonNull float[] outHsl) {
+ RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), outHsl);
}
/**
@@ -235,7 +230,7 @@
* </ul>
* If hsv values are out of range, they are pinned.
*
- * @param hsl 3 element array which holds the input HSL components.
+ * @param hsl 3-element array which holds the input HSL components
* @return the resulting RGB color
*/
@ColorInt
@@ -308,35 +303,35 @@
/**
* Convert the ARGB color to its CIE Lab representative components.
*
- * @param color the ARGB color to convert. The alpha component is ignored.
- * @param result 3 element array which holds the resulting LAB components.
+ * @param color the ARGB color to convert. The alpha component is ignored
+ * @param outLab 3-element array which holds the resulting LAB components
*/
- public static void colorToLAB(@ColorInt int color, @NonNull double[] result) {
- RGBToLAB(Color.red(color), Color.green(color), Color.blue(color), result);
+ public static void colorToLAB(@ColorInt int color, @NonNull double[] outLab) {
+ RGBToLAB(Color.red(color), Color.green(color), Color.blue(color), outLab);
}
/**
* Convert RGB components to its CIE Lab representative components.
*
* <ul>
- * <li>result[0] is L [0 ...1)</li>
- * <li>result[1] is a [-128...127)</li>
- * <li>result[2] is b [-128...127)</li>
+ * <li>outLab[0] is L [0 ...1)</li>
+ * <li>outLab[1] is a [-128...127)</li>
+ * <li>outLab[2] is b [-128...127)</li>
* </ul>
*
- * @param r red component value [0..255)
- * @param g green component value [0..255)
- * @param b blue component value [0..255)
- * @param result 3 element array which holds the resulting LAB components.
+ * @param r red component value [0..255]
+ * @param g green component value [0..255]
+ * @param b blue component value [0..255]
+ * @param outLab 3-element array which holds the resulting LAB components
*/
public static void RGBToLAB(@IntRange(from = 0x0, to = 0xFF) int r,
@IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
- @NonNull double[] result) {
+ @NonNull double[] outLab) {
// First we convert RGB to XYZ
- RGBToXYZ(r, g, b, result);
- // result now contains XYZ
- XYZToLAB(result[0], result[1], result[2], result);
- // result now contains LAB representation
+ RGBToXYZ(r, g, b, outLab);
+ // outLab now contains XYZ
+ XYZToLAB(outLab[0], outLab[1], outLab[2], outLab);
+ // outLab now contains LAB representation
}
/**
@@ -346,16 +341,16 @@
* 2° Standard Observer (1931).</p>
*
* <ul>
- * <li>result[0] is X [0 ...95.047)</li>
- * <li>result[1] is Y [0...100)</li>
- * <li>result[2] is Z [0...108.883)</li>
+ * <li>outXyz[0] is X [0 ...95.047)</li>
+ * <li>outXyz[1] is Y [0...100)</li>
+ * <li>outXyz[2] is Z [0...108.883)</li>
* </ul>
*
- * @param color the ARGB color to convert. The alpha component is ignored.
- * @param result 3 element array which holds the resulting LAB components.
+ * @param color the ARGB color to convert. The alpha component is ignored
+ * @param outXyz 3-element array which holds the resulting LAB components
*/
- public static void colorToXYZ(@ColorInt int color, @NonNull double[] result) {
- RGBToXYZ(Color.red(color), Color.green(color), Color.blue(color), result);
+ public static void colorToXYZ(@ColorInt int color, @NonNull double[] outXyz) {
+ RGBToXYZ(Color.red(color), Color.green(color), Color.blue(color), outXyz);
}
/**
@@ -365,21 +360,21 @@
* 2° Standard Observer (1931).</p>
*
* <ul>
- * <li>result[0] is X [0 ...95.047)</li>
- * <li>result[1] is Y [0...100)</li>
- * <li>result[2] is Z [0...108.883)</li>
+ * <li>outXyz[0] is X [0 ...95.047)</li>
+ * <li>outXyz[1] is Y [0...100)</li>
+ * <li>outXyz[2] is Z [0...108.883)</li>
* </ul>
*
- * @param r red component value [0..255)
- * @param g green component value [0..255)
- * @param b blue component value [0..255)
- * @param result 3 element array which holds the resulting XYZ components.
+ * @param r red component value [0..255]
+ * @param g green component value [0..255]
+ * @param b blue component value [0..255]
+ * @param outXyz 3-element array which holds the resulting XYZ components
*/
public static void RGBToXYZ(@IntRange(from = 0x0, to = 0xFF) int r,
@IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
- @NonNull double[] result) {
- if (result.length != 3) {
- throw new IllegalArgumentException("result must have a length of 3.");
+ @NonNull double[] outXyz) {
+ if (outXyz.length != 3) {
+ throw new IllegalArgumentException("outXyz must have a length of 3.");
}
double sr = r / 255.0;
@@ -389,9 +384,9 @@
double sb = b / 255.0;
sb = sb < 0.04045 ? sb / 12.92 : Math.pow((sb + 0.055) / 1.055, 2.4);
- result[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805);
- result[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722);
- result[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505);
+ outXyz[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805);
+ outXyz[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722);
+ outXyz[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505);
}
/**
@@ -401,29 +396,29 @@
* 2° Standard Observer (1931).</p>
*
* <ul>
- * <li>result[0] is L [0 ...1)</li>
- * <li>result[1] is a [-128...127)</li>
- * <li>result[2] is b [-128...127)</li>
+ * <li>outLab[0] is L [0 ...1)</li>
+ * <li>outLab[1] is a [-128...127)</li>
+ * <li>outLab[2] is b [-128...127)</li>
* </ul>
*
- * @param x X component value [0...95.047)
- * @param y Y component value [0...100)
- * @param z Z component value [0...108.883)
- * @param result 3 element array which holds the resulting Lab components.
+ * @param x X component value [0...95.047)
+ * @param y Y component value [0...100)
+ * @param z Z component value [0...108.883)
+ * @param outLab 3-element array which holds the resulting Lab components
*/
public static void XYZToLAB(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z,
- @NonNull double[] result) {
- if (result.length != 3) {
- throw new IllegalArgumentException("result must have a length of 3.");
+ @NonNull double[] outLab) {
+ if (outLab.length != 3) {
+ throw new IllegalArgumentException("outLab must have a length of 3.");
}
x = pivotXyzComponent(x / XYZ_WHITE_REFERENCE_X);
y = pivotXyzComponent(y / XYZ_WHITE_REFERENCE_Y);
z = pivotXyzComponent(z / XYZ_WHITE_REFERENCE_Z);
- result[0] = Math.max(0, 116 * y - 16);
- result[1] = 500 * (x - y);
- result[2] = 200 * (y - z);
+ outLab[0] = Math.max(0, 116 * y - 16);
+ outLab[1] = 500 * (x - y);
+ outLab[2] = 200 * (y - z);
}
/**
@@ -433,20 +428,20 @@
* 2° Standard Observer (1931).</p>
*
* <ul>
- * <li>result[0] is X [0 ...95.047)</li>
- * <li>result[1] is Y [0...100)</li>
- * <li>result[2] is Z [0...108.883)</li>
+ * <li>outXyz[0] is X [0 ...95.047)</li>
+ * <li>outXyz[1] is Y [0...100)</li>
+ * <li>outXyz[2] is Z [0...108.883)</li>
* </ul>
*
- * @param l L component value [0...100)
- * @param a A component value [-128...127)
- * @param b B component value [-128...127)
- * @param result 3 element array which holds the resulting XYZ components.
+ * @param l L component value [0...100)
+ * @param a A component value [-128...127)
+ * @param b B component value [-128...127)
+ * @param outXyz 3-element array which holds the resulting XYZ components
*/
public static void LABToXYZ(@FloatRange(from = 0f, to = 100) final double l,
@FloatRange(from = -128, to = 127) final double a,
@FloatRange(from = -128, to = 127) final double b,
- @NonNull double[] result) {
+ @NonNull double[] outXyz) {
final double fy = (l + 16) / 116;
final double fx = a / 500 + fy;
final double fz = fy - b / 200;
@@ -458,9 +453,9 @@
tmp = Math.pow(fz, 3);
final double zr = tmp > XYZ_EPSILON ? tmp : (116 * fz - 16) / XYZ_KAPPA;
- result[0] = xr * XYZ_WHITE_REFERENCE_X;
- result[1] = yr * XYZ_WHITE_REFERENCE_Y;
- result[2] = zr * XYZ_WHITE_REFERENCE_Z;
+ outXyz[0] = xr * XYZ_WHITE_REFERENCE_X;
+ outXyz[1] = yr * XYZ_WHITE_REFERENCE_Y;
+ outXyz[2] = zr * XYZ_WHITE_REFERENCE_Z;
}
/**
@@ -495,16 +490,16 @@
/**
* Converts a color from CIE Lab to its RGB representation.
*
- * @param l L component value [0...100)
- * @param a A component value [-128...127)
- * @param b B component value [-128...127)
+ * @param l L component value [0...100]
+ * @param a A component value [-128...127]
+ * @param b B component value [-128...127]
* @return int containing the RGB representation
*/
@ColorInt
public static int LABToColor(@FloatRange(from = 0f, to = 100) final double l,
@FloatRange(from = -128, to = 127) final double a,
@FloatRange(from = -128, to = 127) final double b) {
- final double[] result = new double[3];
+ final double[] result = getTempDouble3Array();
LABToXYZ(l, a, b, result);
return XYZToColor(result[0], result[1], result[2]);
}
@@ -535,8 +530,12 @@
/**
* Blend between two ARGB colors using the given ratio.
*
- * @param ratio of which to blend. 0.0 will return {@code color1}, 0.5 will give an even blend,
- * 1.0 will return {@code color2}.
+ * <p>A blend ratio of 0.0 will result in {@code color1}, 0.5 will give an even blend,
+ * 1.0 will result in {@code color2}.</p>
+ *
+ * @param color1 the first ARGB color
+ * @param color2 the second ARGB color
+ * @param ratio the blend ratio of {@code color1} to {@code color2}
*/
@ColorInt
public static int blendARGB(@ColorInt int color1, @ColorInt int color2,
@@ -553,43 +552,46 @@
* Blend between {@code hsl1} and {@code hsl2} using the given ratio. This will interpolate
* the hue using the shortest angle.
*
- * @param hsl1 3 element array which holds the first HSL color.
- * @param hsl2 3 element array which holds the second HSL color.
- * @param result 3 element array which holds the resulting HSL components.
- * @param ratio of which to blend. 0.0 will result in {@code hsl1},
- * 0.5 will give an even blend, 1.0 will return {@code hsl2}.
+ * <p>A blend ratio of 0.0 will result in {@code hsl1}, 0.5 will give an even blend,
+ * 1.0 will result in {@code hsl2}.</p>
+ *
+ * @param hsl1 3-element array which holds the first HSL color
+ * @param hsl2 3-element array which holds the second HSL color
+ * @param ratio the blend ratio of {@code hsl1} to {@code hsl2}
+ * @param outResult 3-element array which holds the resulting HSL components
*/
public static void blendHSL(@NonNull float[] hsl1, @NonNull float[] hsl2,
- @NonNull float[] result, @FloatRange(from = 0.0, to = 1.0) float ratio) {
- if (result.length != 3) {
+ @FloatRange(from = 0.0, to = 1.0) float ratio, @NonNull float[] outResult) {
+ if (outResult.length != 3) {
throw new IllegalArgumentException("result must have a length of 3.");
}
final float inverseRatio = 1 - ratio;
// Since hue is circular we will need to interpolate carefully
- result[0] = circularInterpolate(hsl1[0], hsl2[0], ratio);
- result[1] = hsl1[1] * inverseRatio + hsl2[1] * ratio;
- result[2] = hsl1[2] * inverseRatio + hsl2[2] * ratio;
+ outResult[0] = circularInterpolate(hsl1[0], hsl2[0], ratio);
+ outResult[1] = hsl1[1] * inverseRatio + hsl2[1] * ratio;
+ outResult[2] = hsl1[2] * inverseRatio + hsl2[2] * ratio;
}
/**
* Blend between two CIE-LAB colors using the given ratio.
*
- * @param lab1 3 element array which holds the first LAB color.
- * @param lab2 3 element array which holds the second LAB color.
- * @param result 3 element array which holds the resulting LAB components.
- * @param ratio of which to blend. 0.0 will result in {@code lab1}, 0.5 will give an even blend,
- * 1.0 will return {@code lab2}.
+ * <p>A blend ratio of 0.0 will result in {@code lab1}, 0.5 will give an even blend,
+ * 1.0 will result in {@code lab2}.</p>
+ *
+ * @param lab1 3-element array which holds the first LAB color
+ * @param lab2 3-element array which holds the second LAB color
+ * @param ratio the blend ratio of {@code lab1} to {@code lab2}
+ * @param outResult 3-element array which holds the resulting LAB components
*/
- public static void blendLAB(@NonNull double[] lab1,
- @NonNull double[] lab2, @NonNull double[] result,
- @FloatRange(from = 0.0, to = 1.0) double ratio) {
- if (result.length != 3) {
- throw new IllegalArgumentException("result must have a length of 3.");
+ public static void blendLAB(@NonNull double[] lab1, @NonNull double[] lab2,
+ @FloatRange(from = 0.0, to = 1.0) double ratio, @NonNull double[] outResult) {
+ if (outResult.length != 3) {
+ throw new IllegalArgumentException("outResult must have a length of 3.");
}
final double inverseRatio = 1 - ratio;
- result[0] = lab1[0] * inverseRatio + lab2[0] * ratio;
- result[1] = lab1[1] * inverseRatio + lab2[1] * ratio;
- result[2] = lab1[2] * inverseRatio + lab2[2] * ratio;
+ outResult[0] = lab1[0] * inverseRatio + lab2[0] * ratio;
+ outResult[1] = lab1[1] * inverseRatio + lab2[1] * ratio;
+ outResult[2] = lab1[2] * inverseRatio + lab2[2] * ratio;
}
@VisibleForTesting
@@ -604,4 +606,13 @@
return (a + ((b - a) * f)) % 360;
}
+ private static double[] getTempDouble3Array() {
+ double[] result = TEMP_ARRAY.get();
+ if (result == null) {
+ result = new double[3];
+ TEMP_ARRAY.set(result);
+ }
+ return result;
+ }
+
}
diff --git a/v7/appcompat/res/values-ldrtl-v23/styles_base.xml b/v7/appcompat/res/values-ldrtl-v23/styles_base.xml
deleted file mode 100644
index cba56bd..0000000
--- a/v7/appcompat/res/values-ldrtl-v23/styles_base.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<resources>
-
- <style name="Base.Widget.AppCompat.Spinner.Underlined" parent="android:Widget.Material.Spinner.Underlined" />
-
-</resources>
diff --git a/v7/appcompat/res/values-v23/styles_base.xml b/v7/appcompat/res/values-v23/styles_base.xml
index 3b0e55c..56563c7 100644
--- a/v7/appcompat/res/values-v23/styles_base.xml
+++ b/v7/appcompat/res/values-v23/styles_base.xml
@@ -23,4 +23,6 @@
<style name="Base.Widget.AppCompat.RatingBar.Small" parent="android:Widget.Material.RatingBar.Small" />
+ <style name="Base.Widget.AppCompat.Spinner.Underlined" parent="android:Widget.Material.Spinner.Underlined" />
+
</resources>