am 168e4ed6: am 6789459d: am 88242bfd: Merge "Fix janky browse transition" into mnc-dev
* commit '168e4ed63a3434f782f5e7a26aa69ceb5cf59add':
Fix janky browse transition
diff --git a/design/base/android/support/design/widget/StateListAnimator.java b/design/base/android/support/design/widget/StateListAnimator.java
index c937b0b..2de5dba 100644
--- a/design/base/android/support/design/widget/StateListAnimator.java
+++ b/design/base/android/support/design/widget/StateListAnimator.java
@@ -124,8 +124,11 @@
if (mLastMatch != null) {
cancel();
}
+
mLastMatch = match;
- if (match != null) {
+
+ View view = mViewRef.get();
+ if (match != null && view != null && view.getVisibility() == View.VISIBLE ) {
start(match);
}
}
diff --git a/design/res/layout/design_menu_item_action_area.xml b/design/res/layout/design_menu_item_action_area.xml
new file mode 100644
index 0000000..ba8141d
--- /dev/null
+++ b/design/res/layout/design_menu_item_action_area.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"/>
diff --git a/design/res/layout/design_navigation_item.xml b/design/res/layout/design_navigation_item.xml
index 3fcd74a..14c1be3 100644
--- a/design/res/layout/design_navigation_item.xml
+++ b/design/res/layout/design_navigation_item.xml
@@ -19,8 +19,4 @@
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeightSmall"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
- android:paddingRight="?attr/listPreferredItemPaddingRight"
- android:drawablePadding="@dimen/design_navigation_icon_padding"
- android:gravity="center_vertical|start"
- android:maxLines="1"
- android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>
+ android:paddingRight="?attr/listPreferredItemPaddingRight"/>
diff --git a/design/res/layout/design_navigation_menu_item.xml b/design/res/layout/design_navigation_menu_item.xml
new file mode 100644
index 0000000..91104bb1
--- /dev/null
+++ b/design/res/layout/design_navigation_menu_item.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <CheckedTextView
+ android:id="@+id/design_menu_item_text"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:drawablePadding="@dimen/design_navigation_icon_padding"
+ android:gravity="center_vertical|start"
+ android:maxLines="1"
+ android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>
+
+ <ViewStub
+ android:id="@+id/design_menu_item_action_area_stub"
+ android:inflatedId="@+id/design_menu_item_action_area"
+ android:layout="@layout/design_menu_item_action_area"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"/>
+
+</merge>
diff --git a/design/src/android/support/design/internal/NavigationMenuItemView.java b/design/src/android/support/design/internal/NavigationMenuItemView.java
index 7813163..1d819df 100644
--- a/design/src/android/support/design/internal/NavigationMenuItemView.java
+++ b/design/src/android/support/design/internal/NavigationMenuItemView.java
@@ -27,19 +27,30 @@
import android.support.v4.widget.TextViewCompat;
import android.support.v7.internal.view.menu.MenuItemImpl;
import android.support.v7.internal.view.menu.MenuView;
+import android.support.v7.widget.LinearLayoutCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
-import android.widget.TextView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewStub;
+import android.widget.CheckedTextView;
+import android.widget.FrameLayout;
/**
* @hide
*/
-public class NavigationMenuItemView extends TextView implements MenuView.ItemView {
+public class NavigationMenuItemView extends LinearLayoutCompat implements MenuView.ItemView {
private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
- private int mIconSize;
+ private final int mIconSize;
+
+ private final CheckedTextView mTextView;
+
+ private FrameLayout mActionArea;
+
private MenuItemImpl mItemData;
+
private ColorStateList mIconTintList;
public NavigationMenuItemView(Context context) {
@@ -52,8 +63,14 @@
public NavigationMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ setOrientation(HORIZONTAL);
+ LayoutInflater.from(context).inflate(R.layout.design_navigation_menu_item, this, true);
mIconSize = context.getResources().getDimensionPixelSize(
R.dimen.design_navigation_icon_size);
+ mTextView = (CheckedTextView) findViewById(R.id.design_menu_item_text);
+ mTextView.setDuplicateParentStateEnabled(true);
+ // Prevent the action view from stealing the event on the item row.
+ setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
}
@Override
@@ -71,6 +88,18 @@
setEnabled(itemData.isEnabled());
setTitle(itemData.getTitle());
setIcon(itemData.getIcon());
+ setActionView(itemData.getActionView());
+ }
+
+ private void setActionView(View actionView) {
+ if (mActionArea == null) {
+ mActionArea = (FrameLayout) ((ViewStub) findViewById(
+ R.id.design_menu_item_action_area_stub)).inflate();
+ }
+ mActionArea.removeAllViews();
+ if (actionView != null) {
+ mActionArea.addView(actionView);
+ }
}
private StateListDrawable createDefaultBackground() {
@@ -91,7 +120,7 @@
@Override
public void setTitle(CharSequence title) {
- setText(title);
+ mTextView.setText(title);
}
@Override
@@ -102,6 +131,7 @@
@Override
public void setChecked(boolean checked) {
refreshDrawableState();
+ mTextView.setChecked(checked);
}
@Override
@@ -115,7 +145,7 @@
icon.setBounds(0, 0, mIconSize, mIconSize);
DrawableCompat.setTintList(icon, mIconTintList);
}
- TextViewCompat.setCompoundDrawablesRelative(this, icon, null, null, null);
+ TextViewCompat.setCompoundDrawablesRelative(mTextView, icon, null, null, null);
}
@Override
@@ -144,4 +174,13 @@
setIcon(mItemData.getIcon());
}
}
+
+ public void setTextAppearance(Context context, int textAppearance) {
+ mTextView.setTextAppearance(context, textAppearance);
+ }
+
+ public void setTextColor(ColorStateList colors) {
+ mTextView.setTextColor(colors);
+ }
+
}
diff --git a/design/src/android/support/design/internal/NavigationMenuPresenter.java b/design/src/android/support/design/internal/NavigationMenuPresenter.java
index e523c38..41b361b 100644
--- a/design/src/android/support/design/internal/NavigationMenuPresenter.java
+++ b/design/src/android/support/design/internal/NavigationMenuPresenter.java
@@ -266,6 +266,7 @@
private static final String STATE_CHECKED_ITEM = "android:menu:checked";
+ private static final String STATE_ACTION_VIEWS = "android:menu:action_views";
private static final int VIEW_TYPE_NORMAL = 0;
private static final int VIEW_TYPE_SUBHEADER = 1;
private static final int VIEW_TYPE_SEPARATOR = 2;
@@ -470,6 +471,18 @@
if (mCheckedItem != null) {
state.putInt(STATE_CHECKED_ITEM, mCheckedItem.getItemId());
}
+ // Store the states of the action views.
+ SparseArray<ParcelableSparseArray> actionViewStates = new SparseArray<>();
+ for (NavigationMenuItem navigationMenuItem : mItems) {
+ MenuItemImpl item = navigationMenuItem.getMenuItem();
+ View actionView = item != null ? item.getActionView() : null;
+ if (actionView != null) {
+ ParcelableSparseArray container = new ParcelableSparseArray();
+ actionView.saveHierarchyState(container);
+ actionViewStates.put(item.getItemId(), container);
+ }
+ }
+ state.putSparseParcelableArray(STATE_ACTION_VIEWS, actionViewStates);
return state;
}
@@ -479,7 +492,7 @@
mUpdateSuspended = true;
for (NavigationMenuItem item : mItems) {
MenuItemImpl menuItem = item.getMenuItem();
- if (menuItem != null && menuItem.getItemId() == checkedItem) {
+ if (menuItem != null && menuItem.getItemId() == checkedItem) {
setCheckedItem(menuItem);
break;
}
@@ -487,6 +500,16 @@
mUpdateSuspended = false;
prepareMenuItems();
}
+ // Restore the states of the action views.
+ SparseArray<ParcelableSparseArray> actionViewStates = state
+ .getSparseParcelableArray(STATE_ACTION_VIEWS);
+ for (NavigationMenuItem navigationMenuItem : mItems) {
+ MenuItemImpl item = navigationMenuItem.getMenuItem();
+ View actionView = item != null ? item.getActionView() : null;
+ if (actionView != null) {
+ actionView.restoreHierarchyState(actionViewStates.get(item.getItemId()));
+ }
+ }
}
public void setUpdateSuspended(boolean updateSuspended) {
diff --git a/design/src/android/support/design/internal/ParcelableSparseArray.java b/design/src/android/support/design/internal/ParcelableSparseArray.java
new file mode 100644
index 0000000..74abcc2
--- /dev/null
+++ b/design/src/android/support/design/internal/ParcelableSparseArray.java
@@ -0,0 +1,76 @@
+/*
+ * 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.design.internal;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+
+/**
+ * @hide
+ */
+public class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable {
+
+ public ParcelableSparseArray() {
+ super();
+ }
+
+ public ParcelableSparseArray(Parcel source) {
+ super();
+ int size = source.readInt();
+ int[] keys = new int[size];
+ source.readIntArray(keys);
+ Parcelable[] values = source.readParcelableArray(
+ ParcelableSparseArray.class.getClassLoader());
+ for (int i = 0; i < size; ++i) {
+ put(keys[i], values[i]);
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ int size = size();
+ int[] keys = new int[size];
+ Parcelable[] values = new Parcelable[size];
+ for (int i = 0; i < size; ++i) {
+ keys[i] = keyAt(i);
+ values[i] = valueAt(i);
+ }
+ parcel.writeInt(size);
+ parcel.writeIntArray(keys);
+ parcel.writeParcelableArray(values, flags);
+ }
+
+ public static final Parcelable.Creator<ParcelableSparseArray> CREATOR
+ = new Creator<ParcelableSparseArray>() {
+ @Override
+ public ParcelableSparseArray createFromParcel(Parcel source) {
+ return new ParcelableSparseArray(source);
+ }
+
+ @Override
+ public ParcelableSparseArray[] newArray(int size) {
+ return new ParcelableSparseArray[size];
+ }
+ };
+
+}
diff --git a/design/src/android/support/design/widget/TextInputLayout.java b/design/src/android/support/design/widget/TextInputLayout.java
index a3d8dcd..2826344 100644
--- a/design/src/android/support/design/widget/TextInputLayout.java
+++ b/design/src/android/support/design/widget/TextInputLayout.java
@@ -95,7 +95,7 @@
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.TextInputLayout, defStyleAttr, R.style.Widget_Design_TextInputLayout);
- mHint = a.getText(R.styleable.TextInputLayout_android_hint);
+ setHint(a.getText(R.styleable.TextInputLayout_android_hint));
mHintAnimationEnabled = a.getBoolean(
R.styleable.TextInputLayout_hintAnimationEnabled, true);
diff --git a/v17/leanback/Android.mk b/v17/leanback/Android.mk
index dd03d6a..57b54e0 100644
--- a/v17/leanback/Android.mk
+++ b/v17/leanback/Android.mk
@@ -40,6 +40,16 @@
# -----------------------------------------------------------------------
+# A helper sub-library that makes direct use of API 23.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v17-leanback-api23
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, api23)
+LOCAL_JAVA_LIBRARIES := android-support-v17-leanback-res android-support-v17-leanback-common
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# -----------------------------------------------------------------------
+
# A helper sub-library that makes direct use of API 21.
include $(CLEAR_VARS)
LOCAL_MODULE := android-support-v17-leanback-api21
@@ -79,6 +89,7 @@
LOCAL_SDK_VERSION := 17
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v17-leanback-kitkat android-support-v17-leanback-jbmr2 \
+ android-support-v17-leanback-api23 \
android-support-v17-leanback-api21 android-support-v17-leanback-common
LOCAL_JAVA_LIBRARIES := \
android-support-v4 \
diff --git a/v17/leanback/api/current.txt b/v17/leanback/api/current.txt
index d25529c..388ce92 100644
--- a/v17/leanback/api/current.txt
+++ b/v17/leanback/api/current.txt
@@ -189,6 +189,7 @@
method public android.support.v17.leanback.widget.GuidanceStylist.Guidance onCreateGuidance(android.os.Bundle);
method public android.support.v17.leanback.widget.GuidanceStylist onCreateGuidanceStylist();
method public void onGuidedActionClicked(android.support.v17.leanback.widget.GuidedAction);
+ method public void onGuidedActionEdited(android.support.v17.leanback.widget.GuidedAction);
method public void onGuidedActionFocused(android.support.v17.leanback.widget.GuidedAction);
method public int onProvideTheme();
method public void setActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>);
@@ -744,6 +745,8 @@
method public abstract void onFragmentExit(java.util.List<android.animation.Animator>);
method public abstract void onFragmentReenter(java.util.List<android.animation.Animator>);
method public abstract void onFragmentReturn(java.util.List<android.animation.Animator>);
+ method public abstract void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public abstract void onImeDisappearing(java.util.List<android.animation.Animator>);
}
public class FullWidthDetailsOverviewRowPresenter extends android.support.v17.leanback.widget.RowPresenter {
@@ -821,6 +824,8 @@
method public void onFragmentExit(java.util.List<android.animation.Animator>);
method public void onFragmentReenter(java.util.List<android.animation.Animator>);
method public void onFragmentReturn(java.util.List<android.animation.Animator>);
+ method public void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public void onImeDisappearing(java.util.List<android.animation.Animator>);
method public int onProvideLayoutId();
}
@@ -841,9 +846,11 @@
method public boolean hasNext();
method public boolean infoOnly();
method public boolean isChecked();
+ method public boolean isEditable();
method public boolean isEnabled();
method public void setChecked(boolean);
method public void setEnabled(boolean);
+ method public void setTitle(java.lang.CharSequence);
field public static final int DEFAULT_CHECK_SET_ID = 1; // 0x1
field public static final int NO_CHECK_SET = 0; // 0x0
field public static final int NO_DRAWABLE = 0; // 0x0
@@ -855,6 +862,7 @@
method public android.support.v17.leanback.widget.GuidedAction.Builder checkSetId(int);
method public android.support.v17.leanback.widget.GuidedAction.Builder checked(boolean);
method public android.support.v17.leanback.widget.GuidedAction.Builder description(java.lang.String);
+ method public android.support.v17.leanback.widget.GuidedAction.Builder editable(boolean);
method public android.support.v17.leanback.widget.GuidedAction.Builder enabled(boolean);
method public android.support.v17.leanback.widget.GuidedAction.Builder hasNext(boolean);
method public android.support.v17.leanback.widget.GuidedAction.Builder icon(android.graphics.drawable.Drawable);
@@ -881,6 +889,8 @@
method public void onFragmentExit(java.util.List<android.animation.Animator>);
method public void onFragmentReenter(java.util.List<android.animation.Animator>);
method public void onFragmentReturn(java.util.List<android.animation.Animator>);
+ method public void onImeAppearing(java.util.List<android.animation.Animator>);
+ method public void onImeDisappearing(java.util.List<android.animation.Animator>);
method public int onProvideItemLayoutId();
method public int onProvideLayoutId();
field protected android.support.v17.leanback.widget.VerticalGridView mActionsGridView;
@@ -934,9 +944,10 @@
}
public class ImageCardView extends android.support.v17.leanback.widget.BaseCardView {
+ ctor public ImageCardView(android.content.Context, int);
+ ctor public ImageCardView(android.content.Context, android.util.AttributeSet, int);
ctor public ImageCardView(android.content.Context);
ctor public ImageCardView(android.content.Context, android.util.AttributeSet);
- ctor public ImageCardView(android.content.Context, android.util.AttributeSet, int);
method public android.graphics.drawable.Drawable getBadgeImage();
method public java.lang.CharSequence getContentText();
method public android.graphics.drawable.Drawable getInfoAreaBackground();
@@ -953,6 +964,19 @@
method public void setMainImageDimensions(int, int);
method public void setMainImageScaleType(android.widget.ImageView.ScaleType);
method public void setTitleText(java.lang.CharSequence);
+ field public static final int CARD_TYPE_FLAG_CONTENT = 2; // 0x2
+ field public static final int CARD_TYPE_FLAG_ICON_LEFT = 8; // 0x8
+ field public static final int CARD_TYPE_FLAG_ICON_RIGHT = 4; // 0x4
+ field public static final int CARD_TYPE_FLAG_IMAGE_ONLY = 0; // 0x0
+ field public static final int CARD_TYPE_FLAG_TITLE = 1; // 0x1
+ }
+
+ public abstract interface ImeKeyMonitor {
+ method public abstract void setImeKeyListener(android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener);
+ }
+
+ public static abstract interface ImeKeyMonitor.ImeKeyListener {
+ method public abstract boolean onKeyPreIme(android.widget.EditText, int, android.view.KeyEvent);
}
public final class ItemAlignmentFacet {
@@ -1463,10 +1487,12 @@
ctor public ShadowOverlayContainer(android.content.Context);
ctor public ShadowOverlayContainer(android.content.Context, android.util.AttributeSet);
ctor public ShadowOverlayContainer(android.content.Context, android.util.AttributeSet, int);
+ ctor public ShadowOverlayContainer(android.content.Context, int, boolean, boolean);
method public int getShadowType();
method public android.view.View getWrappedView();
method public deprecated void initialize(boolean, boolean);
- method public void initialize(boolean, boolean, boolean);
+ method public deprecated void initialize(boolean, boolean, boolean);
+ method public void initialize(int, boolean, boolean);
method protected void onLayout(boolean, int, int, int, int);
method public static void prepareParentForShadow(android.view.ViewGroup);
method public void setOverlayColor(int);
diff --git a/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java b/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
index ab4d179..cd4ff3e 100644
--- a/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
+++ b/v17/leanback/api21/android/support/v17/leanback/widget/ShadowHelperApi21.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
@@ -19,14 +19,14 @@
import android.graphics.Outline;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.view.ViewGroup;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
class ShadowHelperApi21 {
static class ShadowImpl {
- ViewGroup mShadowContainer;
+ View mShadowContainer;
float mNormalZ;
float mFocusedZ;
}
@@ -41,7 +41,7 @@
/* add shadows and return a implementation detail object */
public static Object addDynamicShadow(
- ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
+ View shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
if (roundedCorners) {
RoundedRectHelperApi21.setClipToRoundedOutline(shadowContainer, true);
} else {
@@ -52,7 +52,9 @@
impl.mNormalZ = unfocusedZ;
impl.mFocusedZ = focusedZ;
shadowContainer.setZ(impl.mNormalZ);
- shadowContainer.setTransitionGroup(true);
+ if (shadowContainer instanceof ViewGroup) {
+ ((ViewGroup) shadowContainer).setTransitionGroup(true);
+ }
return impl;
}
diff --git a/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java b/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java
new file mode 100644
index 0000000..c4760d4
--- /dev/null
+++ b/v17/leanback/api23/android/support/v17/leanback/widget/ForegroundHelperApi23.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.widget;
+
+import android.support.v17.leanback.R;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Outline;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.view.ViewGroup;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+class ForegroundHelperApi23 {
+
+ public static Drawable getForeground(View view) {
+ return view.getForeground();
+ }
+
+ public static void setForeground(View view, Drawable drawable) {
+ view.setForeground(drawable);
+ }
+}
diff --git a/v17/leanback/build.gradle b/v17/leanback/build.gradle
index 8dc79e8..401a5c4 100644
--- a/v17/leanback/build.gradle
+++ b/v17/leanback/build.gradle
@@ -19,8 +19,8 @@
sourceSets {
main.manifest.srcFile 'AndroidManifest.xml'
- main.java.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'src']
- main.aidl.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'src']
+ main.java.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'api23', 'src']
+ main.aidl.srcDirs = ['common', 'jbmr2', 'kitkat', 'api21', 'api23', 'src']
main.res.srcDirs = ['res']
androidTest.setRoot('tests')
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/animator/lb_guidedstep_slide_down.xml
similarity index 62%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/animator/lb_guidedstep_slide_down.xml
index 45a40e1..b31421f 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/animator/lb_guidedstep_slide_down.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 The Android Open Source Project
+ 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.
@@ -14,8 +14,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:propertyName="translationY"
+ android:valueFrom="@dimen/lb_guidedstep_slide_ime_distance"
+ android:valueTo="0.0"
+ android:valueType="floatType" />
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/animator/lb_guidedstep_slide_up.xml
similarity index 62%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/animator/lb_guidedstep_slide_up.xml
index 45a40e1..165fe18 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/animator/lb_guidedstep_slide_up.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 The Android Open Source Project
+ 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.
@@ -14,8 +14,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="@android:integer/config_shortAnimTime"
+ android:propertyName="translationY"
+ android:valueFrom="0.0"
+ android:valueTo="@dimen/lb_guidedstep_slide_ime_distance"
+ android:valueType="floatType" />
diff --git a/v17/leanback/res/layout/lb_guidedactions_item.xml b/v17/leanback/res/layout/lb_guidedactions_item.xml
index 4e41454..1d81470 100644
--- a/v17/leanback/res/layout/lb_guidedactions_item.xml
+++ b/v17/leanback/res/layout/lb_guidedactions_item.xml
@@ -34,7 +34,7 @@
android:id="@+id/guidedactions_item_content"
style="?attr/guidedActionItemContentStyle" >
- <TextView
+ <android.support.v17.leanback.widget.LeanbackEditText
android:id="@+id/guidedactions_item_title"
style="?attr/guidedActionItemTitleStyle" />
diff --git a/v17/leanback/res/layout/lb_image_card_view.xml b/v17/leanback/res/layout/lb_image_card_view.xml
index 2261965..1bc23f8 100644
--- a/v17/leanback/res/layout/lb_image_card_view.xml
+++ b/v17/leanback/res/layout/lb_image_card_view.xml
@@ -15,59 +15,16 @@
limitations under the License.
-->
-<merge
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:lb="http://schemas.android.com/apk/res-auto">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:lb="http://schemas.android.com/apk/res-auto" >
<ImageView
android:id="@+id/main_image"
- lb:layout_viewType="main"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scaleType="centerCrop"
- android:adjustViewBounds="true"
- android:contentDescription="@null" />
- <android.support.v17.leanback.widget.NonOverlappingRelativeLayout
- lb:layout_viewType="info"
- android:id="@+id/info_field"
- android:layout_width="match_parent"
- android:layout_height="@dimen/lb_basic_card_info_height"
- android:paddingStart="@dimen/lb_basic_card_info_padding_horizontal"
- android:paddingEnd="@dimen/lb_basic_card_info_padding_horizontal"
- android:paddingTop="@dimen/lb_basic_card_info_padding_top"
- android:layout_centerHorizontal="true" >
- <TextView
- android:id="@+id/title_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_marginBottom="@dimen/lb_basic_card_info_text_margin"
- android:maxLines="1"
- android:fontFamily="sans-serif-condensed"
- android:textColor="@color/lb_basic_card_title_text_color"
- android:textSize="@dimen/lb_basic_card_title_text_size"
- android:ellipsize="end" />
- <TextView
- android:id="@+id/content_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/title_text"
- android:layout_alignParentStart="true"
- android:layout_toStartOf="@+id/extra_badge"
- android:maxLines="1"
- android:fontFamily="sans-serif-condensed"
- android:textColor="@color/lb_basic_card_content_text_color"
- android:textSize="@dimen/lb_basic_card_content_text_size"
- android:ellipsize="none" />
- <ImageView
- android:id="@+id/extra_badge"
- android:layout_width="@dimen/lb_basic_card_info_badge_size"
- android:layout_height="@dimen/lb_basic_card_info_badge_size"
- android:layout_marginStart="@dimen/lb_basic_card_info_badge_margin"
- android:layout_alignBottom="@id/content_text"
- android:layout_alignParentEnd="true"
- android:scaleType="fitCenter"
- android:visibility="gone"
- android:contentDescription="@null" />
- </android.support.v17.leanback.widget.NonOverlappingRelativeLayout>
-</merge>
+ style="?attr/lbImageCardViewImageStyle" />
+
+ <android.support.v17.leanback.widget.NonOverlappingRelativeLayout
+ android:id="@+id/info_field"
+ style="?attr/lbImageCardViewInfoAreaStyle">
+ </android.support.v17.leanback.widget.NonOverlappingRelativeLayout>
+
+</merge>
\ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml
similarity index 68%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml
index 45a40e1..35d2da6 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_badge_left.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/extra_badge"
+ android:layout_alignBottom="@+id/content_text"
+ android:layout_alignParentStart="true"
+ android:layout_marginEnd="@dimen/lb_basic_card_info_badge_margin"
+ style="?attr/lbImageCardViewBadgeStyle" />
\ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml
similarity index 68%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml
index 45a40e1..02dd917 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_badge_right.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/extra_badge"
+ android:layout_alignBottom="@+id/content_text"
+ android:layout_alignParentEnd="true"
+ android:layout_marginStart="@dimen/lb_basic_card_info_badge_margin"
+ style="?attr/lbImageCardViewBadgeStyle" />
\ No newline at end of file
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_content.xml
similarity index 80%
rename from v17/leanback/res/layout/lb_card_color_overlay.xml
rename to v17/leanback/res/layout/lb_image_card_view_themed_content.xml
index 45a40e1..5592371 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_content.xml
@@ -15,7 +15,6 @@
limitations under the License.
-->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content_text"
+ style="?attr/lbImageCardViewContentStyle" />
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v17/leanback/res/layout/lb_image_card_view_themed_title.xml
similarity index 80%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v17/leanback/res/layout/lb_image_card_view_themed_title.xml
index 45a40e1..67e2493 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v17/leanback/res/layout/lb_image_card_view_themed_title.xml
@@ -15,7 +15,6 @@
limitations under the License.
-->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/title_text"
+ style="?attr/lbImageCardViewTitleStyle" />
diff --git a/v17/leanback/res/values-az-rAZ/strings.xml b/v17/leanback/res/values-az-rAZ/strings.xml
deleted file mode 100644
index d1e685f..0000000
--- a/v17/leanback/res/values-az-rAZ/strings.xml
+++ /dev/null
@@ -1,49 +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 xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="orb_search_action" msgid="5651268540267663887">"Axtarış Fəaliyyəti"</string>
- <string name="lb_search_bar_hint" msgid="8325490927970116252">"Axtarış"</string>
- <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Axtarış üçün danışın"</string>
- <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Axtarış: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
- <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Axtarış üçün danışın: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
- <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
- <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
- <string name="lb_playback_controls_play" msgid="731953341987346903">"Oyun"</string>
- <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pauza"</string>
- <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"İrəli Ötürmə"</string>
- <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"İrəli sarı %1$dX"</string>
- <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Geri ötürmə"</string>
- <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Geri sarı %1$dX"</string>
- <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Növbətini atlayın"</string>
- <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Öncəkini atlayın"</string>
- <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Digər fəaliyyətlər"</string>
- <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Bəyənməkdən imtina edin"</string>
- <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Bəyənin"</string>
- <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Bəyənməməkdən imtina edin"</string>
- <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Bəyənməyin"</string>
- <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Təkrarlanmasın"</string>
- <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Hamısını təkrarlayın"</string>
- <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Biri təkrarlansın"</string>
- <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Qarışdırma aktiv edilsin"</string>
- <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Qarışdırma deaktiv edilsin"</string>
- <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Yüksək keyfiyyəti aktiv edin"</string>
- <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Yüksək keyfiyyəti deaktiv edin"</string>
- <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Qapalı çəkilişi aktiv edin"</string>
- <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Qapalı çəkilişi deaktiv edin"</string>
-</resources>
diff --git a/v17/leanback/res/values/attrs.xml b/v17/leanback/res/values/attrs.xml
index e7da321..10ee282 100644
--- a/v17/leanback/res/values/attrs.xml
+++ b/v17/leanback/res/values/attrs.xml
@@ -49,6 +49,10 @@
</declare-styleable>
<declare-styleable name="lbBaseCardView">
+ <!-- Defines the background of card -->
+ <attr name="cardForeground" format="reference|color"/>
+ <!-- Defines the background of card -->
+ <attr name="cardBackground" format="reference|color"/>
<!-- Defines the type of the card layout -->
<attr name="cardType" format="enum">
<!-- A simple card layout with a single layout region. -->
@@ -116,7 +120,23 @@
</declare-styleable>
<declare-styleable name="lbImageCardView">
+ <!-- Deprecated. Use 'lbImageCardViewInfoAreaStyle' instead. -->
<attr name="infoAreaBackground" format="reference|color"/>
+ <!-- Use these attributes to override a ImageCardView's component style. -->
+ <attr name="lbImageCardViewImageStyle" format="reference" />
+ <attr name="lbImageCardViewTitleStyle" format="reference" />
+ <attr name="lbImageCardViewContentStyle" format="reference" />
+ <attr name="lbImageCardViewBadgeStyle" format="reference" />
+ <attr name="lbImageCardViewInfoAreaStyle" format="reference" />
+ <!-- Defines what components the ImageCardView will use. -->
+ <attr name="lbImageCardViewType">
+ <flag name="Title" value="1" />
+ <flag name="Content" value="2" />
+ <flag name="IconOnRight" value="4" />
+ <flag name="IconOnLeft" value="8" />
+ <!-- Only display the main image. -->
+ <flag name="ImageOnly" value="0" />
+ </attr>
</declare-styleable>
<declare-styleable name="lbSearchOrbView">
@@ -308,6 +328,14 @@
fragment stack pop. Default is {@link
android.support.v17.leanback.R.animator#lb_guidedstep_slide_out_to_end}. -->
<attr name="guidedStepReturnAnimation" format="reference" />
+ <!-- Theme attribute for the animation used when a guided step element is animated in
+ response to the IME appearing. Default is {@link
+ android.support.v17.leanback.R.animator#lb_guidedstep_slide_up}. -->
+ <attr name="guidedStepImeAppearingAnimation" format="reference" />
+ <!-- Theme attribute for the animation used when a guided step element is animated in
+ response to the IME disappearing. Default is {@link
+ android.support.v17.leanback.R.animator#lb_guidedstep_slide_down}. -->
+ <attr name="guidedStepImeDisappearingAnimation" format="reference" />
<!-- Theme attribute for the animation used when the guidance is animated in at activity
start. Default is {@link android.support.v17.leanback.R.animator#lb_guidance_entry}.
@@ -431,4 +459,4 @@
</declare-styleable>
-</resources>
+</resources>
\ No newline at end of file
diff --git a/v17/leanback/res/values/dimens.xml b/v17/leanback/res/values/dimens.xml
index 275612e..a05a6fc 100644
--- a/v17/leanback/res/values/dimens.xml
+++ b/v17/leanback/res/values/dimens.xml
@@ -203,6 +203,7 @@
<dimen name="lb_basic_card_info_height">52dp</dimen>
<dimen name="lb_basic_card_info_height_no_content">34dp</dimen>
<dimen name="lb_basic_card_info_padding_top">7dp</dimen>
+ <dimen name="lb_basic_card_info_padding_bottom">8dp</dimen>
<dimen name="lb_basic_card_info_padding_horizontal">11dp</dimen>
<dimen name="lb_basic_card_info_text_margin">1dp</dimen>
<dimen name="lb_basic_card_title_text_size">14sp</dimen>
@@ -226,6 +227,7 @@
<dimen name="lb_guidedstep_guidance_section_width">576dp</dimen>
<dimen name="lb_guidedstep_slide_start_distance">-200dp</dimen>
<dimen name="lb_guidedstep_slide_end_distance">200dp</dimen>
+ <dimen name="lb_guidedstep_slide_ime_distance">-100dp</dimen>
<dimen name="lb_guidance_entry_translationX">-120dp</dimen>
diff --git a/v17/leanback/res/values/ids.xml b/v17/leanback/res/values/ids.xml
index 6b67919..d4ba288 100644
--- a/v17/leanback/res/values/ids.xml
+++ b/v17/leanback/res/values/ids.xml
@@ -16,6 +16,7 @@
-->
<resources>
<item type="id" name="lb_focus_animator" />
+ <item type="id" name="lb_shadow_impl" />
<item type="id" name="lb_slide_transition_value" />
<item type="id" name="lb_control_play_pause" />
@@ -30,5 +31,4 @@
<item type="id" name="lb_control_shuffle" />
<item type="id" name="lb_control_high_quality" />
<item type="id" name="lb_control_closed_captioning" />
-
</resources>
diff --git a/v17/leanback/res/values/styles.xml b/v17/leanback/res/values/styles.xml
index 3ee2821..204c0ee 100644
--- a/v17/leanback/res/values/styles.xml
+++ b/v17/leanback/res/values/styles.xml
@@ -87,14 +87,8 @@
<style name="Widget.Leanback" parent="Widget.LeanbackBase" />
<style name="Widget.Leanback.BaseCardViewStyle">
- <item name="android:foreground">@drawable/lb_card_foreground</item>
- </style>
-
- <style name="Widget.Leanback.ImageCardViewStyle" parent="Widget.Leanback.BaseCardViewStyle">
- <item name="cardType">infoUnder</item>
- <item name="infoVisibility">activated</item>
- <item name="android:background">@color/lb_basic_card_bg_color</item>
- <item name="infoAreaBackground">@color/lb_basic_card_info_bg_color</item>
+ <item name="cardForeground">@drawable/lb_card_foreground</item>
+ <item name="cardBackground">@color/lb_basic_card_bg_color</item>
</style>
<style name="Widget.Leanback.TitleView" >
@@ -104,6 +98,77 @@
<item name="android:paddingEnd">?attr/browsePaddingEnd</item>
</style>
+ <style name="Widget.Leanback.ImageCardViewStyle" parent="Widget.Leanback.BaseCardViewStyle">
+ <item name="cardType">infoUnder</item>
+ <item name="infoVisibility">activated</item>
+ <!-- In order to keep backward compatibility we have to create an icon on right. -->
+ <item name="lbImageCardViewType">Title|Content|IconOnRight</item>
+ <item name="lbImageCardViewImageStyle">@style/Widget.Leanback.ImageCardView.ImageStyle</item>
+ <item name="lbImageCardViewTitleStyle">@style/Widget.Leanback.ImageCardView.TitleStyle</item>
+ <item name="lbImageCardViewContentStyle">@style/Widget.Leanback.ImageCardView.ContentStyle</item>
+ <item name="lbImageCardViewBadgeStyle">@style/Widget.Leanback.ImageCardView.BadgeStyle</item>
+ <item name="lbImageCardViewInfoAreaStyle">@style/Widget.Leanback.ImageCardView.InfoAreaStyle</item>
+ <!-- Deprecated. Use 'Widget.Leanback.ImageCardView.InfoAreaStyle' instead. -->
+ <item name="infoAreaBackground">@null</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView" />
+
+ <style name="Widget.Leanback.ImageCardView.ImageStyle">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:adjustViewBounds">true</item>
+ <item name="android:contentDescription">@null</item>
+ <item name="android:scaleType">centerCrop</item>
+ <item name="layout_viewType">main</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView.InfoAreaStyle">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_centerHorizontal">true</item>
+ <item name="layout_viewType">info</item>
+ <item name="android:paddingBottom">@dimen/lb_basic_card_info_padding_bottom</item>
+ <item name="android:paddingEnd">@dimen/lb_basic_card_info_padding_horizontal</item>
+ <item name="android:paddingStart">@dimen/lb_basic_card_info_padding_horizontal</item>
+ <item name="android:paddingTop">@dimen/lb_basic_card_info_padding_top</item>
+ <item name="android:background">@color/lb_basic_card_info_bg_color</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView.TitleStyle">
+ <item name="android:id">@id/title_text</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:layout_marginBottom">@dimen/lb_basic_card_info_text_margin</item>
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:textColor">@color/lb_basic_card_title_text_color</item>
+ <item name="android:textSize">@dimen/lb_basic_card_title_text_size</item>
+ <item name="android:ellipsize">end</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView.ContentStyle">
+ <item name="android:id">@id/content_text</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_alignParentStart">true</item>
+ <item name="android:layout_below">@+id/title_text</item>
+ <item name="android:layout_toStartOf">@+id/extra_badge</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:textColor">@color/lb_basic_card_content_text_color</item>
+ <item name="android:textSize">@dimen/lb_basic_card_content_text_size</item>
+ <item name="android:ellipsize">none</item>
+ </style>
+
+ <style name="Widget.Leanback.ImageCardView.BadgeStyle">
+ <item name="android:id">@id/extra_badge</item>
+ <item name="android:layout_width">@dimen/lb_basic_card_info_badge_size</item>
+ <item name="android:layout_height">@dimen/lb_basic_card_info_badge_size</item>
+ <item name="android:contentDescription">@null</item>
+ <item name="android:scaleType">fitCenter</item>
+ </style>
+
<style name="Widget.Leanback.Title" />
<style name="Widget.Leanback.Title.Text">
@@ -430,11 +495,13 @@
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:alpha">@string/lb_guidedactions_item_unselected_text_alpha</item>
- <item name="android:ellipsize">marquee</item>
+ <item name="android:ellipsize">end</item>
<item name="android:fontFamily">sans-serif-condensed</item>
<item name="android:maxLines">@integer/lb_guidedactions_item_title_min_lines</item>
<item name="android:textColor">@color/lb_guidedactions_item_unselected_text_color</item>
<item name="android:textSize">@dimen/lb_guidedactions_item_title_font_size</item>
+ <item name="android:background">@null</item>
+ <item name="android:inputType">text</item>
</style>
<!-- Style for an action's description in a GuidedActionsStylist's default item layout. -->
diff --git a/v17/leanback/res/values/themes.xml b/v17/leanback/res/values/themes.xml
index 8178c50..0ded94e 100644
--- a/v17/leanback/res/values/themes.xml
+++ b/v17/leanback/res/values/themes.xml
@@ -115,6 +115,8 @@
<item name="guidedStepExitAnimation">@animator/lb_guidedstep_slide_out_to_start</item>
<item name="guidedStepReentryAnimation">@animator/lb_guidedstep_slide_in_from_start</item>
<item name="guidedStepReturnAnimation">@animator/lb_guidedstep_slide_out_to_end</item>
+ <item name="guidedStepImeAppearingAnimation">@animator/lb_guidedstep_slide_up</item>
+ <item name="guidedStepImeDisappearingAnimation">@animator/lb_guidedstep_slide_down</item>
<item name="guidanceEntryAnimation">@animator/lb_guidance_entry</item>
<item name="guidedActionsEntryAnimation">@animator/lb_guidedactions_entry</item>
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
index 41ecac9..1edd0d1 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
@@ -19,6 +19,7 @@
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.GuidedAction;
import android.support.v17.leanback.widget.GuidedActionsStylist;
+import android.support.v17.leanback.widget.ImeKeyMonitor;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.Log;
@@ -26,9 +27,14 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
import java.util.ArrayList;
import java.util.List;
@@ -43,6 +49,9 @@
private static final String TAG = "GuidedActionAdapter";
private static final boolean DEBUG = false;
+ private static final String TAG_EDIT = "EditableAction";
+ private static final boolean DEBUG_EDIT = false;
+
/**
* Object listening for click events within a {@link GuidedActionAdapter}.
*/
@@ -66,6 +75,17 @@
}
/**
+ * Object listening for edit events within a {@link GuidedActionAdapter}.
+ */
+ public interface EditListener {
+
+ /**
+ * Called when the user enters or exits edit mode on an action.
+ */
+ public void onGuidedActionEdited(GuidedAction action, boolean entering);
+ }
+
+ /**
* View holder containing a {@link GuidedAction}.
*/
private static class ActionViewHolder extends ViewHolder {
@@ -101,6 +121,7 @@
private RecyclerView mRecyclerView;
private final ActionOnKeyListener mActionOnKeyListener;
private final ActionOnFocusListener mActionOnFocusListener;
+ private final ActionEditListener mActionEditListener;
private final List<GuidedAction> mActions;
private ClickListener mClickListener;
private GuidedActionsStylist mStylist;
@@ -126,13 +147,15 @@
* @param presenter The presenter that will manage the display of items in this adapter.
*/
public GuidedActionAdapter(List<GuidedAction> actions, ClickListener clickListener,
- FocusListener focusListener, GuidedActionsStylist presenter) {
+ FocusListener focusListener, EditListener editListener,
+ GuidedActionsStylist presenter) {
super();
mActions = new ArrayList<GuidedAction>(actions);
mClickListener = clickListener;
mStylist = presenter;
- mActionOnKeyListener = new ActionOnKeyListener(clickListener, mActions);
+ mActionOnKeyListener = new ActionOnKeyListener();
mActionOnFocusListener = new ActionOnFocusListener(focusListener);
+ mActionEditListener = new ActionEditListener(editListener);
}
/**
@@ -169,7 +192,6 @@
*/
public void setClickListener(ClickListener clickListener) {
mClickListener = clickListener;
- mActionOnKeyListener.setListener(clickListener);
}
/**
@@ -215,6 +237,16 @@
v.setOnClickListener(mOnClickListener);
v.setOnFocusChangeListener(mActionOnFocusListener);
+ final EditText edit = (EditText)vh.getTitleView();
+ if (edit != null) {
+ edit.setPrivateImeOptions("EscapeNorth=1;");
+ edit.setOnEditorActionListener(mActionEditListener);
+ ImeKeyMonitor monitor = (ImeKeyMonitor)edit;
+ if (monitor != null) {
+ monitor.setImeKeyListener(mActionEditListener);
+ }
+ }
+
return new ActionViewHolder(v, vh);
}
@@ -230,6 +262,13 @@
GuidedAction action = mActions.get(position);
avh.setAction(action);
mStylist.onBindViewHolder(avh.mStylistViewHolder, action);
+
+ final EditText edit = (EditText)avh.mStylistViewHolder.getTitleView();
+ if (edit != null) {
+ int next = getNextEditableActionIndex(action);
+ int flag = (next == -1) ? EditorInfo.IME_ACTION_DONE : EditorInfo.IME_ACTION_NEXT;
+ edit.setImeOptions(flag);
+ }
}
/**
@@ -240,6 +279,25 @@
return mActions.size();
}
+ private int getNextEditableActionIndex(GuidedAction action) {
+ int i, size = mActions.size();
+ for (i = 0; i < size; i++) {
+ GuidedAction a = mActions.get(i);
+ if (mActions.get(i) == action) {
+ i++;
+ break;
+ }
+ }
+ for (; i < size; i++) {
+ GuidedAction a = mActions.get(i);
+ if (a.isEditable()) {
+ break;
+ }
+ }
+ int result = (i == size) ? -1 : i;
+ return result;
+ }
+
private class ActionOnFocusListener implements View.OnFocusChangeListener {
private FocusListener mFocusListener;
@@ -287,19 +345,7 @@
private class ActionOnKeyListener implements View.OnKeyListener {
- private final List<GuidedAction> mActions;
private boolean mKeyPressed = false;
- private ClickListener mClickListener;
-
- public ActionOnKeyListener(ClickListener listener,
- List<GuidedAction> actions) {
- mClickListener = listener;
- mActions = actions;
- }
-
- public void setListener(ClickListener listener) {
- mClickListener = listener;
- }
private void playSound(View v, int soundEffect) {
if (v.isSoundEffectsEnabled()) {
@@ -360,10 +406,14 @@
Log.d(TAG, "Enter Key up");
}
- mStylist.onAnimateItemPressed(avh.mStylistViewHolder,
- mKeyPressed);
- handleCheckedActions(avh, action);
- mClickListener.onGuidedActionClicked(action);
+ mStylist.onAnimateItemPressed(avh.mStylistViewHolder, mKeyPressed);
+ if (action.isEditable()) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme click");
+ mActionEditListener.openIme(avh, true);
+ } else {
+ handleCheckedActions(avh, action);
+ mClickListener.onGuidedActionClicked(action);
+ }
handled = true;
}
break;
@@ -403,4 +453,97 @@
}
}
}
+
+ private class ActionEditListener implements OnEditorActionListener,
+ ImeKeyMonitor.ImeKeyListener {
+
+ private EditListener mEditListener;
+
+ public ActionEditListener(EditListener listener) {
+ mEditListener = listener;
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME action: " + actionId);
+ boolean handled = false;
+ if (actionId == EditorInfo.IME_ACTION_NEXT ||
+ actionId == EditorInfo.IME_ACTION_DONE) {
+
+ ActionViewHolder avh = findSubChildViewHolder(v);
+ GuidedAction action = avh.getAction();
+ action.setTitle(v.getText());
+ mClickListener.onGuidedActionClicked(action);
+ int next = getNextEditableActionIndex(action);
+ if (next != -1) {
+ ViewHolder vh = mRecyclerView.findViewHolderForPosition(next);
+ if (vh != null) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme next/done");
+ handled = true;
+ openIme((ActionViewHolder)vh, false);
+ }
+ }
+ if (!handled) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme no next");
+ handled = true;
+ closeIme(avh);
+ }
+ } else if (actionId == EditorInfo.IME_ACTION_NONE) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme escape north");
+ // Escape north handling: stay on current item, but close editor
+ handled = true;
+ ActionViewHolder avh = findSubChildViewHolder(v);
+ closeIme(avh);
+ }
+ return handled;
+ }
+
+ @Override
+ public boolean onKeyPreIme(EditText editText, int keyCode, KeyEvent event) {
+ if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME key: " + keyCode);
+ if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
+ ActionViewHolder avh = findSubChildViewHolder(editText);
+ GuidedAction action = avh.getAction();
+ action.setTitle(editText.getText());
+ editText.clearFocus();
+ mEditListener.onGuidedActionEdited(action, false);
+ }
+ return false;
+ }
+
+ public void openIme(ActionViewHolder avh, boolean notify) {
+ View v = avh.mStylistViewHolder.getTitleView();
+ InputMethodManager mgr = (InputMethodManager)
+ v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ v.requestFocus();
+ mgr.showSoftInput(v, 0);
+ if (notify) {
+ mEditListener.onGuidedActionEdited(avh.getAction(), true);
+ }
+ }
+
+ public void closeIme(ActionViewHolder avh) {
+ View v = avh.mStylistViewHolder.getTitleView();
+ InputMethodManager mgr = (InputMethodManager)
+ v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ v.clearFocus();
+ mgr.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ mEditListener.onGuidedActionEdited(avh.getAction(), false);
+ }
+
+ private ActionViewHolder findSubChildViewHolder(View v) {
+ // Needed because RecyclerView.getChildViewHolder does not traverse the hierarchy
+ ActionViewHolder result = null;
+ ViewParent parent = v.getParent();
+ while (parent != mRecyclerView && parent != null && v != null) {
+ v = (View)parent;
+ parent = parent.getParent();
+ }
+ if (parent != null && v != null) {
+ result = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
+ }
+ return result;
+ }
+ }
+
}
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 b1e87a1..170aa63 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
@@ -211,6 +211,12 @@
}
/**
+ * Callback invoked when an action's title has been edited.
+ */
+ public void onGuidedActionEdited(GuidedAction action) {
+ }
+
+ /**
* Adds the specified GuidedStepFragment to the fragment stack, replacing any existing
* GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom animations.
* <p>
@@ -354,7 +360,17 @@
View actionsView = mActionsStylist.onCreateView(inflater, actionContainer);
actionContainer.addView(actionsView);
- mAdapter = new GuidedActionAdapter(mActions, this, this, mActionsStylist);
+ GuidedActionAdapter.EditListener editListener = new GuidedActionAdapter.EditListener() {
+ @Override
+ public void onGuidedActionEdited(GuidedAction action, boolean entering) {
+ runImeAnimations(entering);
+ if (!entering) {
+ GuidedStepFragment.this.onGuidedActionEdited(action);
+ }
+ }
+ };
+
+ mAdapter = new GuidedActionAdapter(mActions, this, this, editListener, mActionsStylist);
mListView = mActionsStylist.getActionsGridView();
mListView.setAdapter(mAdapter);
@@ -522,6 +538,20 @@
});
}
+ private void runImeAnimations(boolean entering) {
+ ArrayList<Animator> animators = new ArrayList<Animator>();
+ if (entering) {
+ mGuidanceStylist.onImeAppearing(animators);
+ mActionsStylist.onImeAppearing(animators);
+ } else {
+ mGuidanceStylist.onImeDisappearing(animators);
+ mActionsStylist.onImeDisappearing(animators);
+ }
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(animators);
+ set.start();
+ }
+
private Animator createDummyAnimator(final View v, ArrayList<Animator> animators) {
final AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(animators);
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java b/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
index 614f12b..085aac3 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/BaseCardView.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.support.v17.leanback.R;
import android.util.AttributeSet;
import android.util.Log;
@@ -154,6 +155,14 @@
try {
mCardType = a.getInteger(R.styleable.lbBaseCardView_cardType, CARD_TYPE_MAIN_ONLY);
+ Drawable cardForeground = a.getDrawable(R.styleable.lbBaseCardView_cardForeground);
+ if (cardForeground != null) {
+ setForeground(cardForeground);
+ }
+ Drawable cardBackground = a.getDrawable(R.styleable.lbBaseCardView_cardBackground);
+ if (cardBackground != null) {
+ setBackground(cardBackground);
+ }
mInfoVisibility = a.getInteger(R.styleable.lbBaseCardView_infoVisibility,
CARD_REGION_VISIBLE_ACTIVATED);
mExtraVisibility = a.getInteger(R.styleable.lbBaseCardView_extraVisibility,
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
index 48829eb..4f32ff2 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FocusHighlightHelper.java
@@ -85,7 +85,7 @@
mWrapper = null;
}
mAnimator.setTimeListener(this);
- if (mWrapper != null && useDimmer) {
+ if (useDimmer) {
mDimmer = ColorOverlayDimmer.createDefault(view.getContext());
} else {
mDimmer = null;
@@ -99,9 +99,16 @@
mView.setScaleY(scale);
if (mWrapper != null) {
mWrapper.setShadowFocusLevel(level);
- if (mDimmer != null) {
- mDimmer.setActiveLevel(level);
- mWrapper.setOverlayColor(mDimmer.getPaint().getColor());
+ } else {
+ ShadowOverlayHelper.setShadowFocusLevel(mView, level);
+ }
+ if (mDimmer != null) {
+ mDimmer.setActiveLevel(level);
+ int color = mDimmer.getPaint().getColor();
+ if (mWrapper != null) {
+ mWrapper.setOverlayColor(color);
+ } else {
+ ShadowOverlayHelper.setForegroundColor(mView, color);
}
}
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java
new file mode 100644
index 0000000..c9bed58
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ForegroundHelper.java
@@ -0,0 +1,78 @@
+package android.support.v17.leanback.widget;
+
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewGroup;
+
+final class ForegroundHelper {
+
+ final static ForegroundHelper sInstance = new ForegroundHelper();
+ ForegroundHelperVersionImpl mImpl;
+
+ /**
+ * Interface implemented by classes that support Shadow.
+ */
+ static interface ForegroundHelperVersionImpl {
+
+ public void setForeground(View view, Drawable drawable);
+
+ public Drawable getForeground(View view);
+ }
+
+ /**
+ * Implementation used on api 23 (and above).
+ */
+ private static final class ForegroundHelperApi23Impl implements ForegroundHelperVersionImpl {
+ @Override
+ public void setForeground(View view, Drawable drawable) {
+ ForegroundHelperApi23.setForeground(view, drawable);
+ }
+
+ @Override
+ public Drawable getForeground(View view) {
+ return ForegroundHelperApi23.getForeground(view);
+ }
+ }
+
+ /**
+ * Stub implementation
+ */
+ private static final class ForegroundHelperStubImpl implements ForegroundHelperVersionImpl {
+ @Override
+ public void setForeground(View view, Drawable drawable) {
+ }
+
+ @Override
+ public Drawable getForeground(View view) {
+ return null;
+ }
+ }
+
+ private ForegroundHelper() {
+ if (supportsForeground()) {
+ mImpl = new ForegroundHelperApi23Impl();
+ } else {
+ mImpl = new ForegroundHelperStubImpl();
+ }
+ }
+
+ public static ForegroundHelper getInstance() {
+ return sInstance;
+ }
+
+ /**
+ * Returns true if view.setForeground() is supported.
+ */
+ public static boolean supportsForeground() {
+ return Build.VERSION.SDK_INT >= 23;
+ }
+
+ public Drawable getForeground(View view) {
+ return mImpl.getForeground(view);
+ }
+
+ public void setForeground(View view, Drawable drawable) {
+ mImpl.setForeground(view, drawable);
+ }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java b/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
index 8bd0007..b1f6169 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/FragmentAnimationProvider.java
@@ -69,4 +69,16 @@
*/
public abstract void onFragmentReturn(@NonNull List<Animator> animators);
+ /**
+ * Animates the fragment in response to the IME appearing.
+ * @param animators A list of animations to which this provider's animations should be added.
+ */
+ public abstract void onImeAppearing(@NonNull List<Animator> animators);
+
+ /**
+ * Animates the fragment in response to the IME disappearing.
+ * @param animators A list of animations to which this provider's animations should be added.
+ */
+ public abstract void onImeDisappearing(@NonNull List<Animator> animators);
+
}
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 8d12510..b95c114 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
@@ -59,6 +59,8 @@
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepExitAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReentryAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReturnAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceContainerStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceTitleStyle
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidanceDescriptionStyle
@@ -280,6 +282,28 @@
addAnimator(animators, mIconView, R.attr.guidedStepReturnAnimation);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onImeAppearing(@NonNull List<Animator> animators) {
+ addAnimator(animators, mTitleView, R.attr.guidedStepImeAppearingAnimation);
+ addAnimator(animators, mBreadcrumbView, R.attr.guidedStepImeAppearingAnimation);
+ addAnimator(animators, mDescriptionView, R.attr.guidedStepImeAppearingAnimation);
+ addAnimator(animators, mIconView, R.attr.guidedStepImeAppearingAnimation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onImeDisappearing(@NonNull List<Animator> animators) {
+ addAnimator(animators, mTitleView, R.attr.guidedStepImeDisappearingAnimation);
+ addAnimator(animators, mBreadcrumbView, R.attr.guidedStepImeDisappearingAnimation);
+ addAnimator(animators, mDescriptionView, R.attr.guidedStepImeDisappearingAnimation);
+ addAnimator(animators, mIconView, R.attr.guidedStepImeDisappearingAnimation);
+ }
+
private void addAnimator(List<Animator> animators, View v, int attrId) {
if (v != null) {
Context ctx = v.getContext();
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 e4db2eb..30edc2f 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
@@ -50,6 +50,7 @@
private boolean mMultilineDescription;
private boolean mHasNext;
private boolean mInfoOnly;
+ private boolean mEditable = false;
private int mCheckSetId = NO_CHECK_SET;
private boolean mEnabled = true;
private Intent mIntent;
@@ -68,6 +69,7 @@
// Subclass values
action.mIntent = mIntent;
+ action.mEditable = mEditable;
action.mChecked = mChecked;
action.mCheckSetId = mCheckSetId;
action.mMultilineDescription = mMultilineDescription;
@@ -138,11 +140,27 @@
}
/**
+ * Indicates whether this action is editable. Note: Editable actions cannot also be
+ * checked, or belong to a check set.
+ * @param editable Whether this action is editable.
+ */
+ public Builder editable(boolean editable) {
+ mEditable = editable;
+ if (mChecked || mCheckSetId != NO_CHECK_SET) {
+ throw new IllegalArgumentException("Editable actions cannot also be checked");
+ }
+ return this;
+ }
+
+ /**
* Indicates whether this action is initially checked.
* @param checked Whether this action is checked.
*/
public Builder checked(boolean checked) {
mChecked = checked;
+ if (mEditable) {
+ throw new IllegalArgumentException("Editable actions cannot also be checked");
+ }
return this;
}
@@ -154,6 +172,9 @@
*/
public Builder checkSetId(int checkSetId) {
mCheckSetId = checkSetId;
+ if (mEditable) {
+ throw new IllegalArgumentException("Editable actions cannot also be in check sets");
+ }
return this;
}
@@ -195,9 +216,10 @@
}
}
- private boolean mChecked;
+ private boolean mEditable;
private boolean mMultilineDescription;
private boolean mHasNext;
+ private boolean mChecked;
private boolean mInfoOnly;
private int mCheckSetId;
private boolean mEnabled;
@@ -217,6 +239,14 @@
}
/**
+ * Returns the title of this action.
+ * @return The title set when this action was built.
+ */
+ public void setTitle(CharSequence title) {
+ setLabel1(title);
+ }
+
+ /**
* Returns the description of this action.
* @return The description set when this action was built.
*/
@@ -233,6 +263,14 @@
}
/**
+ * Returns whether this action is editable.
+ * @return true if the action is editable, false otherwise.
+ */
+ public boolean isEditable() {
+ return mEditable;
+ }
+
+ /**
* Returns whether this action is checked.
* @return true if the action is currently checked, false otherwise.
*/
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 15943b4..525e2fc 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
@@ -81,7 +81,17 @@
* </ul><p>
* These view IDs are allowed to be missing, in which case the corresponding views in {@link
* GuidedActionsStylist.ViewHolder} will be null.
+ * <p>
+ * In order to support editable actions, the view associated with guidedactions_item_title should
+ * be a subclass of {@link android.widget.EditText}, and should satisfy the {@link
+ * ImeKeyMonitor} interface.
*
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepEntryAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepExitAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReentryAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepReturnAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeAppearingAnimation
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedStepImeDisappearingAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsEntryAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorShowAnimation
* @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionsSelectorHideAnimation
@@ -483,6 +493,24 @@
animators.add(createAnimator(mSelectorView, R.attr.guidedStepReturnAnimation));
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onImeAppearing(@NonNull List<Animator> animators) {
+ animators.add(createAnimator(mActionsGridView, R.attr.guidedStepImeAppearingAnimation));
+ animators.add(createAnimator(mSelectorView, R.attr.guidedStepImeAppearingAnimation));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onImeDisappearing(@NonNull List<Animator> animators) {
+ animators.add(createAnimator(mActionsGridView, R.attr.guidedStepImeDisappearingAnimation));
+ animators.add(createAnimator(mSelectorView, R.attr.guidedStepImeDisappearingAnimation));
+ }
+
/*
* ==========================================
* Private methods
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
index 2c1c7e0..08eb617 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
@@ -18,60 +18,288 @@
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.v17.leanback.R;
-import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
+import android.widget.RelativeLayout;
import android.widget.TextView;
/**
- * A subclass of {@link BaseCardView} with an {@link ImageView} as its main region.
+ * A subclass of {@link BaseCardView} with an {@link ImageView} as its main
+ * region. The {@link ImageCardView} is highly customizable and can be used for
+ * various use-cases by adjusting the ImageViewCard's type to any combination of
+ * Title, Content, Badge or ImageOnly.
+ * <p>
+ * <h3>Styling</h3> There are three different ways to style the ImageCardView.
+ * <br>
+ * No matter what way you use, all your styles applied to an ImageCardView have
+ * to extend the style {@link R.style#Widget_Leanback_ImageCardViewStyle}.
+ * <p>
+ * <u>Example:</u><br>
+ *
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+ <item name="cardBackground">#F0F</item>
+ <item name="lbImageCardViewType">Title|Content</item>
+ <item name="lbImageCardViewInfoAreaStyle">@style/ImageCardViewColoredInfoArea</item>
+ <item name="lbImageCardViewTitleStyle">@style/ImageCardViewColoredTitle</item>
+ </style>}
+ * </pre>
+ * <p>
+ * The first possibility is to set a custom Style in the Leanback Theme's
+ * attribute <code>imageCardViewStyle</code>. The style set here, is the default
+ * style for all ImageCardViews. The other two possibilities allow you to style
+ * a particular ImageCardView. This is usefull if you want to create multiple
+ * types of cards. E.g. you might want to display a card with only a title and
+ * another one with title and content. Thus you need to define two different
+ * <code>ImageCardViewStyles</code> and apply them to the ImageCardViews. You
+ * can do this by either using a the {@link #ImageCardView(Context, int)}
+ * constructor and passing a style as second argument or by setting the style in
+ * a layout.
+ * <p>
+ * <u>Example (using constructor):</u><br>
+ *
+ * <pre>
+ * {@code
+ * new ImageCardView(context, R.style.CustomImageCardViewStyle);
+ * }
+ * </pre>
+ *
+ * <u>Example (using style attribute in a layout):</u><br>
+ *
+ * <pre>
+ * {@code <android.support.v17.leanback.widget.ImageCardView
+ android:id="@+id/imageCardView"
+ style="@style/CustomImageCardViewStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </android.support.v17.leanback.widget.ImageCardView>}
+ * </pre>
+ * <p>
+ * You can style all ImageCardView's components such as the title, content,
+ * badge, infoArea and the image itself by extending the corresponding style and
+ * overriding the specific attribute in your custom
+ * <code>ImageCardViewStyle</code>.
+ *
+ * <h3>Components</h3> The ImageCardView contains three components which can be
+ * combined in any combination:
+ * <ul>
+ * <li>Title: The card's title</li>
+ * <li>Content: A short description</li>
+ * <li>Badge: An icon which can be displayed on the right or left side of the
+ * card.</li>
+ * </ul>
+ * In order to choose the components you want to use in your ImageCardView, you
+ * have to specify them in the <code>lbImageCardViewType</code> attribute of
+ * your custom <code>ImageCardViewStyle</code>. You can combine the following
+ * values: <code>Title, Content, IconOnRight, IconOnLeft, ImageOnly</code>.
+ * <p>
+ * <u>Examples:</u><br>
+ *
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+ ...
+ <item name="lbImageCardViewType">Title|Content|IconOnLeft</item>
+ ...
+ </style>}
+ * </pre>
+ *
+ * <pre>
+ * {@code <style name="CustomImageCardViewStyle" parent="Widget.Leanback.ImageCardViewStyle">
+ ...
+ <item name="lbImageCardViewType">ImageOnly</item>
+ ...
+ </style>}
+ * </pre>
+ *
+ * @attr ref android.support.v17.leanback.R.styleable#LeanbackTheme_imageCardViewStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewType
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewTitleStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewContentStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewBadgeStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewImageStyle
+ * @attr ref android.support.v17.leanback.R.styleable#lbImageCardView_lbImageCardViewInfoAreaStyle
*/
public class ImageCardView extends BaseCardView {
+ public static final int CARD_TYPE_FLAG_IMAGE_ONLY = 0;
+ public static final int CARD_TYPE_FLAG_TITLE = 1;
+ public static final int CARD_TYPE_FLAG_CONTENT = 2;
+ public static final int CARD_TYPE_FLAG_ICON_RIGHT = 4;
+ public static final int CARD_TYPE_FLAG_ICON_LEFT = 8;
+
private ImageView mImageView;
- private View mInfoArea;
+ private ViewGroup mInfoArea;
private TextView mTitleView;
private TextView mContentView;
private ImageView mBadgeImage;
private boolean mAttachedToWindow;
+ /**
+ * Create an ImageCardView using a given style for customization.
+ *
+ * @param context
+ * The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ * @param styleResId
+ * The resourceId of the style you want to apply to the
+ * ImageCardView. The style has to extend
+ * {@link R.style#Widget_Leanback_ImageCardViewStyle}.
+ */
+ public ImageCardView(Context context, int styleResId) {
+ super(new ContextThemeWrapper(context, styleResId), null, 0);
+ buildImageCardView(styleResId);
+ }
+
+ /**
+ * @see #View(Context, AttributeSet, int)
+ */
+ public ImageCardView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(getStyledContext(context, attrs, defStyleAttr), attrs, defStyleAttr);
+ buildImageCardView(getImageCardViewStyle(context, attrs, defStyleAttr));
+ }
+
+ private void buildImageCardView(int styleResId) {
+ // Make sure the ImageCardView is focusable.
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ inflater.inflate(R.layout.lb_image_card_view, this);
+ TypedArray cardAttrs = getContext().obtainStyledAttributes(styleResId, R.styleable.lbImageCardView);
+ int cardType = cardAttrs.getInt(R.styleable.lbImageCardView_lbImageCardViewType, CARD_TYPE_FLAG_IMAGE_ONLY);
+ boolean hasImageOnly = cardType == CARD_TYPE_FLAG_IMAGE_ONLY;
+ boolean hasTitle = (cardType & CARD_TYPE_FLAG_TITLE) == CARD_TYPE_FLAG_TITLE;
+ boolean hasContent = (cardType & CARD_TYPE_FLAG_CONTENT) == CARD_TYPE_FLAG_CONTENT;
+ boolean hasIconRight = (cardType & CARD_TYPE_FLAG_ICON_RIGHT) == CARD_TYPE_FLAG_ICON_RIGHT;
+ boolean hasIconLeft = !hasIconRight && (cardType & CARD_TYPE_FLAG_ICON_LEFT) == CARD_TYPE_FLAG_ICON_LEFT;
+
+ mImageView = (ImageView) findViewById(R.id.main_image);
+ if (mImageView.getDrawable() == null) {
+ mImageView.setVisibility(View.INVISIBLE);
+ }
+
+ mInfoArea = (ViewGroup) findViewById(R.id.info_field);
+ if (hasImageOnly) {
+ removeView(mInfoArea);
+ cardAttrs.recycle();
+ return;
+ }
+ // Create children
+ if (hasTitle) {
+ mTitleView = (TextView) inflater.inflate(R.layout.lb_image_card_view_themed_title, mInfoArea, false);
+ mInfoArea.addView(mTitleView);
+ }
+
+ if (hasContent) {
+ mContentView = (TextView) inflater.inflate(R.layout.lb_image_card_view_themed_content, mInfoArea, false);
+ mInfoArea.addView(mContentView);
+ }
+
+ if (hasIconRight || hasIconLeft) {
+ int layoutId = R.layout.lb_image_card_view_themed_badge_right;
+ if (hasIconLeft) {
+ layoutId = R.layout.lb_image_card_view_themed_badge_left;
+ }
+ mBadgeImage = (ImageView) inflater.inflate(layoutId, mInfoArea, false);
+ mInfoArea.addView(mBadgeImage);
+ }
+
+ // Set up LayoutParams for children
+ if (hasTitle && !hasContent && mBadgeImage != null) {
+ RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mTitleView
+ .getLayoutParams();
+ // Adjust title TextView if there is an icon but no content
+ if (hasIconLeft) {
+ relativeLayoutParams.addRule(RelativeLayout.END_OF, mBadgeImage.getId());
+ } else {
+ relativeLayoutParams.addRule(RelativeLayout.START_OF, mBadgeImage.getId());
+ }
+ mTitleView.setLayoutParams(relativeLayoutParams);
+ }
+
+ // Set up LayoutParams for children
+ if (hasContent) {
+ RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mContentView
+ .getLayoutParams();
+ if (!hasTitle) {
+ relativeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ }
+ // Adjust content TextView if icon is on the left
+ if (hasIconLeft) {
+ relativeLayoutParams.removeRule(RelativeLayout.START_OF);
+ relativeLayoutParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
+ relativeLayoutParams.addRule(RelativeLayout.END_OF, mBadgeImage.getId());
+ }
+ mContentView.setLayoutParams(relativeLayoutParams);
+ }
+
+ if (mBadgeImage != null) {
+ RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) mBadgeImage
+ .getLayoutParams();
+ if (hasContent) {
+ relativeLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mContentView.getId());
+ } else if (hasTitle) {
+ relativeLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mTitleView.getId());
+ }
+ mBadgeImage.setLayoutParams(relativeLayoutParams);
+ }
+
+ // Backward compatibility: Newly created ImageCardViews should change
+ // the InfoArea's background color in XML using the corresponding style.
+ // However, since older implementations might make use of the
+ // 'infoAreaBackground' attribute, we have to make sure to support it.
+ // If the user has set a specific value here, it will differ from null.
+ // In this case, we do want to override the value set in the style.
+ Drawable background = cardAttrs.getDrawable(R.styleable.lbImageCardView_infoAreaBackground);
+ if (null != background) {
+ setInfoAreaBackground(background);
+ }
+ // Backward compatibility: There has to be an icon in the default
+ // version. If there is one, we have to set it's visibility to 'GONE'.
+ // Disabling 'adjustIconVisibility' allows the user to set the icon's
+ // visibility state in XML rather than code.
+ if (mBadgeImage != null && mBadgeImage.getDrawable() == null) {
+ mBadgeImage.setVisibility(View.GONE);
+ }
+ cardAttrs.recycle();
+ }
+
+ private static Context getStyledContext(Context context, AttributeSet attrs, int defStyleAttr) {
+ int style = getImageCardViewStyle(context, attrs, defStyleAttr);
+ return new ContextThemeWrapper(context, style);
+ }
+
+ private static int getImageCardViewStyle(Context context, AttributeSet attrs, int defStyleAttr) {
+ // Read style attribute defined in XML layout.
+ int style = null == attrs ? 0 : attrs.getStyleAttribute();
+ if (0 == style) {
+ // Not found? Read global ImageCardView style from Theme attribute.
+ TypedArray styledAttrs = context.obtainStyledAttributes(R.styleable.LeanbackTheme);
+ style = styledAttrs.getResourceId(R.styleable.LeanbackTheme_imageCardViewStyle, 0);
+ styledAttrs.recycle();
+ }
+ return style;
+ }
+
+ /**
+ * @see #View(Context)
+ */
public ImageCardView(Context context) {
this(context, null);
}
+ /**
+ * @see #View(Context, AttributeSet)
+ */
public ImageCardView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.imageCardViewStyle);
}
- public ImageCardView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- LayoutInflater inflater = LayoutInflater.from(context);
- View v = inflater.inflate(R.layout.lb_image_card_view, this);
-
- mImageView = (ImageView) v.findViewById(R.id.main_image);
- mImageView.setVisibility(View.INVISIBLE);
- mInfoArea = v.findViewById(R.id.info_field);
- mTitleView = (TextView) v.findViewById(R.id.title_text);
- mContentView = (TextView) v.findViewById(R.id.content_text);
- mBadgeImage = (ImageView) v.findViewById(R.id.extra_badge);
-
- if (mInfoArea != null) {
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.lbImageCardView,
- defStyle, 0);
- try {
- setInfoAreaBackground(
- a.getDrawable(R.styleable.lbImageCardView_infoAreaBackground));
- } finally {
- a.recycle();
- }
- }
- }
-
/**
* Returns the main image view.
*/
@@ -170,7 +398,7 @@
/**
* Sets the info area background color.
- */
+ */
public void setInfoAreaBackgroundColor(@ColorInt int color) {
if (mInfoArea != null) {
mInfoArea.setBackgroundColor(color);
@@ -184,7 +412,6 @@
if (mTitleView == null) {
return;
}
-
mTitleView.setText(text);
}
@@ -206,7 +433,6 @@
if (mContentView == null) {
return;
}
-
mContentView.setText(text);
}
@@ -229,7 +455,7 @@
return;
}
mBadgeImage.setImageDrawable(drawable);
- if (drawable != null && mContentView!= null && mContentView.getVisibility() != GONE) {
+ if (drawable != null) {
mBadgeImage.setVisibility(View.VISIBLE);
} else {
mBadgeImage.setVisibility(View.GONE);
@@ -250,8 +476,8 @@
private void fadeIn() {
mImageView.setAlpha(0f);
if (mAttachedToWindow) {
- mImageView.animate().alpha(1f).setDuration(mImageView.getResources().getInteger(
- android.R.integer.config_shortAnimTime));
+ mImageView.animate().alpha(1f)
+ .setDuration(mImageView.getResources().getInteger(android.R.integer.config_shortAnimTime));
}
}
@@ -276,4 +502,5 @@
mImageView.setAlpha(1f);
super.onDetachedFromWindow();
}
+
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java b/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java
new file mode 100644
index 0000000..4691ad2
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ImeKeyMonitor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.widget;
+
+import android.widget.EditText;
+import android.view.KeyEvent;
+
+/**
+ * Interface for an EditText subclass that can delegate calls to onKeyPreIme up to a registered
+ * listener.
+ * <p>
+ * Used in editable actions within {@link android.support.v17.leanback.app.GuidedStepFragment} to
+ * allow for custom back key handling. Specifically, this is used to implement the behavior that
+ * dismissing the IME also clears edit text focus. Clients who need to supply custom layouts for
+ * {@link GuidedActionsStylist} with their own EditText classes should satisfy this interface in
+ * order to inherit this behavior.
+ */
+public interface ImeKeyMonitor {
+
+ /**
+ * Listener interface for key events intercepted pre-IME by edit text objects.
+ */
+ public interface ImeKeyListener {
+ /**
+ * Callback invoked from EditText's onKeyPreIme method override. Returning true tells the
+ * caller that the key event is handled and should not be propagated.
+ */
+ public abstract boolean onKeyPreIme(EditText editText, int keyCode, KeyEvent event);
+ }
+
+ /**
+ * Set the listener for this edit text object. The listener's onKeyPreIme method will be
+ * invoked from the host edit text's onKeyPreIme method.
+ */
+ public void setImeKeyListener(ImeKeyListener listener);
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/LeanbackEditText.java b/v17/leanback/src/android/support/v17/leanback/widget/LeanbackEditText.java
new file mode 100644
index 0000000..97c4477
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/LeanbackEditText.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.support.v17.leanback.widget.ImeKeyMonitor.ImeKeyListener;
+import android.util.AttributeSet;
+import android.widget.EditText;
+import android.view.KeyEvent;
+
+/**
+ * A custom EditText that satisfies the IME key monitoring requirements of GuidedStepFragment.
+ *
+ * @hide
+ */
+public class LeanbackEditText extends EditText implements ImeKeyMonitor {
+
+ private ImeKeyListener mKeyListener;
+
+ public LeanbackEditText(Context ctx) {
+ this(ctx, null);
+ }
+
+ public LeanbackEditText(Context ctx, AttributeSet attrs) {
+ this(ctx, attrs, android.R.attr.editTextStyle);
+ }
+
+ public LeanbackEditText(Context ctx, AttributeSet attrs, int defStyleAttr) {
+ super(ctx, attrs, defStyleAttr);
+ }
+
+ @Override
+ public void setImeKeyListener(ImeKeyListener listener) {
+ mKeyListener = listener;
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ boolean result = false;
+ if (mKeyListener != null) {
+ result = mKeyListener.onKeyPreIme(this, keyCode, event);
+ }
+ if (!result) {
+ result = super.onKeyPreIme(keyCode, event);
+ }
+ return result;
+ }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
index 9e588eb..1c5c1f9 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ListRowPresenter.java
@@ -15,6 +15,7 @@
import android.content.Context;
import android.content.res.TypedArray;
+import android.os.Build;
import android.support.v17.leanback.R;
import android.support.v17.leanback.system.Settings;
import android.util.Log;
@@ -96,6 +97,13 @@
}
@Override
+ protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
+ if (mShadowOverlayHelper != null) {
+ mShadowOverlayHelper.onViewCreated(viewHolder.itemView);
+ }
+ }
+
+ @Override
public void onBind(final ItemBridgeAdapter.ViewHolder viewHolder) {
// Only when having an OnItemClickListner, we will attach the OnClickListener.
if (mRowViewHolder.getOnItemViewClickedListener() != null) {
@@ -122,9 +130,13 @@
@Override
public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
- if (needsDefaultListSelectEffect()) {
+ if (mShadowOverlayHelper != null && mShadowOverlayHelper.needsOverlay()) {
int dimmedColor = mRowViewHolder.mColorDimmer.getPaint().getColor();
- ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor);
+ if (mShadowOverlayHelper.getWrapper() != null) {
+ ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor);
+ } else {
+ ShadowOverlayHelper.setForegroundColor(viewHolder.itemView, dimmedColor);
+ }
}
mRowViewHolder.syncActivatedStatus(viewHolder.itemView);
}
@@ -145,6 +157,7 @@
private int mBrowseRowsFadingEdgeLength = -1;
private boolean mRoundedCornersEnabled = true;
private HashMap<Presenter, Integer> mRecycledPoolSize = new HashMap<Presenter, Integer>();
+ private ShadowOverlayHelper mShadowOverlayHelper;
private static int sSelectedRowTopPadding;
private static int sExpandedSelectedRowTopPadding;
@@ -253,44 +266,24 @@
return mUseFocusDimmer;
}
- private ItemBridgeAdapter.Wrapper mCardWrapper = new ItemBridgeAdapter.Wrapper() {
- @Override
- public View createWrapper(View root) {
- ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
- wrapper.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- if (isUsingZOrder(root.getContext())) {
- wrapper.useDynamicShadow();
- } else {
- wrapper.useStaticShadow();
- }
- wrapper.initialize(needsDefaultShadow(),
- needsDefaultListSelectEffect(),
- areChildRoundedCornersEnabled());
- return wrapper;
- }
- @Override
- public void wrap(View wrapper, View wrapped) {
- ((ShadowOverlayContainer) wrapper).wrap(wrapped);
- }
- };
-
@Override
protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) {
super.initializeRowViewHolder(holder);
final ViewHolder rowViewHolder = (ViewHolder) holder;
+ Context context = holder.view.getContext();
+ if (mShadowOverlayHelper == null) {
+ mShadowOverlayHelper = new ShadowOverlayHelper(context, needsDefaultListSelectEffect(),
+ needsDefaultShadow(), areChildRoundedCornersEnabled(), isUsingZOrder(context));
+ }
rowViewHolder.mItemBridgeAdapter = new ListRowPresenterItemBridgeAdapter(rowViewHolder);
- if (needsDefaultListSelectEffect() || needsDefaultShadow()
- || areChildRoundedCornersEnabled()) {
- rowViewHolder.mItemBridgeAdapter.setWrapper(mCardWrapper);
- }
- if (needsDefaultShadow()) {
- ShadowOverlayContainer.prepareParentForShadow(rowViewHolder.mGridView);
- }
+ // set wrapper if needed
+ rowViewHolder.mItemBridgeAdapter.setWrapper(mShadowOverlayHelper.getWrapper());
+ mShadowOverlayHelper.prepareParentForShadow(rowViewHolder.mGridView);
+
FocusHighlightHelper.setupBrowseItemFocusHighlight(rowViewHolder.mItemBridgeAdapter,
mFocusZoomFactor, mUseFocusDimmer);
- rowViewHolder.mGridView.setFocusDrawingOrderEnabled(
- !isUsingZOrder(rowViewHolder.getGridView().getContext()));
+ rowViewHolder.mGridView.setFocusDrawingOrderEnabled(mShadowOverlayHelper.getShadowType()
+ == ShadowOverlayHelper.SHADOW_STATIC);
rowViewHolder.mGridView.setOnChildSelectedListener(
new OnChildSelectedListener() {
@Override
@@ -545,7 +538,7 @@
* Subclass may return false to disable.
*/
public boolean isUsingDefaultShadow() {
- return ShadowOverlayContainer.supportsShadow();
+ return ShadowOverlayHelper.supportsShadow();
}
/**
@@ -554,8 +547,7 @@
* and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
*/
public boolean isUsingZOrder(Context context) {
- return ShadowOverlayContainer.supportsDynamicShadow() &&
- !Settings.getInstance(context).preferStaticShadows();
+ return !Settings.getInstance(context).preferStaticShadows();
}
/**
@@ -615,12 +607,18 @@
@Override
protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) {
super.onSelectLevelChanged(holder);
- if (needsDefaultListSelectEffect()) {
+ if (mShadowOverlayHelper != null && mShadowOverlayHelper.needsOverlay()) {
ViewHolder vh = (ViewHolder) holder;
int dimmedColor = vh.mColorDimmer.getPaint().getColor();
- for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
- ShadowOverlayContainer wrapper = (ShadowOverlayContainer) vh.mGridView.getChildAt(i);
- wrapper.setOverlayColor(dimmedColor);
+ if (mShadowOverlayHelper.getWrapper() != null) {
+ for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
+ ((ShadowOverlayContainer) vh.mGridView.getChildAt(i))
+ .setOverlayColor(dimmedColor);
+ }
+ } else {
+ for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
+ ShadowOverlayHelper.setForegroundColor(vh.mGridView.getChildAt(i), dimmedColor);
+ }
}
if (vh.mGridView.getFadingLeftEdge()) {
vh.mGridView.invalidate();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
index e1c5979..f21670c 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/RoundedRectHelper.java
@@ -33,6 +33,10 @@
return sInstance;
}
+ public static boolean supportsRoundedCorner() {
+ return Build.VERSION.SDK_INT >= 21;
+ }
+
/**
* Sets or removes a rounded rectangle outline on the given view.
*/
@@ -65,7 +69,7 @@
}
private RoundedRectHelper() {
- if (Build.VERSION.SDK_INT >= 21) {
+ if (supportsRoundedCorner()) {
mImpl = new Api21Impl();
} else {
mImpl = new StubImpl();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
index be70575..9532635 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowHelper.java
@@ -32,7 +32,7 @@
*/
static interface ShadowHelperVersionImpl {
public Object addDynamicShadow(
- ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners);
+ View shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners);
public void setZ(View view, float z);
public void setShadowFocusLevel(Object impl, float level);
}
@@ -43,7 +43,7 @@
private static final class ShadowHelperStubImpl implements ShadowHelperVersionImpl {
@Override
public Object addDynamicShadow(
- ViewGroup shadowContainer, float focusedZ, float unfocusedZ, boolean roundedCorners) {
+ View shadowContainer, float focusedZ, float unfocusedZ, boolean roundedCorners) {
// do nothing
return null;
}
@@ -65,7 +65,7 @@
private static final class ShadowHelperApi21Impl implements ShadowHelperVersionImpl {
@Override
public Object addDynamicShadow(
- ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
+ View shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
return ShadowHelperApi21.addDynamicShadow(
shadowContainer, unfocusedZ, focusedZ, roundedCorners);
}
@@ -102,7 +102,7 @@
}
public Object addDynamicShadow(
- ViewGroup shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
+ View shadowContainer, float unfocusedZ, float focusedZ, boolean roundedCorners) {
return mImpl.addDynamicShadow(shadowContainer, unfocusedZ, focusedZ, roundedCorners);
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
index e367494..84a30e4 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
@@ -20,6 +20,9 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.Rect;
/**
@@ -51,20 +54,19 @@
/**
* No shadow.
*/
- public static final int SHADOW_NONE = 1;
+ public static final int SHADOW_NONE = ShadowOverlayHelper.SHADOW_NONE;
/**
* Shadows are fixed.
*/
- public static final int SHADOW_STATIC = 2;
+ public static final int SHADOW_STATIC = ShadowOverlayHelper.SHADOW_STATIC;
/**
* Shadows depend on the size, shape, and position of the view.
*/
- public static final int SHADOW_DYNAMIC = 3;
+ public static final int SHADOW_DYNAMIC = ShadowOverlayHelper.SHADOW_DYNAMIC;
private boolean mInitialized;
- private View mColorDimOverlay;
private Object mShadowImpl;
private View mWrappedView;
private boolean mRoundedCorners;
@@ -72,15 +74,26 @@
private float mUnfocusedZ;
private float mFocusedZ;
private static final Rect sTempRect = new Rect();
+ private Paint mOverlayPaint;
+ private int mOverlayColor;
+ /**
+ * Create ShadowOverlayContainer and auto select shadow type.
+ */
public ShadowOverlayContainer(Context context) {
this(context, null, 0);
}
+ /**
+ * Create ShadowOverlayContainer and auto select shadow type.
+ */
public ShadowOverlayContainer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
+ /**
+ * Create ShadowOverlayContainer and auto select shadow type.
+ */
public ShadowOverlayContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
useStaticShadow();
@@ -88,6 +101,17 @@
}
/**
+ * Create ShadowOverlayContainer with specific shadowType.
+ */
+ public ShadowOverlayContainer(Context context,
+ int shadowType, boolean hasColorDimOverlay, boolean roundedCorners) {
+ super(context);
+ mUnfocusedZ = getResources().getDimension(R.dimen.lb_material_shadow_normal_z);
+ mFocusedZ = getResources().getDimension(R.dimen.lb_material_shadow_focused_z);
+ initialize(shadowType, hasColorDimOverlay, roundedCorners);
+ }
+
+ /**
* Return true if the platform sdk supports shadow.
*/
public static boolean supportsShadow() {
@@ -164,29 +188,59 @@
/**
* Initialize shadows, color overlay, and rounded corners. All are optional.
+ * Shadow type are auto-selected based on {@link #useStaticShadow()} and
+ * {@link #useDynamicShadow()} call.
+ * @deprecated use {@link #initialize(int, boolean, boolean)} instead.
*/
+ @Deprecated
public void initialize(boolean hasShadow, boolean hasColorDimOverlay, boolean roundedCorners) {
+ int shadowType;
+ if (!hasShadow) {
+ shadowType = SHADOW_NONE;
+ } else {
+ shadowType = mShadowType;
+ }
+ initialize(shadowType, hasColorDimOverlay, roundedCorners);
+ }
+
+ /**
+ * Initialize shadows, color overlay, and rounded corners. All are optional.
+ */
+ public void initialize(int shadowType, boolean hasColorDimOverlay, boolean roundedCorners) {
if (mInitialized) {
throw new IllegalStateException();
}
mInitialized = true;
- if (hasShadow) {
- switch (mShadowType) {
- case SHADOW_DYNAMIC:
- mShadowImpl = ShadowHelper.getInstance().addDynamicShadow(
- this, mUnfocusedZ, mFocusedZ, roundedCorners);
- break;
- case SHADOW_STATIC:
- mShadowImpl = StaticShadowHelper.getInstance().addStaticShadow(
- this, roundedCorners);
- break;
- }
+ mShadowType = shadowType;
+ switch (mShadowType) {
+ case SHADOW_DYNAMIC:
+ mShadowImpl = ShadowHelper.getInstance().addDynamicShadow(
+ this, mUnfocusedZ, mFocusedZ, roundedCorners);
+ break;
+ case SHADOW_STATIC:
+ mShadowImpl = StaticShadowHelper.getInstance().addStaticShadow(this);
+ break;
}
mRoundedCorners = roundedCorners;
if (hasColorDimOverlay) {
- mColorDimOverlay = LayoutInflater.from(getContext())
- .inflate(R.layout.lb_card_color_overlay, this, false);
- addView(mColorDimOverlay);
+ setWillNotDraw(false);
+ mOverlayColor = Color.TRANSPARENT;
+ mOverlayPaint = new Paint();
+ mOverlayPaint.setColor(mOverlayColor);
+ mOverlayPaint.setStyle(Paint.Style.FILL);
+ } else {
+ setWillNotDraw(true);
+ mOverlayPaint = null;
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ if (mOverlayPaint != null && mOverlayColor != Color.TRANSPARENT) {
+ canvas.drawRect(mWrappedView.getLeft(), mWrappedView.getTop(),
+ mWrappedView.getRight(), mWrappedView.getBottom(),
+ mOverlayPaint);
}
}
@@ -195,19 +249,7 @@
*/
public void setShadowFocusLevel(float level) {
if (mShadowImpl != null) {
- if (level < 0f) {
- level = 0f;
- } else if (level > 1f) {
- level = 1f;
- }
- switch (mShadowType) {
- case SHADOW_DYNAMIC:
- ShadowHelper.getInstance().setShadowFocusLevel(mShadowImpl, level);
- break;
- case SHADOW_STATIC:
- StaticShadowHelper.getInstance().setShadowFocusLevel(mShadowImpl, level);
- break;
- }
+ ShadowOverlayHelper.setShadowFocusLevel(mShadowImpl, mShadowType, level);
}
}
@@ -215,8 +257,12 @@
* Set color (with alpha) of the overlay.
*/
public void setOverlayColor(@ColorInt int overlayColor) {
- if (mColorDimOverlay != null) {
- mColorDimOverlay.setBackgroundColor(overlayColor);
+ if (mOverlayPaint != null) {
+ if (overlayColor != mOverlayColor) {
+ mOverlayColor = overlayColor;
+ mOverlayPaint.setColor(overlayColor);
+ invalidate();
+ }
}
}
@@ -227,15 +273,11 @@
if (!mInitialized || mWrappedView != null) {
throw new IllegalStateException();
}
- if (mColorDimOverlay != null) {
- addView(view, indexOfChild(mColorDimOverlay));
- } else {
- addView(view);
+ addView(view);
+ if (mRoundedCorners && mShadowType == SHADOW_STATIC) {
+ RoundedRectHelper.getInstance().setClipToRoundedOutline(view, true);
}
mWrappedView = view;
- if (mRoundedCorners) {
- RoundedRectHelper.getInstance().setClipToRoundedOutline(mWrappedView, true);
- }
}
/**
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
new file mode 100644
index 0000000..457e882
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
@@ -0,0 +1,256 @@
+/*
+ * 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.content.res.Resources;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.support.v17.leanback.R;
+import android.support.v17.leanback.system.Settings;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.View;
+
+
+/**
+ * ShadowOverlayHelper is a helper class for shadow, overlay and rounded corner.
+ * Initialize it with all the options and it decides the best strategy.
+ * <li> For shadow: it may use 9-patch with opticalBounds or Z-value based shadow for
+ * API >= 21. When 9-patch is used, it requires a ShadowOverlayContainer
+ * created by ItemBridgeAdapter.Wrapper to include 9-patch views.
+ * <li> For overlay: it may use ShadowOverlayContainer which overrides draw() or it may
+ * use setForeground(new ColorDrawable()) for API>=23. The foreground support
+ * might be disabled if rounded corner is applied due to performance reason.
+ * <li> For rounded-corner: it uses a ViewOutlineProvider for API>=21.
+ * @hide
+ */
+public final class ShadowOverlayHelper {
+
+ /**
+ * No shadow.
+ */
+ public static final int SHADOW_NONE = 1;
+
+ /**
+ * Shadows are fixed.
+ */
+ public static final int SHADOW_STATIC = 2;
+
+ /**
+ * Shadows depend on the size, shape, and position of the view.
+ */
+ public static final int SHADOW_DYNAMIC = 3;
+
+ int mShadowType = SHADOW_NONE;
+ boolean mNeedsOverlay;
+ boolean mNeedsRoundedCorner;
+ boolean mNeedsShadow;
+ boolean mNeedsWrapper;
+ private ItemBridgeAdapter.Wrapper mCardWrapper;
+
+ float mUnfocusedZ;
+ float mFocusedZ;
+
+ /**
+ * Return true if the platform sdk supports shadow.
+ */
+ public static boolean supportsShadow() {
+ return StaticShadowHelper.getInstance().supportsShadow();
+ }
+
+ /**
+ * Returns true if the platform sdk supports dynamic shadows.
+ */
+ public static boolean supportsDynamicShadow() {
+ return ShadowHelper.getInstance().supportsDynamicShadow();
+ }
+
+ /**
+ * Returns true if the platform sdk supports rounded corner through outline.
+ */
+ public static boolean supportsRoundedCorner() {
+ return RoundedRectHelper.supportsRoundedCorner();
+ }
+
+ /**
+ * Returns true if view.setForeground() is supported.
+ */
+ public static boolean supportsForeground() {
+ return ForegroundHelper.supportsForeground();
+ }
+
+ /**
+ * Create ShadowHelper that includes all options.
+ *
+ * @param context Context that required to query options
+ * @param needsOverlay true if overlay (dim) is needed
+ * @param needsShadow true if shadow is needed
+ * @param needsRoundedCorner true if roundedCorner is needed.
+ * @param preferZOrder true if prefer dynamic shadow otherwise static shadow is used.
+ */
+ public ShadowOverlayHelper(Context context,
+ boolean needsOverlay, boolean needsShadow, boolean needsRoundedCorner,
+ boolean preferZOrder) {
+ mNeedsOverlay = needsOverlay;
+ mNeedsRoundedCorner = needsRoundedCorner && supportsRoundedCorner();
+ mNeedsShadow = needsShadow && supportsShadow();
+
+ // Force to use wrapper to avoid rebuild rounded corner outline on animating foreground
+ // drawable. See b/22724385
+ final boolean forceWrapperForOverlay = mNeedsRoundedCorner;
+
+ // figure out shadow type and if we need use wrapper:
+ if (mNeedsShadow) {
+ // if static shadow is prefered or dynamic shadow is not supported,
+ // use static shadow, otherwise use dynamic shadow.
+ if (!preferZOrder || !supportsDynamicShadow()) {
+ mShadowType = SHADOW_STATIC;
+ // static shadow requires ShadowOverlayContainer to support crossfading
+ // of two shadow views.
+ mNeedsWrapper = true;
+ } else {
+ useDynamicShadow(context);
+ mNeedsWrapper = ((!supportsForeground() || forceWrapperForOverlay) && mNeedsOverlay);
+ }
+ } else {
+ mShadowType = SHADOW_NONE;
+ mNeedsWrapper = ((!supportsForeground() || forceWrapperForOverlay) && mNeedsOverlay);
+ }
+
+ if (mNeedsWrapper) {
+ mCardWrapper = new ItemBridgeAdapter.Wrapper() {
+ @Override
+ public View createWrapper(View root) {
+ Context context = root.getContext();
+ ShadowOverlayContainer wrapper = createShadowOverlayContainer(context);
+ wrapper.setLayoutParams(
+ new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ return wrapper;
+ }
+ @Override
+ public void wrap(View wrapper, View wrapped) {
+ ((ShadowOverlayContainer) wrapper).wrap(wrapped);
+ }
+ };
+ }
+ }
+
+ /**
+ * {@link #prepareParentForShadow(ViewGroup)} must be called on parent of container
+ * before using shadow. Depending on Shadow type, optical bounds might be applied.
+ */
+ public void prepareParentForShadow(ViewGroup parent) {
+ if (mShadowType == SHADOW_STATIC) {
+ StaticShadowHelper.getInstance().prepareParent(parent);
+ }
+ }
+
+ void useDynamicShadow(Context context) {
+ Resources res = context.getResources();
+ useDynamicShadow(res.getDimension(R.dimen.lb_material_shadow_normal_z),
+ res.getDimension(R.dimen.lb_material_shadow_focused_z));
+ }
+
+ void useDynamicShadow(float unfocusedZ, float focusedZ) {
+ mShadowType = SHADOW_DYNAMIC;
+ mUnfocusedZ = unfocusedZ;
+ mFocusedZ = focusedZ;
+ }
+
+ public int getShadowType() {
+ return mShadowType;
+ }
+
+ public boolean needsOverlay() {
+ return mNeedsOverlay;
+ }
+
+ public boolean needsRoundedCorner() {
+ return mNeedsRoundedCorner;
+ }
+
+ ShadowOverlayContainer createShadowOverlayContainer(Context context) {
+ return new ShadowOverlayContainer(context, mShadowType, mNeedsOverlay,
+ mNeedsRoundedCorner);
+ }
+
+ public ItemBridgeAdapter.Wrapper getWrapper() {
+ return mCardWrapper;
+ }
+
+ /**
+ * Set foreground color for view other than ShadowOverlayContainer.
+ */
+ public static void setForegroundColor(View view, int color) {
+ Drawable d = ForegroundHelper.getInstance().getForeground(view);
+ if (d instanceof ColorDrawable) {
+ ((ColorDrawable) d).setColor(color);
+ } else {
+ ForegroundHelper.getInstance().setForeground(view, new ColorDrawable(color));
+ }
+ }
+
+ /**
+ * Called on view is created.
+ * @param view
+ */
+ public void onViewCreated(View view) {
+ if (!mNeedsWrapper) {
+ if (!mNeedsShadow) {
+ if (mNeedsRoundedCorner) {
+ RoundedRectHelper.getInstance().setClipToRoundedOutline(view, true);
+ }
+ } else {
+ if (mShadowType == SHADOW_DYNAMIC) {
+ Object tag = ShadowHelper.getInstance().addDynamicShadow(
+ view, mUnfocusedZ, mFocusedZ, mNeedsRoundedCorner);
+ view.setTag(R.id.lb_shadow_impl, tag);
+ }
+ }
+ }
+ }
+
+ public static Object getNoneWrapperDyamicShadowImpl(View view) {
+ return view.getTag(R.id.lb_shadow_impl);
+ }
+
+ /**
+ * Set shadow focus level (0 to 1). 0 for unfocused, 1f for fully focused.
+ * This is for view other than ShadowOverlayContainer.
+ */
+ public static void setShadowFocusLevel(View view, float level) {
+ setShadowFocusLevel(getNoneWrapperDyamicShadowImpl(view), SHADOW_DYNAMIC, level);
+ }
+
+ static void setShadowFocusLevel(Object impl, int shadowType, float level) {
+ if (impl != null) {
+ if (level < 0f) {
+ level = 0f;
+ } else if (level > 1f) {
+ level = 1f;
+ }
+ switch (shadowType) {
+ case SHADOW_DYNAMIC:
+ ShadowHelper.getInstance().setShadowFocusLevel(impl, level);
+ break;
+ case SHADOW_STATIC:
+ StaticShadowHelper.getInstance().setShadowFocusLevel(impl, level);
+ break;
+ }
+ }
+ }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
index 4d8411b..022ff1d 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/StaticShadowHelper.java
@@ -34,7 +34,7 @@
*/
static interface ShadowHelperVersionImpl {
public void prepareParent(ViewGroup parent);
- public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners);
+ public Object addStaticShadow(ViewGroup shadowContainer);
public void setShadowFocusLevel(Object impl, float level);
}
@@ -48,7 +48,7 @@
}
@Override
- public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
+ public Object addStaticShadow(ViewGroup shadowContainer) {
// do nothing
return null;
}
@@ -69,8 +69,7 @@
}
@Override
- public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
- // Static shadows are always rounded
+ public Object addStaticShadow(ViewGroup shadowContainer) {
return ShadowHelperJbmr2.addShadow(shadowContainer);
}
@@ -105,8 +104,8 @@
mImpl.prepareParent(parent);
}
- public Object addStaticShadow(ViewGroup shadowContainer, boolean roundedCorners) {
- return mImpl.addStaticShadow(shadowContainer, roundedCorners);
+ public Object addStaticShadow(ViewGroup shadowContainer) {
+ return mImpl.addStaticShadow(shadowContainer);
}
public void setShadowFocusLevel(Object impl, float level) {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
index 16b66cd..c04fe85 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/VerticalGridPresenter.java
@@ -31,6 +31,13 @@
class VerticalGridItemBridgeAdapter extends ItemBridgeAdapter {
@Override
+ protected void onCreate(ItemBridgeAdapter.ViewHolder viewHolder) {
+ if (mShadowOverlayHelper != null) {
+ mShadowOverlayHelper.onViewCreated(viewHolder.itemView);
+ }
+ }
+
+ @Override
public void onBind(final ItemBridgeAdapter.ViewHolder itemViewHolder) {
// Only when having an OnItemClickListner, we attach the OnClickListener.
if (getOnItemViewClickedListener() != null) {
@@ -86,6 +93,7 @@
private OnItemViewSelectedListener mOnItemViewSelectedListener;
private OnItemViewClickedListener mOnItemViewClickedListener;
private boolean mRoundedCornersEnabled = true;
+ private ShadowOverlayHelper mShadowOverlayHelper;
/**
* Constructs a VerticalGridPresenter with defaults.
@@ -170,7 +178,7 @@
* Subclass may return false to disable.
*/
public boolean isUsingDefaultShadow() {
- return ShadowOverlayContainer.supportsShadow();
+ return ShadowOverlayHelper.supportsShadow();
}
/**
@@ -194,8 +202,7 @@
* and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
*/
public boolean isUsingZOrder(Context context) {
- return ShadowOverlayContainer.supportsDynamicShadow() &&
- !Settings.getInstance(context).preferStaticShadows();
+ return !Settings.getInstance(context).preferStaticShadows();
}
final boolean needsDefaultShadow() {
@@ -238,21 +245,6 @@
return new ViewHolder((VerticalGridView) root.findViewById(R.id.browse_grid));
}
- private ItemBridgeAdapter.Wrapper mWrapper = new ItemBridgeAdapter.Wrapper() {
- @Override
- public View createWrapper(View root) {
- ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
- wrapper.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- wrapper.initialize(needsDefaultShadow(), true, areChildRoundedCornersEnabled());
- return wrapper;
- }
- @Override
- public void wrap(View wrapper, View wrapped) {
- ((ShadowOverlayContainer) wrapper).wrap(wrapped);
- }
- };
-
/**
* Called after a {@link VerticalGridPresenter.ViewHolder} is created.
* Subclasses may override this method and start by calling
@@ -268,12 +260,15 @@
vh.getGridView().setNumColumns(mNumColumns);
vh.mInitialized = true;
- vh.mItemBridgeAdapter.setWrapper(mWrapper);
- if (needsDefaultShadow() || areChildRoundedCornersEnabled()) {
- ShadowOverlayContainer.prepareParentForShadow(vh.getGridView());
- ((ViewGroup) vh.view).setClipChildren(false);
+ Context context = vh.mGridView.getContext();
+ if (mShadowOverlayHelper == null) {
+ mShadowOverlayHelper = new ShadowOverlayHelper(context, mUseFocusDimmer,
+ needsDefaultShadow(), areChildRoundedCornersEnabled(), isUsingZOrder(context));
}
- vh.getGridView().setFocusDrawingOrderEnabled(!isUsingZOrder(vh.getGridView().getContext()));
+ vh.mItemBridgeAdapter.setWrapper(mShadowOverlayHelper.getWrapper());
+ mShadowOverlayHelper.prepareParentForShadow(vh.mGridView);
+ vh.getGridView().setFocusDrawingOrderEnabled(mShadowOverlayHelper.getShadowType()
+ == ShadowOverlayHelper.SHADOW_STATIC);
FocusHighlightHelper.setupBrowseItemFocusHighlight(vh.mItemBridgeAdapter,
mFocusZoomFactor, mUseFocusDimmer);
diff --git a/v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml b/v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml
new file mode 100644
index 0000000..efdf1c0
--- /dev/null
+++ b/v17/preference-leanback/res/color/lb_preference_item_primary_text_color.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/lb_preference_item_primary_text_color_disabled" />
+ <item android:color="@color/lb_preference_item_primary_text_color_default"/>
+</selector>
diff --git a/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml b/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml
new file mode 100644
index 0000000..68bb81a
--- /dev/null
+++ b/v17/preference-leanback/res/color/lb_preference_item_secondary_text_color.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/lb_preference_item_secondary_text_color_disabled" />
+ <item android:color="@color/lb_preference_item_secondary_text_color_default"/>
+</selector>
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml b/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
index 9fae0f8..c0a5bf9 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
@@ -35,11 +35,11 @@
android:id="@+id/decor_title"
android:layout_width="match_parent"
android:layout_height="@dimen/lb_preference_decor_title_text_height"
+ android:layout_marginTop="@dimen/lb_preference_decor_title_margin_top"
+ android:layout_marginStart="@dimen/lb_preference_decor_title_margin_start"
+ android:layout_marginEnd="@dimen/lb_preference_decor_title_margin_end"
android:fontFamily="sans-serif-condensed"
android:gravity="center_vertical"
- android:paddingTop="@dimen/lb_preference_decor_title_padding_top"
- android:paddingStart="@dimen/lb_preference_decor_title_padding_start"
- android:paddingEnd="@dimen/lb_preference_decor_title_padding_end"
android:singleLine="true"
android:textSize="@dimen/lb_preference_decor_title_text_size"
android:textColor="?android:attr/textColorPrimary"
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml b/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
index 3b1345c..04ea1dc 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
@@ -18,20 +18,34 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:descendantFocusability="blocksDescendants"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
<CheckBox
android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@android:id/title"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center_vertical" />
+ android:layout_width="@dimen/lb_preference_item_icon_size"
+ android:layout_height="@dimen/lb_preference_item_icon_size"
+ android:layout_marginEnd="@dimen/lb_preference_item_icon_margin_end"
+ android:layout_gravity="center_vertical" />
+
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+ </LinearLayout>
+
</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml b/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
index eaf42a4..23e94bc 100644
--- a/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
@@ -18,20 +18,34 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:descendantFocusability="blocksDescendants"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
<RadioButton
android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@android:id/title"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center_vertical" />
+ android:layout_width="@dimen/lb_preference_item_icon_size"
+ android:layout_height="@dimen/lb_preference_item_icon_size"
+ android:layout_marginEnd="@dimen/lb_preference_item_icon_margin_end"
+ android:layout_gravity="center_vertical" />
+
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+ </LinearLayout>
+
</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference.xml b/v17/preference-leanback/res/layout/leanback_preference.xml
new file mode 100644
index 0000000..ca391c9
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference.xml
@@ -0,0 +1,72 @@
+<?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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
+ android:clickable="true"
+ android:focusable="true"
+ android:descendantFocusability="blocksDescendants"
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
+ <FrameLayout
+ android:id="@+id/icon_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" >
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ />
+ </FrameLayout>
+
+ <LinearLayout android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/lb_preference_item_secondary_text_color"
+ android:textSize="@dimen/lb_preference_item_secondary_text_size"
+ android:maxLines="4" />
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+ </LinearLayout>
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout android:id="@android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference_category.xml b/v17/preference-leanback/res/layout/leanback_preference_category.xml
new file mode 100644
index 0000000..b3c2067
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference_category.xml
@@ -0,0 +1,31 @@
+<?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
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/lb_preference_category_height"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end">
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_category_text_size"/>
+</FrameLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference_fragment.xml b/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
index d119c2d..ffbbf66 100644
--- a/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
+++ b/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
@@ -35,11 +35,11 @@
android:id="@+id/decor_title"
android:layout_width="match_parent"
android:layout_height="@dimen/lb_preference_decor_title_text_height"
+ android:layout_marginTop="@dimen/lb_preference_decor_title_margin_top"
+ android:layout_marginStart="@dimen/lb_preference_decor_title_margin_start"
+ android:layout_marginEnd="@dimen/lb_preference_decor_title_margin_end"
android:fontFamily="sans-serif-condensed"
android:gravity="center_vertical"
- android:paddingTop="@dimen/lb_preference_decor_title_padding_top"
- android:paddingStart="@dimen/lb_preference_decor_title_padding_start"
- android:paddingEnd="@dimen/lb_preference_decor_title_padding_end"
android:singleLine="true"
android:textSize="@dimen/lb_preference_decor_title_text_size"
android:textColor="?android:attr/textColorPrimary"
diff --git a/v17/preference-leanback/res/layout/leanback_preference_information.xml b/v17/preference-leanback/res/layout/leanback_preference_information.xml
new file mode 100644
index 0000000..8c0c4b9
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference_information.xml
@@ -0,0 +1,59 @@
+<?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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
+ android:clickable="false"
+ android:focusable="false"
+ android:descendantFocusability="blocksDescendants"
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/lb_preference_item_padding_start"
+ android:paddingEnd="@dimen/lb_preference_item_padding_end" >
+
+ <LinearLayout android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_top" />
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/lb_preference_item_primary_text_margin_bottom"
+ android:textColor="@color/lb_preference_item_primary_text_color"
+ android:textSize="@dimen/lb_preference_item_primary_text_size"/>
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/lb_preference_item_secondary_text_color"
+ android:textSize="@dimen/lb_preference_item_secondary_text_size"
+ android:maxLines="4" />
+ <Space android:layout_width="0dp" android:layout_height="@dimen/lb_preference_item_text_space_bottom" />
+ </LinearLayout>
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout android:id="@android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v17/preference-leanback/res/values/colors.xml b/v17/preference-leanback/res/values/colors.xml
index de6c888..30a373a 100644
--- a/v17/preference-leanback/res/values/colors.xml
+++ b/v17/preference-leanback/res/values/colors.xml
@@ -16,4 +16,11 @@
-->
<resources>
<color name="lb_preference_decor_list_background">#263238</color>
+
+ <color name="lb_preference_item_primary_text_color_default">#EEEEEE</color>
+ <color name="lb_preference_item_primary_text_color_disabled">#4DEEEEEE</color>
+
+ <color name="lb_preference_item_secondary_text_color_default">#B3EEEEEE</color>
+ <color name="lb_preference_item_secondary_text_color_disabled">#4DEEEEEE</color>
+
</resources>
diff --git a/v17/preference-leanback/res/values/dimens.xml b/v17/preference-leanback/res/values/dimens.xml
index 49763fe..dbd3b04 100644
--- a/v17/preference-leanback/res/values/dimens.xml
+++ b/v17/preference-leanback/res/values/dimens.xml
@@ -15,11 +15,25 @@
~ limitations under the License
-->
<resources>
- <dimen name="lb_preference_decor_title_text_height">64dp</dimen>
- <dimen name="lb_preference_decor_title_padding_top">27dp</dimen>
- <dimen name="lb_preference_decor_title_padding_start">24dp</dimen>
- <dimen name="lb_preference_decor_title_padding_end">56dp</dimen>
- <dimen name="lb_preference_decor_title_text_size">20sp</dimen>
+ <dimen name="lb_preference_decor_title_text_height">64dp</dimen>
+ <dimen name="lb_preference_decor_title_margin_top">27dp</dimen>
+ <dimen name="lb_preference_decor_title_margin_start">24dp</dimen>
+ <dimen name="lb_preference_decor_title_margin_end">56dp</dimen>
+ <dimen name="lb_preference_decor_title_text_size">20sp</dimen>
- <dimen name="lb_settings_pane_width">360dp</dimen>
+ <dimen name="lb_preference_item_padding_start">24dp</dimen>
+ <dimen name="lb_preference_item_padding_end">56dp</dimen>
+ <dimen name="lb_preference_item_icon_size">32dp</dimen>
+ <dimen name="lb_preference_item_icon_margin_end">16dp</dimen>
+
+ <dimen name="lb_preference_item_primary_text_size">14sp</dimen>
+ <dimen name="lb_preference_item_primary_text_margin_bottom">2dp</dimen>
+ <dimen name="lb_preference_item_secondary_text_size">12sp</dimen>
+ <dimen name="lb_preference_item_text_space_top">14dp</dimen>
+ <dimen name="lb_preference_item_text_space_bottom">13dp</dimen>
+
+ <dimen name="lb_preference_category_text_size">12sp</dimen>
+ <dimen name="lb_preference_category_height">40dp</dimen>
+
+ <dimen name="lb_settings_pane_width">360dp</dimen>
</resources>
diff --git a/v17/preference-leanback/res/values/styles.xml b/v17/preference-leanback/res/values/styles.xml
new file mode 100644
index 0000000..0b315a8
--- /dev/null
+++ b/v17/preference-leanback/res/values/styles.xml
@@ -0,0 +1,65 @@
+<?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
+ -->
+
+<resources>
+
+ <style name="LeanbackPreference">
+ <item name="layout">@layout/leanback_preference</item>
+ </style>
+
+ <style name="LeanbackPreference.Information">
+ <item name="layout">@layout/leanback_preference_information</item>
+ <item name="enabled">false</item>
+ <item name="shouldDisableView">false</item>
+ </style>
+
+ <style name="LeanbackPreference.Category">
+ <item name="layout">@layout/leanback_preference_category</item>
+ <!-- The title should not dim if the category is disabled, instead only the preference children should dim. -->
+ <item name="shouldDisableView">false</item>
+ <item name="selectable">false</item>
+ </style>
+
+ <style name="LeanbackPreference.CheckBoxPreference">
+ <item name="widgetLayout">@layout/preference_widget_checkbox</item>
+ </style>
+
+ <style name="LeanbackPreference.SwitchPreferenceCompat">
+ <item name="widgetLayout">@layout/preference_widget_switch_compat</item>
+ <item name="switchTextOn">@string/v7_preference_on</item>
+ <item name="switchTextOff">@string/v7_preference_off</item>
+ </style>
+
+ <style name="LeanbackPreference.SwitchPreference">
+ <item name="widgetLayout">@layout/preference_widget_switch</item>
+ <item name="switchTextOn">@string/v7_preference_on</item>
+ <item name="switchTextOff">@string/v7_preference_off</item>
+ </style>
+
+ <style name="LeanbackPreference.PreferenceScreen">
+ </style>
+
+ <style name="LeanbackPreference.DialogPreference">
+ <item name="positiveButtonText">@android:string/ok</item>
+ <item name="negativeButtonText">@android:string/cancel</item>
+ </style>
+
+ <style name="LeanbackPreference.DialogPreference.EditTextPreference">
+ <item name="dialogLayout">@layout/preference_dialog_edittext</item>
+ </style>
+
+</resources>
diff --git a/v17/preference-leanback/res/values/themes.xml b/v17/preference-leanback/res/values/themes.xml
new file mode 100644
index 0000000..b3060d9
--- /dev/null
+++ b/v17/preference-leanback/res/values/themes.xml
@@ -0,0 +1,30 @@
+<?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
+ -->
+
+<resources>
+ <style name="PreferenceThemeOverlay.v14.Leanback">
+ <item name="preferenceScreenStyle">@style/LeanbackPreference.PreferenceScreen</item>
+ <item name="preferenceCategoryStyle">@style/LeanbackPreference.Category</item>
+ <item name="preferenceStyle">@style/LeanbackPreference</item>
+ <item name="preferenceInformationStyle">@style/LeanbackPreference.Information</item>
+ <item name="checkBoxPreferenceStyle">@style/LeanbackPreference.CheckBoxPreference</item>
+ <item name="switchPreferenceCompatStyle">@style/LeanbackPreference.SwitchPreferenceCompat</item>
+ <item name="switchPreferenceStyle">@style/LeanbackPreference.SwitchPreference</item>
+ <item name="dialogPreferenceStyle">@style/LeanbackPreference.DialogPreference</item>
+ <item name="editTextPreferenceStyle">@style/LeanbackPreference.DialogPreference.EditTextPreference</item>
+ </style>
+</resources>
diff --git a/v4/java/android/support/v4/graphics/ColorUtils.java b/v4/java/android/support/v4/graphics/ColorUtils.java
index aac809b..4d9d9b2 100644
--- a/v4/java/android/support/v4/graphics/ColorUtils.java
+++ b/v4/java/android/support/v4/graphics/ColorUtils.java
@@ -17,6 +17,10 @@
package android.support.v4.graphics;
import android.graphics.Color;
+import android.support.annotation.ColorInt;
+import android.support.annotation.FloatRange;
+import android.support.annotation.IntRange;
+import android.support.annotation.NonNull;
/**
* A set of color-related utility methods, building upon those available in {@code Color}.
@@ -24,14 +28,14 @@
public class ColorUtils {
private static final int MIN_ALPHA_SEARCH_MAX_ITERATIONS = 10;
- private static final int MIN_ALPHA_SEARCH_PRECISION = 10;
+ private static final int MIN_ALPHA_SEARCH_PRECISION = 1;
private ColorUtils() {}
/**
* Composite two potentially translucent colors over each other and returns the result.
*/
- public static int compositeColors(int foreground, int background) {
+ public static int compositeColors(@ColorInt int foreground, @ColorInt int background) {
int bgAlpha = Color.alpha(background);
int fgAlpha = Color.alpha(foreground);
int a = compositeAlpha(fgAlpha, bgAlpha);
@@ -57,10 +61,13 @@
/**
* Returns the luminance of a color.
- *
- * Formula defined here: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+ * <p>
+ * Formula defined
+ * <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef">here</a>.
+ * </p>
*/
- public static double calculateLuminance(int color) {
+ @FloatRange(from = 0.0, to = 1.0)
+ public static double calculateLuminance(@ColorInt int color) {
double red = Color.red(color) / 255d;
red = red < 0.03928 ? red / 12.92 : Math.pow((red + 0.055) / 1.055, 2.4);
@@ -80,9 +87,10 @@
* Formula defined
* <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef">here</a>.
*/
- public static double calculateContrast(int foreground, int background) {
+ public static double calculateContrast(@ColorInt int foreground, @ColorInt int background) {
if (Color.alpha(background) != 255) {
- throw new IllegalArgumentException("background can not be translucent");
+ throw new IllegalArgumentException("background can not be translucent: #"
+ + Integer.toHexString(background));
}
if (Color.alpha(foreground) < 255) {
// If the foreground is translucent, composite the foreground over the background
@@ -106,10 +114,11 @@
* @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(int foreground, int background,
+ public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background,
float minContrastRatio) {
if (Color.alpha(background) != 255) {
- throw new IllegalArgumentException("background can not be translucent");
+ throw new IllegalArgumentException("background can not be translucent: #"
+ + Integer.toHexString(background));
}
// First lets check that a fully opaque foreground has sufficient contrast
@@ -158,7 +167,9 @@
* @param b blue component value [0..255]
* @param hsl 3 element array which holds the resulting HSL components.
*/
- public static void RGBToHSL(int r, int g, int b, float[] hsl) {
+ 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) {
final float rf = r / 255f;
final float gf = g / 255f;
final float bf = b / 255f;
@@ -206,7 +217,7 @@
* @param color the ARGB color to convert. The alpha component is ignored.
* @param hsl 3 element array which holds the resulting HSL components.
*/
- public static void colorToHSL(int color, float[] hsl) {
+ public static void colorToHSL(@ColorInt int color, @NonNull float[] hsl) {
RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hsl);
}
@@ -222,7 +233,8 @@
* @param hsl 3 element array which holds the input HSL components.
* @return the resulting RGB color
*/
- public static int HSLToColor(float[] hsl) {
+ @ColorInt
+ public static int HSLToColor(@NonNull float[] hsl) {
final float h = hsl[0];
final float s = hsl[1];
final float l = hsl[2];
@@ -279,7 +291,9 @@
/**
* Set the alpha component of {@code color} to be {@code alpha}.
*/
- public static int setAlphaComponent(int color, int alpha) {
+ @ColorInt
+ public static int setAlphaComponent(@ColorInt int color,
+ @IntRange(from = 0x0, to = 0xFF) int alpha) {
if (alpha < 0 || alpha > 255) {
throw new IllegalArgumentException("alpha must be between 0 and 255.");
}
diff --git a/v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java b/v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java
index 855cdba..56cb6fb 100644
--- a/v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java
+++ b/v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java
@@ -17,9 +17,9 @@
package android.support.v4.graphics;
import android.graphics.Color;
-import android.support.v4.graphics.ColorUtils;
import android.test.AndroidTestCase;
+import java.lang.Integer;
import java.util.ArrayList;
/**
@@ -31,21 +31,31 @@
private static final float ALLOWED_OFFSET_HUE = 360 * 0.005f;
private static final float ALLOWED_OFFSET_SATURATION = 0.005f;
private static final float ALLOWED_OFFSET_LIGHTNESS = 0.005f;
+ private static final float ALLOWED_OFFSET_MIN_ALPHA = 0.01f;
private static final int ALLOWED_OFFSET_RGB_COMPONENT = 2;
private static final ArrayList<TestEntry> sEntryList = new ArrayList<>();
static {
- sEntryList.add(new TestEntry(Color.BLACK).setHsl(0f, 0f, 0f));
- sEntryList.add(new TestEntry(Color.WHITE).setHsl(0f, 0f, 1f));
- sEntryList.add(new TestEntry(Color.BLUE).setHsl(240f, 1f, 0.5f));
- sEntryList.add(new TestEntry(Color.GREEN).setHsl(120f, 1f, 0.5f));
- sEntryList.add(new TestEntry(Color.RED).setHsl(0f, 1f, 0.5f));
- sEntryList.add(new TestEntry(Color.CYAN).setHsl(180f, 1f, 0.5f));
- sEntryList.add(new TestEntry(0x2196F3).setHsl(207f, 0.9f, 0.54f));
- sEntryList.add(new TestEntry(0xD1C4E9).setHsl(261f, 0.46f, 0.84f));
- sEntryList.add(new TestEntry(0x311B92).setHsl(251.09f, 0.687f, 0.339f));
+ sEntryList.add(new TestEntry(Color.BLACK).setHsl(0f, 0f, 0f)
+ .setWhiteMinAlpha30(0.35f).setWhiteMinAlpha45(0.46f));
+ sEntryList.add(new TestEntry(Color.WHITE).setHsl(0f, 0f, 1f)
+ .setBlackMinAlpha30(0.42f).setBlackMinAlpha45(0.54f));
+ sEntryList.add(new TestEntry(Color.BLUE).setHsl(240f, 1f, 0.5f)
+ .setWhiteMinAlpha30(0.55f).setWhiteMinAlpha45(0.71f));
+ sEntryList.add(new TestEntry(Color.GREEN).setHsl(120f, 1f, 0.5f)
+ .setBlackMinAlpha30(0.43f).setBlackMinAlpha45(0.55f));
+ sEntryList.add(new TestEntry(Color.RED).setHsl(0f, 1f, 0.5f)
+ .setWhiteMinAlpha30(0.84f).setBlackMinAlpha30(0.55f).setBlackMinAlpha45(0.78f));
+ sEntryList.add(new TestEntry(Color.CYAN).setHsl(180f, 1f, 0.5f)
+ .setBlackMinAlpha30(0.43f).setBlackMinAlpha45(0.55f));
+ sEntryList.add(new TestEntry(0xFF2196F3).setHsl(207f, 0.9f, 0.54f)
+ .setBlackMinAlpha30(0.52f).setWhiteMinAlpha30(0.97f).setBlackMinAlpha45(0.7f));
+ sEntryList.add(new TestEntry(0xFFD1C4E9).setHsl(261f, 0.46f, 0.84f)
+ .setBlackMinAlpha30(0.45f).setBlackMinAlpha45(0.58f));
+ sEntryList.add(new TestEntry(0xFF311B92).setHsl(251.09f, 0.687f, 0.339f)
+ .setWhiteMinAlpha30(0.39f).setWhiteMinAlpha45(0.54f));
}
public void testToHSL() {
@@ -72,6 +82,28 @@
}
}
+ public void testMinAlphas() {
+ for (TestEntry entry : sEntryList) {
+ testMinAlpha("Black title", entry.rgb, entry.blackMinAlpha30,
+ ColorUtils.calculateMinimumAlpha(Color.BLACK, entry.rgb, 3.0f));
+ testMinAlpha("Black body", entry.rgb, entry.blackMinAlpha45,
+ ColorUtils.calculateMinimumAlpha(Color.BLACK, entry.rgb, 4.5f));
+ testMinAlpha("White title", entry.rgb, entry.whiteMinAlpha30,
+ ColorUtils.calculateMinimumAlpha(Color.WHITE, entry.rgb, 3.0f));
+ testMinAlpha("White body", entry.rgb, entry.whiteMinAlpha45,
+ ColorUtils.calculateMinimumAlpha(Color.WHITE, entry.rgb, 4.5f));
+ }
+ }
+
+ private static void testMinAlpha(String title, int color, float expected, int actual) {
+ final String message = title + " text within error for #" + Integer.toHexString(color);
+ if (expected < 0) {
+ assertEquals(message, actual, -1);
+ } else {
+ assertClose(message, expected, actual / 255f, ALLOWED_OFFSET_MIN_ALPHA);
+ }
+ }
+
private static void assertClose(String message, float expected, float actual,
float allowedOffset) {
StringBuilder sb = new StringBuilder(message);
@@ -114,6 +146,10 @@
private static class TestEntry {
final int rgb;
final float[] hsl = new float[3];
+ float blackMinAlpha45 = -1;
+ float blackMinAlpha30 = -1;
+ float whiteMinAlpha45 = -1;
+ float whiteMinAlpha30 = -1;
TestEntry(int rgb) {
this.rgb = rgb;
@@ -125,5 +161,25 @@
hsl[2] = l;
return this;
}
+
+ TestEntry setBlackMinAlpha30(float minAlpha) {
+ blackMinAlpha30 = minAlpha;
+ return this;
+ }
+
+ TestEntry setBlackMinAlpha45(float minAlpha) {
+ blackMinAlpha45 = minAlpha;
+ return this;
+ }
+
+ TestEntry setWhiteMinAlpha30(float minAlpha) {
+ whiteMinAlpha30 = minAlpha;
+ return this;
+ }
+
+ TestEntry setWhiteMinAlpha45(float minAlpha) {
+ whiteMinAlpha45 = minAlpha;
+ return this;
+ }
}
}
\ No newline at end of file
diff --git a/v7/appcompat/api/current.txt b/v7/appcompat/api/current.txt
index 336e3a7..0a3bec5 100644
--- a/v7/appcompat/api/current.txt
+++ b/v7/appcompat/api/current.txt
@@ -368,6 +368,7 @@
field public static int alertDialogCenterButtons;
field public static int alertDialogStyle;
field public static int alertDialogTheme;
+ field public static int allowStacking;
field public static int arrowHeadLength;
field public static int arrowShaftLength;
field public static int autoCompleteTextViewStyle;
@@ -477,6 +478,7 @@
field public static int searchHintIcon;
field public static int searchIcon;
field public static int searchViewStyle;
+ field public static int seekBarStyle;
field public static int selectableItemBackground;
field public static int selectableItemBackgroundBorderless;
field public static int showAsAction;
@@ -540,6 +542,7 @@
field public static int abc_action_bar_embed_tabs;
field public static int abc_action_bar_embed_tabs_pre_jb;
field public static int abc_action_bar_expanded_action_views_exclusive;
+ field public static int abc_allow_stacked_button_bar;
field public static int abc_config_actionMenuItemAllCaps;
field public static int abc_config_allowActionMenuItemTextWithIcon;
field public static int abc_config_closeDialogWhenTouchOutside;
@@ -664,6 +667,8 @@
field public static int abc_panel_menu_list_width;
field public static int abc_search_view_preferred_width;
field public static int abc_search_view_text_min_width;
+ field public static int abc_seekbar_track_background_height_material;
+ field public static int abc_seekbar_track_progress_height_material;
field public static int abc_switch_padding;
field public static int abc_text_size_body_1_material;
field public static int abc_text_size_body_2_material;
@@ -748,6 +753,13 @@
field public static int abc_menu_hardkey_panel_mtrl_mult;
field public static int abc_popup_background_mtrl_mult;
field public static int abc_ratingbar_full_material;
+ field public static int abc_scrubber_control_off_mtrl_alpha;
+ field public static int abc_scrubber_control_to_pressed_mtrl_000;
+ field public static int abc_scrubber_control_to_pressed_mtrl_005;
+ field public static int abc_scrubber_primary_mtrl_alpha;
+ field public static int abc_scrubber_track_mtrl_alpha;
+ field public static int abc_seekbar_thumb_material;
+ field public static int abc_seekbar_track_material;
field public static int abc_spinner_mtrl_am_alpha;
field public static int abc_spinner_textfield_background_material;
field public static int abc_switch_thumb_material;
@@ -837,6 +849,7 @@
field public static int showCustom;
field public static int showHome;
field public static int showTitle;
+ field public static int spacer;
field public static int split_action_bar;
field public static int src_atop;
field public static int src_in;
@@ -877,6 +890,7 @@
field public static int abc_action_mode_close_item_material;
field public static int abc_activity_chooser_view;
field public static int abc_activity_chooser_view_list_item;
+ field public static int abc_alert_dialog_button_bar_material;
field public static int abc_alert_dialog_material;
field public static int abc_dialog_title_material;
field public static int abc_expanded_menu_layout;
@@ -1067,6 +1081,7 @@
field public static int Base_Widget_AppCompat_RatingBar;
field public static int Base_Widget_AppCompat_SearchView;
field public static int Base_Widget_AppCompat_SearchView_ActionBar;
+ field public static int Base_Widget_AppCompat_SeekBar;
field public static int Base_Widget_AppCompat_Spinner;
field public static int Base_Widget_AppCompat_Spinner_Underlined;
field public static int Base_Widget_AppCompat_TextView_SpinnerItem;
@@ -1225,6 +1240,7 @@
field public static int Widget_AppCompat_RatingBar;
field public static int Widget_AppCompat_SearchView;
field public static int Widget_AppCompat_SearchView_ActionBar;
+ field public static int Widget_AppCompat_SeekBar;
field public static int Widget_AppCompat_Spinner;
field public static int Widget_AppCompat_Spinner_DropDown;
field public static int Widget_AppCompat_Spinner_DropDown_ActionBar;
@@ -1289,6 +1305,7 @@
field public static final int[] AppCompatTextView;
field public static int AppCompatTextView_android_textAppearance;
field public static int AppCompatTextView_textAllCaps;
+ field public static int ButtonBarLayout_allowStacking;
field public static final int[] CompoundButton;
field public static int CompoundButton_android_button;
field public static int CompoundButton_buttonTint;
@@ -1483,6 +1500,7 @@
field public static int Theme_radioButtonStyle;
field public static int Theme_ratingBarStyle;
field public static int Theme_searchViewStyle;
+ field public static int Theme_seekBarStyle;
field public static int Theme_selectableItemBackground;
field public static int Theme_selectableItemBackgroundBorderless;
field public static int Theme_spinnerDropDownItemStyle;
@@ -1708,6 +1726,12 @@
ctor public AppCompatRatingBar(android.content.Context, android.util.AttributeSet, int);
}
+ public class AppCompatSeekBar extends android.widget.SeekBar {
+ ctor public AppCompatSeekBar(android.content.Context);
+ ctor public AppCompatSeekBar(android.content.Context, android.util.AttributeSet);
+ ctor public AppCompatSeekBar(android.content.Context, android.util.AttributeSet, int);
+ }
+
public class AppCompatSpinner extends android.widget.Spinner {
ctor public AppCompatSpinner(android.content.Context);
ctor public AppCompatSpinner(android.content.Context, int);
diff --git a/v7/appcompat/res-public/values/public_styles.xml b/v7/appcompat/res-public/values/public_styles.xml
index 4b42d0f..083fbc6 100644
--- a/v7/appcompat/res-public/values/public_styles.xml
+++ b/v7/appcompat/res-public/values/public_styles.xml
@@ -135,6 +135,7 @@
<public type="style" name="Widget.AppCompat.RatingBar"/>
<public type="style" name="Widget.AppCompat.SearchView"/>
<public type="style" name="Widget.AppCompat.SearchView.ActionBar"/>
+ <public type="style" name="Widget.AppCompat.SeekBar"/>
<public type="style" name="Widget.AppCompat.Spinner"/>
<public type="style" name="Widget.AppCompat.Spinner.DropDown"/>
<public type="style" name="Widget.AppCompat.Spinner.DropDown.ActionBar"/>
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_off_mtrl_alpha.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_off_mtrl_alpha.png
new file mode 100644
index 0000000..4efe298
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_off_mtrl_alpha.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..543dec3
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..9930b3a
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_primary_mtrl_alpha.9.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_primary_mtrl_alpha.9.png
new file mode 100644
index 0000000..4cfb1a7
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-hdpi/abc_scrubber_track_mtrl_alpha.9.png b/v7/appcompat/res/drawable-hdpi/abc_scrubber_track_mtrl_alpha.9.png
new file mode 100644
index 0000000..32ddf7a
--- /dev/null
+++ b/v7/appcompat/res/drawable-hdpi/abc_scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_off_mtrl_alpha.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_off_mtrl_alpha.png
new file mode 100644
index 0000000..10df639
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_off_mtrl_alpha.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..f83b1ef
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..e9efb20f
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_primary_mtrl_alpha.9.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_primary_mtrl_alpha.9.png
new file mode 100644
index 0000000..a4ab0a1
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_scrubber_track_mtrl_alpha.9.png b/v7/appcompat/res/drawable-mdpi/abc_scrubber_track_mtrl_alpha.9.png
new file mode 100644
index 0000000..db9e172
--- /dev/null
+++ b/v7/appcompat/res/drawable-mdpi/abc_scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_off_mtrl_alpha.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_off_mtrl_alpha.png
new file mode 100644
index 0000000..138f643
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_off_mtrl_alpha.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..cd41d74
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..8d67525
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_primary_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_primary_mtrl_alpha.9.png
new file mode 100644
index 0000000..2b4734d
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_scrubber_track_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_track_mtrl_alpha.9.png
new file mode 100644
index 0000000..805cb29
--- /dev/null
+++ b/v7/appcompat/res/drawable-xhdpi/abc_scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_off_mtrl_alpha.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_off_mtrl_alpha.png
new file mode 100644
index 0000000..5268745
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_off_mtrl_alpha.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..adffc14
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..f3d16d5
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_primary_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_primary_mtrl_alpha.9.png
new file mode 100644
index 0000000..6a82af5
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_track_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_track_mtrl_alpha.9.png
new file mode 100644
index 0000000..c3791fc
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxhdpi/abc_scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png b/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
new file mode 100644
index 0000000..e5a43bb
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_000.png
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png b/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
new file mode 100644
index 0000000..eeb37c1
--- /dev/null
+++ b/v7/appcompat/res/drawable-xxxhdpi/abc_scrubber_control_to_pressed_mtrl_005.png
Binary files differ
diff --git a/v7/appcompat/res/drawable/abc_seekbar_thumb_material.xml b/v7/appcompat/res/drawable/abc_seekbar_thumb_material.xml
new file mode 100644
index 0000000..7fea83bc
--- /dev/null
+++ b/v7/appcompat/res/drawable/abc_seekbar_thumb_material.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:constantSize="true">
+ <item android:state_enabled="false" android:state_pressed="true">
+ <bitmap android:src="@drawable/abc_scrubber_control_off_mtrl_alpha"
+ android:gravity="center"/>
+ </item>
+ <item android:state_enabled="false">
+ <bitmap android:src="@drawable/abc_scrubber_control_off_mtrl_alpha"
+ android:gravity="center"/>
+ </item>
+ <item android:state_pressed="true">
+ <bitmap android:src="@drawable/abc_scrubber_control_to_pressed_mtrl_005"
+ android:gravity="center"/>
+ </item>
+ <item>
+ <bitmap android:src="@drawable/abc_scrubber_control_to_pressed_mtrl_000"
+ android:gravity="center"/>
+ </item>
+</selector>
\ No newline at end of file
diff --git a/v7/appcompat/res/drawable/abc_seekbar_track_material.xml b/v7/appcompat/res/drawable/abc_seekbar_track_material.xml
new file mode 100644
index 0000000..e68ac03
--- /dev/null
+++ b/v7/appcompat/res/drawable/abc_seekbar_track_material.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@android:id/background"
+ android:drawable="@drawable/abc_scrubber_track_mtrl_alpha"/>
+ <item android:id="@android:id/secondaryProgress">
+ <scale android:scaleWidth="100%">
+ <selector>
+ <item android:state_enabled="false">
+ <color android:color="@android:color/transparent"/>
+ </item>
+ <item android:drawable="@drawable/abc_scrubber_primary_mtrl_alpha"/>
+ </selector>
+ </scale>
+ </item>
+ <item android:id="@android:id/progress">
+ <scale android:scaleWidth="100%">
+ <selector>
+ <item android:state_enabled="false">
+ <color android:color="@android:color/transparent"/>
+ </item>
+ <item android:drawable="@drawable/abc_scrubber_primary_mtrl_alpha"/>
+ </selector>
+ </scale>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/v7/appcompat/res/layout/abc_alert_dialog_button_bar_material.xml b/v7/appcompat/res/layout/abc_alert_dialog_button_bar_material.xml
new file mode 100644
index 0000000..4405707
--- /dev/null
+++ b/v7/appcompat/res/layout/abc_alert_dialog_button_bar_material.xml
@@ -0,0 +1,59 @@
+<?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.
+-->
+
+<android.support.v7.internal.widget.ButtonBarLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/buttonPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layoutDirection="locale"
+ android:orientation="horizontal"
+ android:paddingLeft="12dp"
+ android:paddingRight="12dp"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp"
+ android:gravity="bottom"
+ app:allowStacking="@bool/abc_allow_stacked_button_bar"
+ style="?attr/buttonBarStyle">
+
+ <Button
+ android:id="@android:id/button3"
+ style="?attr/buttonBarNeutralButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <android.support.v4.widget.Space
+ android:id="@+id/spacer"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+
+ <Button
+ android:id="@android:id/button2"
+ style="?attr/buttonBarNegativeButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <Button
+ android:id="@android:id/button1"
+ style="?attr/buttonBarPositiveButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</android.support.v7.internal.widget.ButtonBarLayout>
diff --git a/v7/appcompat/res/layout/abc_alert_dialog_material.xml b/v7/appcompat/res/layout/abc_alert_dialog_material.xml
index 9ba81fd..01ff885 100644
--- a/v7/appcompat/res/layout/abc_alert_dialog_material.xml
+++ b/v7/appcompat/res/layout/abc_alert_dialog_material.xml
@@ -108,41 +108,6 @@
android:layout_height="wrap_content"/>
</FrameLayout>
- <LinearLayout
- android:id="@+id/buttonPanel"
- style="?attr/buttonBarStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layoutDirection="locale"
- android:orientation="horizontal"
- android:paddingLeft="12dp"
- android:paddingRight="12dp"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:gravity="bottom">
+ <include layout="@layout/abc_alert_dialog_button_bar_material" />
- <Button
- android:id="@android:id/button3"
- style="?attr/buttonBarNeutralButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <android.support.v4.widget.Space
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:visibility="invisible"/>
-
- <Button
- android:id="@android:id/button2"
- style="?attr/buttonBarNegativeButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <Button
- android:id="@android:id/button1"
- style="?attr/buttonBarPositiveButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/v7/appcompat/res/values-az-rAZ/strings.xml b/v7/appcompat/res/values-az-rAZ/strings.xml
deleted file mode 100644
index a39f5f4..0000000
--- a/v7/appcompat/res/values-az-rAZ/strings.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2012 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 xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="abc_action_mode_done" msgid="4076576682505996667">"Hazırdır"</string>
- <string name="abc_action_bar_home_description" msgid="4600421777120114993">"Evə get"</string>
- <string name="abc_action_bar_up_description" msgid="1594238315039666878">"Yuxarı get"</string>
- <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Daha çox seçim"</string>
- <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Dağıt"</string>
- <string name="abc_action_bar_home_description_format" msgid="1397052879051804371">"%1$s, %2$s"</string>
- <string name="abc_action_bar_home_subtitle_description_format" msgid="6623331958280229229">"%1$s, %2$s, %3$s"</string>
- <string name="abc_searchview_description_search" msgid="8264924765203268293">"Axtarış"</string>
- <string name="abc_search_hint" msgid="7723749260725869598">"Axtarış..."</string>
- <string name="abc_searchview_description_query" msgid="2550479030709304392">"Axtarış sorğusu"</string>
- <string name="abc_searchview_description_clear" msgid="3691816814315814921">"Sorğunu təmizlə"</string>
- <string name="abc_searchview_description_submit" msgid="8928215447528550784">"Sorğunu göndərin"</string>
- <string name="abc_searchview_description_voice" msgid="893419373245838918">"Səsli axtarış"</string>
- <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"Tətbiq seçin"</string>
- <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"Hamısına baxın"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for abc_shareactionprovider_share_with_application (7165123711973476752) -->
- <skip />
- <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"Bununla paylaşın"</string>
- <string name="status_bar_notification_info_overflow" msgid="2869576371154716097">"999+"</string>
-</resources>
diff --git a/v17/leanback/res/layout/lb_card_color_overlay.xml b/v7/appcompat/res/values-h320dp/bools.xml
similarity index 73%
copy from v17/leanback/res/layout/lb_card_color_overlay.xml
copy to v7/appcompat/res/values-h320dp/bools.xml
index 45a40e1..5576c18 100644
--- a/v17/leanback/res/layout/lb_card_color_overlay.xml
+++ b/v7/appcompat/res/values-h320dp/bools.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 The Android Open Source Project
+<!-- 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.
@@ -15,7 +14,6 @@
limitations under the License.
-->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
+<resources>
+ <bool name="abc_allow_stacked_button_bar">true</bool>
+</resources>
diff --git a/v7/appcompat/res/values-kk-rKZ/strings.xml b/v7/appcompat/res/values-kk-rKZ/strings.xml
index 2ce080f..52b9af5 100644
--- a/v7/appcompat/res/values-kk-rKZ/strings.xml
+++ b/v7/appcompat/res/values-kk-rKZ/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="abc_action_mode_done" msgid="4076576682505996667">"Дайын"</string>
+ <string name="abc_action_mode_done" msgid="4076576682505996667">"Орындалды"</string>
<string name="abc_action_bar_home_description" msgid="4600421777120114993">"Негізгі бетте қозғалу"</string>
<string name="abc_action_bar_up_description" msgid="1594238315039666878">"Жоғары қозғалу"</string>
<string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Басқа опциялар"</string>
diff --git a/v7/appcompat/res/values-v21/styles_base.xml b/v7/appcompat/res/values-v21/styles_base.xml
index 47681f2..649f0ca 100644
--- a/v7/appcompat/res/values-v21/styles_base.xml
+++ b/v7/appcompat/res/values-v21/styles_base.xml
@@ -172,6 +172,8 @@
<style name="Base.Widget.AppCompat.RatingBar" parent="android:Widget.Material.RatingBar" />
+ <style name="Base.Widget.AppCompat.SeekBar" parent="android:Widget.Material.SeekBar" />
+
<style name="Base.Widget.AppCompat.Button" parent="android:Widget.Material.Button" />
<style name="Base.Widget.AppCompat.Button.Small" parent="android:Widget.Material.Button.Small" />
diff --git a/v7/appcompat/res/values/attrs.xml b/v7/appcompat/res/values/attrs.xml
index 040bea1..174fcc8 100644
--- a/v7/appcompat/res/values/attrs.xml
+++ b/v7/appcompat/res/values/attrs.xml
@@ -371,6 +371,8 @@
<attr name="radioButtonStyle" format="reference" />
<!-- Default RatingBar style. -->
<attr name="ratingBarStyle" format="reference" />
+ <!-- Default SeekBar style. -->
+ <attr name="seekBarStyle" format="reference" />
<!-- Default Spinner style. -->
<attr name="spinnerStyle" format="reference" />
<!-- Default style for the Switch widget. -->
@@ -943,4 +945,11 @@
<attr name="listItemLayout" format="reference" />
</declare-styleable>
+ <!-- @hide -->
+ <declare-styleable name="ButtonBarLayout">
+ <!-- Whether to automatically stack the buttons when there is not
+ enough space to lay them out side-by-side. -->
+ <attr name="allowStacking" format="boolean" />
+ </declare-styleable>
+
</resources>
diff --git a/v7/appcompat/res/values/bools.xml b/v7/appcompat/res/values/bools.xml
index 79a5035..3508cf3 100644
--- a/v7/appcompat/res/values/bools.xml
+++ b/v7/appcompat/res/values/bools.xml
@@ -21,4 +21,8 @@
<bool name="abc_action_bar_expanded_action_views_exclusive">true</bool>
<bool name="abc_config_showMenuShortcutsWhenKeyboardPresent">false</bool>
+
+ <!-- Whether to allow vertically stacked button bars. This is disabled for
+ configurations with a small (e.g. less than 320dp) screen height. -->
+ <bool name="abc_allow_stacked_button_bar">false</bool>
</resources>
diff --git a/v7/appcompat/res/values/dimens_material.xml b/v7/appcompat/res/values/dimens_material.xml
index f67127c..357dc3e 100644
--- a/v7/appcompat/res/values/dimens_material.xml
+++ b/v7/appcompat/res/values/dimens_material.xml
@@ -68,4 +68,7 @@
<item name="abc_disabled_alpha_material_light" format="float" type="dimen">0.26</item>
<item name="abc_disabled_alpha_material_dark" format="float" type="dimen">0.30</item>
+ <dimen name="abc_seekbar_track_background_height_material">2dp</dimen>
+ <dimen name="abc_seekbar_track_progress_height_material">2dp</dimen>
+
</resources>
diff --git a/v7/appcompat/res/values/styles.xml b/v7/appcompat/res/values/styles.xml
index e10c01f..9453944 100644
--- a/v7/appcompat/res/values/styles.xml
+++ b/v7/appcompat/res/values/styles.xml
@@ -224,6 +224,8 @@
<style name="AlertDialog.AppCompat.Light" parent="Base.AlertDialog.AppCompat.Light" />
+ <style name="Widget.AppCompat.SeekBar" parent="Base.Widget.AppCompat.SeekBar" />
+
<!-- Toolbar -->
<style name="Widget.AppCompat.Toolbar" parent="Base.Widget.AppCompat.Toolbar" />
diff --git a/v7/appcompat/res/values/styles_base.xml b/v7/appcompat/res/values/styles_base.xml
index d65b16f..8df76d8 100644
--- a/v7/appcompat/res/values/styles_base.xml
+++ b/v7/appcompat/res/values/styles_base.xml
@@ -395,6 +395,16 @@
<item name="android:indeterminateDrawable">@drawable/abc_ratingbar_full_material</item>
</style>
+ <style name="Base.Widget.AppCompat.SeekBar" parent="android:Widget">
+ <item name="android:indeterminateOnly">false</item>
+ <item name="android:progressDrawable">@drawable/abc_seekbar_track_material</item>
+ <item name="android:indeterminateDrawable">@drawable/abc_seekbar_track_material</item>
+ <item name="android:thumb">@drawable/abc_seekbar_thumb_material</item>
+ <item name="android:focusable">true</item>
+ <item name="android:paddingLeft">16dip</item>
+ <item name="android:paddingRight">16dip</item>
+ </style>
+
<!-- Bordered ink button -->
<style name="Base.Widget.AppCompat.Button" parent="android:Widget">
<item name="android:background">@drawable/abc_btn_default_mtrl_shape</item>
diff --git a/v7/appcompat/res/values/themes_base.xml b/v7/appcompat/res/values/themes_base.xml
index d0dfca5..298196f 100644
--- a/v7/appcompat/res/values/themes_base.xml
+++ b/v7/appcompat/res/values/themes_base.xml
@@ -229,6 +229,7 @@
<item name="switchStyle">@style/Widget.AppCompat.CompoundButton.Switch</item>
<item name="ratingBarStyle">@style/Widget.AppCompat.RatingBar</item>
+ <item name="seekBarStyle">@style/Widget.AppCompat.SeekBar</item>
<!-- Button styles -->
<item name="buttonStyle">@style/Widget.AppCompat.Button</item>
@@ -379,6 +380,7 @@
<item name="switchStyle">@style/Widget.AppCompat.CompoundButton.Switch</item>
<item name="ratingBarStyle">@style/Widget.AppCompat.RatingBar</item>
+ <item name="seekBarStyle">@style/Widget.AppCompat.SeekBar</item>
<!-- Button styles -->
<item name="buttonStyle">@style/Widget.AppCompat.Button</item>
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
index 490abb4..31d1eb0 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
@@ -54,6 +54,8 @@
boolean mIsFloating;
// true if this activity has no title
boolean mWindowNoTitle;
+ // true if the theme has been read
+ boolean mThemeRead;
private CharSequence mTitle;
@@ -106,13 +108,11 @@
@Override
public void onCreate(Bundle savedInstanceState) {
TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
-
if (!a.hasValue(R.styleable.Theme_windowActionBar)) {
a.recycle();
throw new IllegalStateException(
"You need to use a Theme.AppCompat theme (or descendant) with this activity.");
}
-
if (a.getBoolean(R.styleable.Theme_windowNoTitle, false)) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
} else if (a.getBoolean(R.styleable.Theme_windowActionBar, false)) {
@@ -127,6 +127,7 @@
}
mIsFloating = a.getBoolean(R.styleable.Theme_android_windowIsFloating, false);
a.recycle();
+ mThemeRead = true;
}
// Methods used to create and respond to options menu
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
index 0f306f5..bef6cbf 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
@@ -277,6 +277,12 @@
private void ensureSubDecor() {
if (!mSubDecorInstalled) {
+ if (!mThemeRead) {
+ throw new IllegalStateException("AppCompat can not install it's decor before "
+ + "reading the theme. This is usually caused by calling setContentView() "
+ + "before super.onCreate().");
+ }
+
final LayoutInflater inflater = LayoutInflater.from(mContext);
if (!mWindowNoTitle) {
diff --git a/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java b/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
index 621fc51..95cf83a 100644
--- a/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
+++ b/v7/appcompat/src/android/support/v7/internal/app/AppCompatViewInflater.java
@@ -30,6 +30,7 @@
import android.support.v7.widget.AppCompatMultiAutoCompleteTextView;
import android.support.v7.widget.AppCompatRadioButton;
import android.support.v7.widget.AppCompatRatingBar;
+import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.AppCompatSpinner;
import android.support.v7.internal.widget.ViewUtils;
import android.support.v7.widget.AppCompatTextView;
@@ -101,6 +102,8 @@
return new AppCompatButton(context, attrs);
case "TextView":
return new AppCompatTextView(context, attrs);
+ case "SeekBar":
+ return new AppCompatSeekBar(context, attrs);
}
if (originalContext != context) {
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ButtonBarLayout.java b/v7/appcompat/src/android/support/v7/internal/widget/ButtonBarLayout.java
new file mode 100644
index 0000000..dd0044b
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ButtonBarLayout.java
@@ -0,0 +1,110 @@
+/*
+ * 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.v7.internal.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v7.appcompat.R;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.LinearLayout;
+
+/**
+ * An extension of LinearLayout that automatically switches to vertical
+ * orientation when it can't fit its child views horizontally.
+ *
+ * @hide
+ */
+public class ButtonBarLayout extends LinearLayout {
+
+ /** Whether the current configuration allows stacking. */
+ private boolean mAllowStacking;
+ private int mLastWidthSize = -1;
+
+ public ButtonBarLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ButtonBarLayout);
+ mAllowStacking = ta.getBoolean(R.styleable.ButtonBarLayout_allowStacking, false);
+ ta.recycle();
+ }
+
+ public void setAllowStacking(boolean allowStacking) {
+ if (mAllowStacking != allowStacking) {
+ mAllowStacking = allowStacking;
+ if (!mAllowStacking && getOrientation() == LinearLayout.VERTICAL) {
+ setStacked(false);
+ }
+ requestLayout();
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ if (mAllowStacking) {
+ if (widthSize > mLastWidthSize && isStacked()) {
+ // We're being measured wider this time, try un-stacking.
+ setStacked(false);
+ }
+ mLastWidthSize = widthSize;
+ }
+ boolean needsRemeasure = false;
+ // If we're not stacked, make sure the measure spec is AT_MOST rather
+ // than EXACTLY. This ensures that we'll still get TOO_SMALL so that we
+ // know to stack the buttons.
+ final int initialWidthMeasureSpec;
+ if (!isStacked() && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
+ initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
+ // We'll need to remeasure again to fill excess space.
+ needsRemeasure = true;
+ } else {
+ initialWidthMeasureSpec = widthMeasureSpec;
+ }
+ super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec);
+ if (mAllowStacking && !isStacked()) {
+ final int measuredWidth = getMeasuredWidthAndState();
+ final int measuredWidthState = measuredWidth & MEASURED_STATE_MASK;
+ if (measuredWidthState == MEASURED_STATE_TOO_SMALL) {
+ setStacked(true);
+ // Measure again in the new orientation.
+ needsRemeasure = true;
+ }
+ }
+ if (needsRemeasure) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ private void setStacked(boolean stacked) {
+ setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
+ setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM);
+ final View spacer = findViewById(R.id.spacer);
+ if (spacer != null) {
+ spacer.setVisibility(stacked ? View.GONE : View.INVISIBLE);
+ }
+ // Reverse the child order. This is specific to the Material button
+ // bar's layout XML and will probably not generalize.
+ final int childCount = getChildCount();
+ for (int i = childCount - 2; i >= 0; i--) {
+ bringChildToFront(getChildAt(i));
+ }
+ }
+
+ private boolean isStacked() {
+ return getOrientation() == LinearLayout.VERTICAL;
+ }
+}
\ No newline at end of file
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java b/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
index d926e17..ec85157 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
@@ -191,10 +191,18 @@
DrawableCompat.setTintMode(drawable, tintMode);
}
} else if (resId == R.drawable.abc_cab_background_top_material) {
- return new LayerDrawable(new Drawable[] {
+ return new LayerDrawable(new Drawable[]{
getDrawable(R.drawable.abc_cab_background_internal_bg),
getDrawable(R.drawable.abc_cab_background_top_mtrl_alpha)
});
+ } else if (resId == R.drawable.abc_seekbar_track_material) {
+ LayerDrawable ld = (LayerDrawable) drawable;
+ setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.background),
+ getThemeAttrColor(context, R.attr.colorControlNormal), DEFAULT_MODE);
+ setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.secondaryProgress),
+ getThemeAttrColor(context, R.attr.colorControlNormal), DEFAULT_MODE);
+ setPorterDuffColorFilter(ld.findDrawableByLayerId(android.R.id.progress),
+ getThemeAttrColor(context, R.attr.colorControlActivated), DEFAULT_MODE);
} else {
final boolean usedColorFilter = tintDrawableUsingColorFilter(resId, drawable);
if (!usedColorFilter && failIfNotKnown) {
@@ -307,6 +315,8 @@
tint = getDefaultColorStateList(context);
} else if (arrayContains(TINT_CHECKABLE_BUTTON_LIST, resId)) {
tint = createCheckableButtonColorStateList(context);
+ } else if (resId == R.drawable.abc_seekbar_thumb_material) {
+ tint = createSeekbarThumbColorStateList(context);
}
if (tint != null) {
@@ -541,6 +551,23 @@
return new ColorStateList(states, colors);
}
+ private ColorStateList createSeekbarThumbColorStateList(Context context) {
+ final int[][] states = new int[2][];
+ final int[] colors = new int[2];
+ int i = 0;
+
+ // Disabled state
+ states[i] = ThemeUtils.DISABLED_STATE_SET;
+ colors[i] = getDisabledThemeAttrColor(context, R.attr.colorControlActivated);
+ i++;
+
+ states[i] = ThemeUtils.EMPTY_STATE_SET;
+ colors[i] = getThemeAttrColor(context, R.attr.colorControlActivated);
+ i++;
+
+ return new ColorStateList(states, colors);
+ }
+
private static class ColorFilterLruCache extends LruCache<Integer, PorterDuffColorFilter> {
public ColorFilterLruCache(int maxSize) {
@@ -602,4 +629,8 @@
return filter;
}
+
+ private static void setPorterDuffColorFilter(Drawable d, int color, PorterDuff.Mode mode) {
+ d.setColorFilter(getPorterDuffColorFilter(color, mode == null ? DEFAULT_MODE : mode));
+ }
}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatProgressBarHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatProgressBarHelper.java
new file mode 100644
index 0000000..7fd8f05
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatProgressBarHelper.java
@@ -0,0 +1,151 @@
+/*
+ * 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.v7.widget;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Shader;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ClipDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.RoundRectShape;
+import android.graphics.drawable.shapes.Shape;
+import android.support.v4.graphics.drawable.DrawableWrapper;
+import android.support.v7.appcompat.R;
+import android.support.v7.internal.widget.TintManager;
+import android.support.v7.internal.widget.TintTypedArray;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.CompoundButton;
+import android.widget.ProgressBar;
+
+class AppCompatProgressBarHelper {
+
+ private static final int[] TINT_ATTRS = {
+ android.R.attr.indeterminateDrawable,
+ android.R.attr.progressDrawable
+ };
+
+ private final ProgressBar mView;
+ final TintManager mTintManager;
+
+ private Bitmap mSampleTile;
+
+ AppCompatProgressBarHelper(ProgressBar view, TintManager tintManager) {
+ mView = view;
+ mTintManager = tintManager;
+ }
+
+ void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
+ TintTypedArray a = TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs,
+ TINT_ATTRS, defStyleAttr, 0);
+
+ Drawable drawable = a.getDrawableIfKnown(0);
+ if (drawable != null) {
+ mView.setIndeterminateDrawable(tileifyIndeterminate(drawable));
+ }
+
+ drawable = a.getDrawableIfKnown(1);
+ if (drawable != null) {
+ mView.setProgressDrawable(tileify(drawable, false));
+ }
+
+ a.recycle();
+ }
+
+ /**
+ * Converts a drawable to a tiled version of itself. It will recursively
+ * traverse layer and state list drawables.
+ */
+ private Drawable tileify(Drawable drawable, boolean clip) {
+ if (drawable instanceof DrawableWrapper) {
+ Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
+ if (inner != null) {
+ inner = tileify(inner, clip);
+ ((DrawableWrapper) drawable).setWrappedDrawable(inner);
+ }
+ } else if (drawable instanceof LayerDrawable) {
+ LayerDrawable background = (LayerDrawable) drawable;
+ final int N = background.getNumberOfLayers();
+ Drawable[] outDrawables = new Drawable[N];
+
+ for (int i = 0; i < N; i++) {
+ int id = background.getId(i);
+ outDrawables[i] = tileify(background.getDrawable(i),
+ (id == android.R.id.progress || id == android.R.id.secondaryProgress));
+ }
+ LayerDrawable newBg = new LayerDrawable(outDrawables);
+
+ for (int i = 0; i < N; i++) {
+ newBg.setId(i, background.getId(i));
+ }
+
+ return newBg;
+
+ } else if (drawable instanceof BitmapDrawable) {
+ final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
+ if (mSampleTile == null) {
+ mSampleTile = tileBitmap;
+ }
+
+ final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
+ final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
+ Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
+ shapeDrawable.getPaint().setShader(bitmapShader);
+ return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
+ ClipDrawable.HORIZONTAL) : shapeDrawable;
+ }
+
+ return drawable;
+ }
+
+ /**
+ * Convert a AnimationDrawable for use as a barberpole animation.
+ * Each frame of the animation is wrapped in a ClipDrawable and
+ * given a tiling BitmapShader.
+ */
+ private Drawable tileifyIndeterminate(Drawable drawable) {
+ if (drawable instanceof AnimationDrawable) {
+ AnimationDrawable background = (AnimationDrawable) drawable;
+ final int N = background.getNumberOfFrames();
+ AnimationDrawable newBg = new AnimationDrawable();
+ newBg.setOneShot(background.isOneShot());
+
+ for (int i = 0; i < N; i++) {
+ Drawable frame = tileify(background.getFrame(i), true);
+ frame.setLevel(10000);
+ newBg.addFrame(frame, background.getDuration(i));
+ }
+ newBg.setLevel(10000);
+ drawable = newBg;
+ }
+ return drawable;
+ }
+
+ private Shape getDrawableShape() {
+ final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
+ return new RoundRectShape(roundedCorners, null, null);
+ }
+
+ Bitmap getSampleTime() {
+ return mSampleTile;
+ }
+
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java b/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
index 51811a8..0bc14ab 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
@@ -18,23 +18,10 @@
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Shader;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ClipDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.RoundRectShape;
-import android.graphics.drawable.shapes.Shape;
-import android.support.v4.graphics.drawable.DrawableWrapper;
import android.support.v4.view.ViewCompat;
import android.support.v7.appcompat.R;
import android.support.v7.internal.widget.TintManager;
-import android.support.v7.internal.widget.TintTypedArray;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.widget.RatingBar;
/**
@@ -45,12 +32,8 @@
*/
public class AppCompatRatingBar extends RatingBar {
- private static final int[] TINT_ATTRS = {
- android.R.attr.indeterminateDrawable,
- android.R.attr.progressDrawable
- };
-
- private Bitmap mSampleTile;
+ private AppCompatProgressBarHelper mAppCompatProgressBarHelper;
+ private TintManager mTintManager;
public AppCompatRatingBar(Context context) {
this(context, null);
@@ -63,104 +46,19 @@
public AppCompatRatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- if (TintManager.SHOULD_BE_USED) {
- TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
- TINT_ATTRS, defStyleAttr, 0);
+ mTintManager = TintManager.get(context);
- Drawable drawable = a.getDrawableIfKnown(0);
- if (drawable != null) {
- setIndeterminateDrawable(tileifyIndeterminate(drawable));
- }
-
- drawable = a.getDrawableIfKnown(1);
- if (drawable != null) {
- setProgressDrawable(tileify(drawable, false));
- }
-
- a.recycle();
- }
- }
-
- /**
- * Converts a drawable to a tiled version of itself. It will recursively
- * traverse layer and state list drawables.
- */
- private Drawable tileify(Drawable drawable, boolean clip) {
- if (drawable instanceof DrawableWrapper) {
- Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
- if (inner != null) {
- inner = tileify(inner, clip);
- ((DrawableWrapper) drawable).setWrappedDrawable(inner);
- }
- } else if (drawable instanceof LayerDrawable) {
- LayerDrawable background = (LayerDrawable) drawable;
- final int N = background.getNumberOfLayers();
- Drawable[] outDrawables = new Drawable[N];
-
- for (int i = 0; i < N; i++) {
- int id = background.getId(i);
- outDrawables[i] = tileify(background.getDrawable(i),
- (id == android.R.id.progress || id == android.R.id.secondaryProgress));
- }
- LayerDrawable newBg = new LayerDrawable(outDrawables);
-
- for (int i = 0; i < N; i++) {
- newBg.setId(i, background.getId(i));
- }
-
- return newBg;
-
- } else if (drawable instanceof BitmapDrawable) {
- final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
- if (mSampleTile == null) {
- mSampleTile = tileBitmap;
- }
-
- final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
- final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
- Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
- shapeDrawable.getPaint().setShader(bitmapShader);
- return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
- ClipDrawable.HORIZONTAL) : shapeDrawable;
- }
-
- return drawable;
- }
-
- /**
- * Convert a AnimationDrawable for use as a barberpole animation.
- * Each frame of the animation is wrapped in a ClipDrawable and
- * given a tiling BitmapShader.
- */
- private Drawable tileifyIndeterminate(Drawable drawable) {
- if (drawable instanceof AnimationDrawable) {
- AnimationDrawable background = (AnimationDrawable) drawable;
- final int N = background.getNumberOfFrames();
- AnimationDrawable newBg = new AnimationDrawable();
- newBg.setOneShot(background.isOneShot());
-
- for (int i = 0; i < N; i++) {
- Drawable frame = tileify(background.getFrame(i), true);
- frame.setLevel(10000);
- newBg.addFrame(frame, background.getDuration(i));
- }
- newBg.setLevel(10000);
- drawable = newBg;
- }
- return drawable;
- }
-
- private Shape getDrawableShape() {
- final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
- return new RoundRectShape(roundedCorners, null, null);
+ mAppCompatProgressBarHelper = new AppCompatProgressBarHelper(this, mTintManager);
+ mAppCompatProgressBarHelper.loadFromAttributes(attrs, defStyleAttr);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mSampleTile != null) {
- final int width = mSampleTile.getWidth() * getNumStars();
+ Bitmap sampleTile = mAppCompatProgressBarHelper.getSampleTime();
+ if (sampleTile != null) {
+ final int width = sampleTile.getWidth() * getNumStars();
setMeasuredDimension(ViewCompat.resolveSizeAndState(width, widthMeasureSpec, 0),
getMeasuredHeight());
}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBar.java b/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBar.java
new file mode 100644
index 0000000..86ec881
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBar.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v7.widget;
+
+import android.content.Context;
+import android.support.v7.appcompat.R;
+import android.support.v7.internal.widget.TintManager;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+/**
+ * A {@link SeekBar} which supports compatible features on older version of the platform.
+ *
+ * <p>This will automatically be used when you use {@link SeekBar} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
+ */
+public class AppCompatSeekBar extends SeekBar {
+
+ private AppCompatSeekBarHelper mAppCompatSeekBarHelper;
+ private TintManager mTintManager;
+
+ public AppCompatSeekBar(Context context) {
+ this(context, null);
+ }
+
+ public AppCompatSeekBar(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.seekBarStyle);
+ }
+
+ public AppCompatSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ mTintManager = TintManager.get(context);
+
+ mAppCompatSeekBarHelper = new AppCompatSeekBarHelper(this, mTintManager);
+ mAppCompatSeekBarHelper.loadFromAttributes(attrs, defStyleAttr);
+ }
+
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBarHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBarHelper.java
new file mode 100644
index 0000000..3211942
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatSeekBarHelper.java
@@ -0,0 +1,49 @@
+/*
+ * 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.v7.widget;
+
+import android.graphics.drawable.Drawable;
+import android.support.v7.internal.widget.TintManager;
+import android.support.v7.internal.widget.TintTypedArray;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+class AppCompatSeekBarHelper extends AppCompatProgressBarHelper {
+
+ private static final int[] TINT_ATTRS = {
+ android.R.attr.thumb
+ };
+
+ private final SeekBar mView;
+
+ AppCompatSeekBarHelper(SeekBar view, TintManager tintManager) {
+ super(view, tintManager);
+ mView = view;
+ }
+
+ void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
+ super.loadFromAttributes(attrs, defStyleAttr);
+
+ TintTypedArray a = TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs,
+ TINT_ATTRS, defStyleAttr, 0);
+ Drawable drawable = a.getDrawableIfKnown(0);
+ if (drawable != null) {
+ mView.setThumb(drawable);
+ }
+ a.recycle();
+ }
+}
diff --git a/v7/mediarouter/res/values-az-rAZ/strings.xml b/v7/mediarouter/res/values-az-rAZ/strings.xml
deleted file mode 100644
index 2f3ff74..0000000
--- a/v7/mediarouter/res/values-az-rAZ/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2013 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 xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="mr_system_route_name" msgid="5441529851481176817">"Sistem"</string>
- <string name="mr_user_route_category_name" msgid="7498112907524977311">"Cihazlar"</string>
- <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"İştirakçılar"</string>
- <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Cihaza qoş"</string>
- <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Cihazları axtarır..."</string>
- <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Bağlantını kəs"</string>
- <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Yayımı dayandır"</string>
- <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Marşrut parametrləri"</string>
- <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Göstər"</string>
- <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Fasilə ver"</string>
-</resources>
diff --git a/v7/preference/res/layout/preference_category.xml b/v7/preference/res/layout/preference_category.xml
index 0b58063..258f7da 100644
--- a/v7/preference/res/layout/preference_category.xml
+++ b/v7/preference/res/layout/preference_category.xml
@@ -20,6 +20,6 @@
android:layout_height="wrap_content" >
<TextView
style="?android:attr/listSeparatorTextViewStyle"
- android:id="@+android:id/title"
+ android:id="@android:id/title"
/>
</FrameLayout>
diff --git a/v7/preference/res/layout/preference_information.xml b/v7/preference/res/layout/preference_information.xml
index e3be3820..5815c46 100644
--- a/v7/preference/res/layout/preference_information.xml
+++ b/v7/preference/res/layout/preference_information.xml
@@ -33,14 +33,14 @@
android:layout_marginBottom="6sp"
android:layout_weight="1">
- <TextView android:id="@+android:id/title"
+ <TextView android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="?android:attr/textColorSecondary" />
- <TextView android:id="@+android:id/summary"
+ <TextView android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
@@ -52,7 +52,7 @@
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
- <LinearLayout android:id="@+android:id/widget_frame"
+ <LinearLayout android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"