Merge "Deprecate and cleanup usage of KeyEventCompat."
diff --git a/README.md b/README.md
index 46cb691..098a0c6 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,8 @@
We **are not** currently accepting new modules, features, or behavior changes.
## Checking Out the Code
+**NOTE: You will need to use Linux or Mac OS. Building under Windows is not currently supported.**
+
Follow the [“Downloading the Source”](https://source.android.com/source/downloading.html) guide to install and set up `repo` tool, but instead of running the listed `repo` commands to initialize the repository, run the folowing:
repo init -u https://android.googlesource.com/platform/manifest -b ub-supportlib-master
diff --git a/api/25.2.0.txt b/api/25.3.0.txt
similarity index 97%
rename from api/25.2.0.txt
rename to api/25.3.0.txt
index 6709b97..917fd00 100644
--- a/api/25.2.0.txt
+++ b/api/25.3.0.txt
@@ -354,11 +354,18 @@
method public android.content.res.ColorStateList getItemTextColor();
method public int getMaxItemCount();
method public android.view.Menu getMenu();
+ method public int getSelectedItemId();
method public void inflateMenu(int);
method public void setItemBackgroundResource(int);
method public void setItemIconTintList(android.content.res.ColorStateList);
method public void setItemTextColor(android.content.res.ColorStateList);
+ method public void setOnNavigationItemReselectedListener(android.support.design.widget.BottomNavigationView.OnNavigationItemReselectedListener);
method public void setOnNavigationItemSelectedListener(android.support.design.widget.BottomNavigationView.OnNavigationItemSelectedListener);
+ method public void setSelectedItemId(int);
+ }
+
+ public static abstract interface BottomNavigationView.OnNavigationItemReselectedListener {
+ method public abstract void onNavigationItemReselected(android.view.MenuItem);
}
public static abstract interface BottomNavigationView.OnNavigationItemSelectedListener {
@@ -1707,6 +1714,7 @@
method protected java.lang.Object createEntranceTransition();
method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
method public android.support.v17.leanback.widget.BaseOnItemViewClickedListener getOnItemViewClickedListener();
+ method public android.support.v17.leanback.widget.DetailsParallax getParallax();
method public android.support.v17.leanback.app.RowsFragment getRowsFragment();
method protected deprecated android.view.View inflateTitle(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
method protected void onEntranceTransitionEnd();
@@ -1724,11 +1732,30 @@
method protected void setupPresenter(android.support.v17.leanback.widget.Presenter);
}
+ public class DetailsFragmentBackgroundController {
+ ctor public DetailsFragmentBackgroundController(android.support.v17.leanback.app.DetailsFragment);
+ method public void enableParallax();
+ method public void enableParallax(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.support.v17.leanback.widget.ParallaxTarget.PropertyValuesHolderTarget);
+ method public final android.app.Fragment findOrCreateVideoFragment();
+ method public final android.graphics.drawable.Drawable getBottomDrawable();
+ method public final android.graphics.Bitmap getCoverBitmap();
+ method public final android.graphics.drawable.Drawable getCoverDrawable();
+ method public final int getParallaxDrawableMaxOffset();
+ method public final int getSolidColor();
+ method public android.support.v17.leanback.media.PlaybackGlueHost onCreateGlueHost();
+ method public android.app.Fragment onCreateVideoFragment();
+ method public final void setCoverBitmap(android.graphics.Bitmap);
+ method public final void setParallaxDrawableMaxOffset(int);
+ method public final void setSolidColor(int);
+ method public void setupVideoPlayback(android.support.v17.leanback.media.PlaybackGlue);
+ }
+
public class DetailsSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
ctor public DetailsSupportFragment();
method protected java.lang.Object createEntranceTransition();
method public android.support.v17.leanback.widget.ObjectAdapter getAdapter();
method public android.support.v17.leanback.widget.BaseOnItemViewClickedListener getOnItemViewClickedListener();
+ method public android.support.v17.leanback.widget.DetailsParallax getParallax();
method public android.support.v17.leanback.app.RowsSupportFragment getRowsSupportFragment();
method protected deprecated android.view.View inflateTitle(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
method protected void onEntranceTransitionEnd();
@@ -1746,6 +1773,24 @@
method protected void setupPresenter(android.support.v17.leanback.widget.Presenter);
}
+ public class DetailsSupportFragmentBackgroundController {
+ ctor public DetailsSupportFragmentBackgroundController(android.support.v17.leanback.app.DetailsSupportFragment);
+ method public void enableParallax();
+ method public void enableParallax(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.support.v17.leanback.widget.ParallaxTarget.PropertyValuesHolderTarget);
+ method public final android.support.v4.app.Fragment findOrCreateVideoSupportFragment();
+ method public final android.graphics.drawable.Drawable getBottomDrawable();
+ method public final android.graphics.Bitmap getCoverBitmap();
+ method public final android.graphics.drawable.Drawable getCoverDrawable();
+ method public final int getParallaxDrawableMaxOffset();
+ method public final int getSolidColor();
+ method public android.support.v17.leanback.media.PlaybackGlueHost onCreateGlueHost();
+ method public android.support.v4.app.Fragment onCreateVideoSupportFragment();
+ method public final void setCoverBitmap(android.graphics.Bitmap);
+ method public final void setParallaxDrawableMaxOffset(int);
+ method public final void setSolidColor(int);
+ method public void setupVideoPlayback(android.support.v17.leanback.media.PlaybackGlue);
+ }
+
public class ErrorFragment extends android.support.v17.leanback.app.BrandedFragment {
ctor public ErrorFragment();
method public android.graphics.drawable.Drawable getBackgroundDrawable();
@@ -2040,6 +2085,7 @@
method public void setFadingEnabled(boolean);
method public void setHostCallback(android.support.v17.leanback.media.PlaybackGlueHost.HostCallback);
method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.BaseOnItemViewSelectedListener);
method public final void setOnKeyInterceptListener(android.view.View.OnKeyListener);
method public void setOnPlaybackItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
method public void setPlaybackRow(android.support.v17.leanback.widget.Row);
@@ -2124,6 +2170,7 @@
method public void setFadingEnabled(boolean);
method public void setHostCallback(android.support.v17.leanback.media.PlaybackGlueHost.HostCallback);
method public void setOnItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
+ method public void setOnItemViewSelectedListener(android.support.v17.leanback.widget.BaseOnItemViewSelectedListener);
method public final void setOnKeyInterceptListener(android.view.View.OnKeyListener);
method public void setOnPlaybackItemViewClickedListener(android.support.v17.leanback.widget.BaseOnItemViewClickedListener);
method public void setPlaybackRow(android.support.v17.leanback.widget.Row);
@@ -2290,6 +2337,28 @@
method public void setSelectedPosition(int);
}
+ public class VideoFragment extends android.support.v17.leanback.app.PlaybackFragment {
+ ctor public VideoFragment();
+ method public android.view.SurfaceView getSurfaceView();
+ method public void setSurfaceHolderCallback(android.view.SurfaceHolder.Callback);
+ }
+
+ public class VideoFragmentGlueHost extends android.support.v17.leanback.app.PlaybackFragmentGlueHost implements android.support.v17.leanback.media.SurfaceHolderGlueHost {
+ ctor public VideoFragmentGlueHost(android.support.v17.leanback.app.VideoFragment);
+ method public void setSurfaceHolderCallback(android.view.SurfaceHolder.Callback);
+ }
+
+ public class VideoSupportFragment extends android.support.v17.leanback.app.PlaybackSupportFragment {
+ ctor public VideoSupportFragment();
+ method public android.view.SurfaceView getSurfaceView();
+ method public void setSurfaceHolderCallback(android.view.SurfaceHolder.Callback);
+ }
+
+ public class VideoSupportFragmentGlueHost extends android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost implements android.support.v17.leanback.media.SurfaceHolderGlueHost {
+ ctor public VideoSupportFragmentGlueHost(android.support.v17.leanback.app.VideoSupportFragment);
+ method public void setSurfaceHolderCallback(android.view.SurfaceHolder.Callback);
+ }
+
}
package android.support.v17.leanback.database {
@@ -2305,6 +2374,26 @@
package android.support.v17.leanback.graphics {
+ public class BoundsRule {
+ ctor public BoundsRule();
+ ctor public BoundsRule(android.support.v17.leanback.graphics.BoundsRule);
+ method public static android.support.v17.leanback.graphics.BoundsRule.ValueRule absoluteValue(int);
+ method public void calculateBounds(android.graphics.Rect, android.graphics.Rect);
+ method public static android.support.v17.leanback.graphics.BoundsRule.ValueRule inheritFromParent(float);
+ method public static android.support.v17.leanback.graphics.BoundsRule.ValueRule inheritFromParentWithOffset(float, int);
+ field public android.support.v17.leanback.graphics.BoundsRule.ValueRule bottom;
+ field public android.support.v17.leanback.graphics.BoundsRule.ValueRule left;
+ field public android.support.v17.leanback.graphics.BoundsRule.ValueRule right;
+ field public android.support.v17.leanback.graphics.BoundsRule.ValueRule top;
+ }
+
+ public static final class BoundsRule.ValueRule {
+ method public int getAbsoluteValue();
+ method public float getFraction();
+ method public void setAbsoluteValue(int);
+ method public void setFraction(float);
+ }
+
public final class ColorFilterCache {
method public static android.support.v17.leanback.graphics.ColorFilterCache getColorFilterCache(int);
method public android.graphics.ColorFilter getFilterForLevel(float);
@@ -2331,6 +2420,54 @@
method public void setActiveLevel(float);
}
+ public class CompositeDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ ctor public CompositeDrawable();
+ method public void addChildDrawable(android.graphics.drawable.Drawable);
+ method public void draw(android.graphics.Canvas);
+ method public android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable getChildAt(int);
+ method public int getChildCount();
+ method public android.graphics.drawable.Drawable getDrawable(int);
+ method public int getOpacity();
+ method public void invalidateDrawable(android.graphics.drawable.Drawable);
+ method public void removeChild(int);
+ method public void removeDrawable(android.graphics.drawable.Drawable);
+ method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+ method public void setAlpha(int);
+ method public void setChildDrawableAt(int, android.graphics.drawable.Drawable);
+ method public void setColorFilter(android.graphics.ColorFilter);
+ method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+ }
+
+ public static final class CompositeDrawable.ChildDrawable {
+ ctor public CompositeDrawable.ChildDrawable(android.graphics.drawable.Drawable, android.support.v17.leanback.graphics.CompositeDrawable);
+ method public android.support.v17.leanback.graphics.BoundsRule getBoundsRule();
+ method public android.graphics.drawable.Drawable getDrawable();
+ method public void recomputeBounds();
+ field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Integer> BOTTOM_ABSOLUTE;
+ field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Float> BOTTOM_FRACTION;
+ field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Integer> LEFT_ABSOLUTE;
+ field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Float> LEFT_FRACTION;
+ field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Integer> RIGHT_ABSOLUTE;
+ field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Float> RIGHT_FRACTION;
+ field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Integer> TOP_ABSOLUTE;
+ field public static final android.util.Property<android.support.v17.leanback.graphics.CompositeDrawable.ChildDrawable, java.lang.Float> TOP_FRACTION;
+ }
+
+ public class FitWidthBitmapDrawable extends android.graphics.drawable.Drawable {
+ ctor public FitWidthBitmapDrawable();
+ method public void draw(android.graphics.Canvas);
+ method public android.graphics.Bitmap getBitmap();
+ method public int getOpacity();
+ method public android.graphics.Rect getSource();
+ method public int getVerticalOffset();
+ method public void setAlpha(int);
+ method public void setBitmap(android.graphics.Bitmap);
+ method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setSource(android.graphics.Rect);
+ method public void setVerticalOffset(int);
+ field public static final android.util.Property<android.support.v17.leanback.graphics.FitWidthBitmapDrawable, java.lang.Integer> PROPERTY_VERTICAL_OFFSET;
+ }
+
}
package android.support.v17.leanback.media {
@@ -2727,6 +2864,12 @@
field public final android.support.v17.leanback.widget.Presenter.ViewHolder mDetailsDescriptionViewHolder;
}
+ public class DetailsParallax extends android.support.v17.leanback.widget.RecyclerViewParallax {
+ ctor public DetailsParallax();
+ method public android.support.v17.leanback.widget.Parallax.IntProperty getOverviewRowBottom();
+ method public android.support.v17.leanback.widget.Parallax.IntProperty getOverviewRowTop();
+ }
+
public class DividerPresenter extends android.support.v17.leanback.widget.Presenter {
ctor public DividerPresenter();
method public void onBindViewHolder(android.support.v17.leanback.widget.Presenter.ViewHolder, java.lang.Object);
@@ -3347,6 +3490,115 @@
method public final boolean isRenderedAsRowView();
}
+ public abstract class Parallax<PropertyT extends android.util.Property> {
+ ctor public Parallax();
+ method public void addEffect(android.support.v17.leanback.widget.ParallaxEffect);
+ method public android.support.v17.leanback.widget.ParallaxEffect addEffect(android.support.v17.leanback.widget.Parallax.IntPropertyMarkerValue...);
+ method public android.support.v17.leanback.widget.ParallaxEffect addEffect(android.support.v17.leanback.widget.Parallax.FloatPropertyMarkerValue...);
+ method public abstract PropertyT addProperty(java.lang.String);
+ method public abstract PropertyT createProperty(java.lang.String, int);
+ method public java.util.List<android.support.v17.leanback.widget.ParallaxEffect> getEffects();
+ method public final java.util.List<PropertyT> getProperties();
+ method public void removeAllEffects();
+ method public void removeEffect(android.support.v17.leanback.widget.ParallaxEffect);
+ method public void updateValues();
+ method public abstract void verifyProperties() throws java.lang.IllegalStateException;
+ }
+
+ public static abstract class Parallax.FloatParallax<FloatPropertyT extends android.support.v17.leanback.widget.Parallax.FloatProperty> extends android.support.v17.leanback.widget.Parallax {
+ ctor public Parallax.FloatParallax();
+ method public final FloatPropertyT addProperty(java.lang.String);
+ method public abstract float getMaxValue();
+ method public final float getPropertyValue(int);
+ method public final void setPropertyValue(int, float);
+ method public final void verifyProperties() throws java.lang.IllegalStateException;
+ }
+
+ public static class Parallax.FloatProperty extends android.util.Property {
+ ctor public Parallax.FloatProperty(java.lang.String, int);
+ method public final android.support.v17.leanback.widget.Parallax.FloatPropertyMarkerValue at(float, float);
+ method public final android.support.v17.leanback.widget.Parallax.FloatPropertyMarkerValue atAbsolute(float);
+ method public final android.support.v17.leanback.widget.Parallax.FloatPropertyMarkerValue atFraction(float);
+ method public final java.lang.Float get(android.support.v17.leanback.widget.Parallax.FloatParallax);
+ method public final int getIndex();
+ method public final void set(android.support.v17.leanback.widget.Parallax.FloatParallax, java.lang.Float);
+ field public static final float UNKNOWN_AFTER = 3.4028235E38f;
+ field public static final float UNKNOWN_BEFORE = -3.4028235E38f;
+ }
+
+ public static class Parallax.FloatPropertyMarkerValue extends android.support.v17.leanback.widget.Parallax.PropertyMarkerValue {
+ ctor public Parallax.FloatPropertyMarkerValue(android.support.v17.leanback.widget.Parallax.FloatProperty, float);
+ ctor public Parallax.FloatPropertyMarkerValue(android.support.v17.leanback.widget.Parallax.FloatProperty, float, float);
+ method public final float getMarkerValue(android.support.v17.leanback.widget.Parallax.FloatParallax);
+ }
+
+ public static abstract class Parallax.IntParallax<IntPropertyT extends android.support.v17.leanback.widget.Parallax.IntProperty> extends android.support.v17.leanback.widget.Parallax {
+ ctor public Parallax.IntParallax();
+ method public final IntPropertyT addProperty(java.lang.String);
+ method public abstract int getMaxValue();
+ method public final int getPropertyValue(int);
+ method public final void setPropertyValue(int, int);
+ method public final void verifyProperties() throws java.lang.IllegalStateException;
+ }
+
+ public static class Parallax.IntProperty extends android.util.Property {
+ ctor public Parallax.IntProperty(java.lang.String, int);
+ method public final android.support.v17.leanback.widget.Parallax.IntPropertyMarkerValue at(int, float);
+ method public final android.support.v17.leanback.widget.Parallax.IntPropertyMarkerValue atAbsolute(int);
+ method public final android.support.v17.leanback.widget.Parallax.IntPropertyMarkerValue atFraction(float);
+ method public final java.lang.Integer get(android.support.v17.leanback.widget.Parallax.IntParallax);
+ method public final int getIndex();
+ method public final void set(android.support.v17.leanback.widget.Parallax.IntParallax, java.lang.Integer);
+ field public static final int UNKNOWN_AFTER = 2147483647; // 0x7fffffff
+ field public static final int UNKNOWN_BEFORE = -2147483648; // 0x80000000
+ }
+
+ public static class Parallax.IntPropertyMarkerValue extends android.support.v17.leanback.widget.Parallax.PropertyMarkerValue {
+ ctor public Parallax.IntPropertyMarkerValue(android.support.v17.leanback.widget.Parallax.IntProperty, int);
+ ctor public Parallax.IntPropertyMarkerValue(android.support.v17.leanback.widget.Parallax.IntProperty, int, float);
+ method public final int getMarkerValue(android.support.v17.leanback.widget.Parallax.IntParallax);
+ }
+
+ public static class Parallax.PropertyMarkerValue<PropertyT> {
+ ctor public Parallax.PropertyMarkerValue(PropertyT);
+ method public PropertyT getProperty();
+ }
+
+ public abstract class ParallaxEffect<ParallaxEffectT extends android.support.v17.leanback.widget.ParallaxEffect, PropertyMarkerValueT extends android.support.v17.leanback.widget.Parallax.PropertyMarkerValue> {
+ ctor public ParallaxEffect();
+ method public final void addTarget(android.support.v17.leanback.widget.ParallaxTarget);
+ method protected abstract float calculateFraction(android.support.v17.leanback.widget.Parallax);
+ method public final java.util.List<PropertyMarkerValueT> getPropertyRanges();
+ method public final java.util.List<android.support.v17.leanback.widget.ParallaxTarget> getTargets();
+ method public final void performMapping(android.support.v17.leanback.widget.Parallax);
+ method public final void removeTarget(android.support.v17.leanback.widget.ParallaxTarget);
+ method public final void setPropertyRanges(PropertyMarkerValueT...);
+ method public final android.support.v17.leanback.widget.ParallaxEffect target(android.support.v17.leanback.widget.ParallaxTarget);
+ method public final android.support.v17.leanback.widget.ParallaxEffect target(java.lang.Object, android.animation.PropertyValuesHolder);
+ }
+
+ public static final class ParallaxEffect.FloatEffect extends android.support.v17.leanback.widget.ParallaxEffect {
+ ctor public ParallaxEffect.FloatEffect();
+ method protected float calculateFraction(android.support.v17.leanback.widget.Parallax);
+ }
+
+ public static final class ParallaxEffect.IntEffect extends android.support.v17.leanback.widget.ParallaxEffect {
+ ctor public ParallaxEffect.IntEffect();
+ method protected float calculateFraction(android.support.v17.leanback.widget.Parallax);
+ }
+
+ public abstract class ParallaxTarget {
+ ctor public ParallaxTarget();
+ method public abstract float getFraction();
+ method public abstract void update(float);
+ }
+
+ public static final class ParallaxTarget.PropertyValuesHolderTarget extends android.support.v17.leanback.widget.ParallaxTarget {
+ ctor public ParallaxTarget.PropertyValuesHolderTarget(java.lang.Object, android.animation.PropertyValuesHolder);
+ method public float getFraction();
+ method public void update(float);
+ }
+
public class PlaybackControlsRow extends android.support.v17.leanback.widget.Row {
ctor public PlaybackControlsRow(java.lang.Object);
ctor public PlaybackControlsRow();
@@ -3536,6 +3788,25 @@
method public void unselect();
}
+ public class RecyclerViewParallax extends android.support.v17.leanback.widget.Parallax.IntParallax {
+ ctor public RecyclerViewParallax();
+ method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty createProperty(java.lang.String, int);
+ method public int getMaxValue();
+ method public android.support.v7.widget.RecyclerView getRecyclerView();
+ method public void setRecyclerView(android.support.v7.widget.RecyclerView);
+ }
+
+ public static final class RecyclerViewParallax.ChildPositionProperty extends android.support.v17.leanback.widget.Parallax.IntProperty {
+ method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty adapterPosition(int);
+ method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty fraction(float);
+ method public int getAdapterPosition();
+ method public float getFraction();
+ method public int getOffset();
+ method public int getViewId();
+ method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty offset(int);
+ method public android.support.v17.leanback.widget.RecyclerViewParallax.ChildPositionProperty viewId(int);
+ }
+
public class Row {
ctor public Row(long, android.support.v17.leanback.widget.HeaderItem);
ctor public Row(android.support.v17.leanback.widget.HeaderItem);
@@ -5264,6 +5535,10 @@
method public static int setAlphaComponent(int, int);
}
+ public final class PaintCompat {
+ method public static boolean hasGlyph(android.graphics.Paint, java.lang.String);
+ }
+
}
package android.support.v4.graphics.drawable {
diff --git a/api/current.txt b/api/current.txt
index f9cbc2f..13200de 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -904,7 +904,8 @@
method public java.lang.String getAttribute(java.lang.String);
method public double getAttributeDouble(java.lang.String, double);
method public int getAttributeInt(java.lang.String, int);
- method public boolean getLatLong(float[]);
+ method public deprecated boolean getLatLong(float[]);
+ method public double[] getLatLong();
method public byte[] getThumbnail();
method public android.graphics.Bitmap getThumbnailBitmap();
method public byte[] getThumbnailBytes();
@@ -913,6 +914,7 @@
method public boolean isThumbnailCompressed();
method public void saveAttributes() throws java.io.IOException;
method public void setAttribute(java.lang.String, java.lang.String);
+ method public void setLatLong(double, double);
field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
field public static final int ORIENTATION_NORMAL = 1; // 0x1
@@ -5908,17 +5910,17 @@
}
public final class IntentCompat {
- method public static android.content.Intent makeMainActivity(android.content.ComponentName);
+ method public static deprecated android.content.Intent makeMainActivity(android.content.ComponentName);
method public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String);
- method public static android.content.Intent makeRestartActivityTask(android.content.ComponentName);
- field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
- field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
+ method public static deprecated android.content.Intent makeRestartActivityTask(android.content.ComponentName);
+ field public static final deprecated java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
+ field public static final deprecated java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
field public static final java.lang.String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
- field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
- field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
+ field public static final deprecated java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
+ field public static final deprecated java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
- field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000
- field public static final int FLAG_ACTIVITY_TASK_ON_HOME = 16384; // 0x4000
+ field public static final deprecated int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000
+ field public static final deprecated int FLAG_ACTIVITY_TASK_ON_HOME = 16384; // 0x4000
}
public class Loader<D> {
@@ -6821,15 +6823,15 @@
}
public final class TrafficStatsCompat {
- method public static void clearThreadStatsTag();
- method public static int getThreadStatsTag();
- method public static void incrementOperationCount(int);
- method public static void incrementOperationCount(int, int);
- method public static void setThreadStatsTag(int);
+ method public static deprecated void clearThreadStatsTag();
+ method public static deprecated int getThreadStatsTag();
+ method public static deprecated void incrementOperationCount(int);
+ method public static deprecated void incrementOperationCount(int, int);
+ method public static deprecated void setThreadStatsTag(int);
method public static void tagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
- method public static void tagSocket(java.net.Socket) throws java.net.SocketException;
+ method public static deprecated void tagSocket(java.net.Socket) throws java.net.SocketException;
method public static void untagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
- method public static void untagSocket(java.net.Socket) throws java.net.SocketException;
+ method public static deprecated void untagSocket(java.net.Socket) throws java.net.SocketException;
}
}
@@ -8621,26 +8623,26 @@
method public void startScroll(int, int, int, int, int);
}
- public final class SearchViewCompat {
- method public static java.lang.CharSequence getQuery(android.view.View);
- method public static boolean isIconified(android.view.View);
- method public static boolean isQueryRefinementEnabled(android.view.View);
- method public static boolean isSubmitButtonEnabled(android.view.View);
- method public static android.view.View newSearchView(android.content.Context);
- method public static void setIconified(android.view.View, boolean);
- method public static void setImeOptions(android.view.View, int);
- method public static void setInputType(android.view.View, int);
- method public static void setMaxWidth(android.view.View, int);
- method public static void setOnCloseListener(android.view.View, android.support.v4.widget.SearchViewCompat.OnCloseListener);
- method public static void setOnQueryTextListener(android.view.View, android.support.v4.widget.SearchViewCompat.OnQueryTextListener);
- method public static void setQuery(android.view.View, java.lang.CharSequence, boolean);
- method public static void setQueryHint(android.view.View, java.lang.CharSequence);
- method public static void setQueryRefinementEnabled(android.view.View, boolean);
- method public static void setSearchableInfo(android.view.View, android.content.ComponentName);
- method public static void setSubmitButtonEnabled(android.view.View, boolean);
+ public final deprecated class SearchViewCompat {
+ method public static deprecated java.lang.CharSequence getQuery(android.view.View);
+ method public static deprecated boolean isIconified(android.view.View);
+ method public static deprecated boolean isQueryRefinementEnabled(android.view.View);
+ method public static deprecated boolean isSubmitButtonEnabled(android.view.View);
+ method public static deprecated android.view.View newSearchView(android.content.Context);
+ method public static deprecated void setIconified(android.view.View, boolean);
+ method public static deprecated void setImeOptions(android.view.View, int);
+ method public static deprecated void setInputType(android.view.View, int);
+ method public static deprecated void setMaxWidth(android.view.View, int);
+ method public static deprecated void setOnCloseListener(android.view.View, android.support.v4.widget.SearchViewCompat.OnCloseListener);
+ method public static deprecated void setOnQueryTextListener(android.view.View, android.support.v4.widget.SearchViewCompat.OnQueryTextListener);
+ method public static deprecated void setQuery(android.view.View, java.lang.CharSequence, boolean);
+ method public static deprecated void setQueryHint(android.view.View, java.lang.CharSequence);
+ method public static deprecated void setQueryRefinementEnabled(android.view.View, boolean);
+ method public static deprecated void setSearchableInfo(android.view.View, android.content.ComponentName);
+ method public static deprecated void setSubmitButtonEnabled(android.view.View, boolean);
}
- public static abstract interface SearchViewCompat.OnCloseListener {
+ public static abstract deprecated interface SearchViewCompat.OnCloseListener {
method public abstract boolean onClose();
}
@@ -8649,7 +8651,7 @@
method public boolean onClose();
}
- public static abstract interface SearchViewCompat.OnQueryTextListener {
+ public static abstract deprecated interface SearchViewCompat.OnQueryTextListener {
method public abstract boolean onQueryTextChange(java.lang.String);
method public abstract boolean onQueryTextSubmit(java.lang.String);
}
@@ -11118,7 +11120,6 @@
method public boolean isLayoutHierarchical(android.support.v7.widget.RecyclerView.Recycler, android.support.v7.widget.RecyclerView.State);
method public boolean isMeasurementCacheEnabled();
method public boolean isSmoothScrolling();
- method public boolean isViewPartiallyVisible(android.view.View, boolean, boolean);
method public void layoutDecorated(android.view.View, int, int, int, int);
method public void layoutDecoratedWithMargins(android.view.View, int, int, int, int);
method public void measureChild(android.view.View, int, int);
@@ -11163,7 +11164,6 @@
method public void removeView(android.view.View);
method public void removeViewAt(int);
method public boolean requestChildRectangleOnScreen(android.support.v7.widget.RecyclerView, android.view.View, android.graphics.Rect, boolean);
- method public boolean requestChildRectangleOnScreen(android.support.v7.widget.RecyclerView, android.view.View, android.graphics.Rect, boolean, boolean);
method public void requestLayout();
method public void requestSimpleAnimationsInNextLayout();
method public int scrollHorizontallyBy(int, android.support.v7.widget.RecyclerView.Recycler, android.support.v7.widget.RecyclerView.State);
diff --git a/compat/api23/android/support/v4/text/ICUCompatApi23.java b/compat/api23/android/support/v4/text/ICUCompatApi21.java
similarity index 88%
rename from compat/api23/android/support/v4/text/ICUCompatApi23.java
rename to compat/api23/android/support/v4/text/ICUCompatApi21.java
index 0088f95..086a7cd 100644
--- a/compat/api23/android/support/v4/text/ICUCompatApi23.java
+++ b/compat/api23/android/support/v4/text/ICUCompatApi21.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package android.support.v4.text;
@@ -23,16 +23,16 @@
import java.lang.reflect.Method;
import java.util.Locale;
-@RequiresApi(23)
-class ICUCompatApi23 {
+@RequiresApi(21)
+class ICUCompatApi21 {
- private static final String TAG = "ICUCompatIcs";
+ private static final String TAG = "ICUCompatApi21";
private static Method sAddLikelySubtagsMethod;
static {
try {
- // This class should always exist on API-23 since it's CTS tested.
+ // This class should always exist on API-21 since it's CTS tested.
final Class<?> clazz = Class.forName("libcore.icu.ICU");
sAddLikelySubtagsMethod = clazz.getMethod("addLikelySubtags",
new Class[]{ Locale.class });
@@ -41,7 +41,6 @@
}
}
-
public static String maximizeAndGetScript(Locale locale) {
try {
final Object[] args = new Object[] { locale };
diff --git a/compat/api24/android/support/v4/net/ConnectivityManagerCompatApi24.java b/compat/api24/android/support/v4/net/ConnectivityManagerCompatApi24.java
deleted file mode 100644
index c63062d..0000000
--- a/compat/api24/android/support/v4/net/ConnectivityManagerCompatApi24.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2016 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.v4.net;
-
-import android.net.ConnectivityManager;
-import android.support.annotation.RequiresApi;
-
-/**
- * Implementation of ConnectivityManagerCompat that can use API 24 APIs.
- */
-@RequiresApi(24)
-class ConnectivityManagerCompatApi24 {
- public static int getRestrictBackgroundStatus(ConnectivityManager cm) {
- return cm.getRestrictBackgroundStatus();
- }
-}
diff --git a/compat/api24/android/support/v4/net/TrafficStatsCompatApi24.java b/compat/api24/android/support/v4/net/TrafficStatsCompatApi24.java
deleted file mode 100644
index 7a9e248..0000000
--- a/compat/api24/android/support/v4/net/TrafficStatsCompatApi24.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.v4.net;
-
-import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.net.TrafficStats;
-import android.support.annotation.RequiresApi;
-import android.support.annotation.RestrictTo;
-
-import java.net.DatagramSocket;
-import java.net.SocketException;
-
-/** @hide */
-@RequiresApi(24)
-@RestrictTo(LIBRARY_GROUP)
-public class TrafficStatsCompatApi24 {
- public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
- TrafficStats.tagDatagramSocket(socket);
- }
-
- public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
- TrafficStats.untagDatagramSocket(socket);
- }
-}
diff --git a/compat/honeycomb/android/support/v4/content/IntentCompatHoneycomb.java b/compat/honeycomb/android/support/v4/content/IntentCompatHoneycomb.java
deleted file mode 100644
index d3243d6..0000000
--- a/compat/honeycomb/android/support/v4/content/IntentCompatHoneycomb.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.content;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.support.annotation.RequiresApi;
-
-@RequiresApi(11)
-class IntentCompatHoneycomb {
- public static Intent makeMainActivity(ComponentName mainActivity) {
- return Intent.makeMainActivity(mainActivity);
- }
-
- public static Intent makeRestartActivityTask(ComponentName mainActivity) {
- return Intent.makeRestartActivityTask(mainActivity);
- }
-}
diff --git a/compat/honeycomb/android/support/v4/widget/SearchViewCompatHoneycomb.java b/compat/honeycomb/android/support/v4/widget/SearchViewCompatHoneycomb.java
deleted file mode 100644
index f44e398..0000000
--- a/compat/honeycomb/android/support/v4/widget/SearchViewCompatHoneycomb.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2011 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.v4.widget;
-
-import android.app.SearchManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.support.annotation.RequiresApi;
-import android.view.View;
-import android.widget.SearchView;
-import android.widget.SearchView.OnCloseListener;
-import android.widget.SearchView.OnQueryTextListener;
-
-/**
- * Implementation of SearchView compatibility that can call Honeycomb APIs.
- */
-
-@RequiresApi(11)
-class SearchViewCompatHoneycomb {
-
- public static void checkIfLegalArg(View searchView) {
- if (searchView == null) {
- throw new IllegalArgumentException("searchView must be non-null");
- }
- if (!(searchView instanceof SearchView)) {
- throw new IllegalArgumentException("searchView must be an instance of" +
- "android.widget.SearchView");
- }
- }
-
- interface OnQueryTextListenerCompatBridge {
- boolean onQueryTextSubmit(String query);
- boolean onQueryTextChange(String newText);
- }
-
- interface OnCloseListenerCompatBridge {
- boolean onClose();
- }
-
- public static View newSearchView(Context context) {
- return new SearchView(context);
- }
-
- public static void setSearchableInfo(View searchView, ComponentName searchableComponent) {
- SearchView sv = ((SearchView) searchView);
- SearchManager searchManager = (SearchManager)
- sv.getContext().getSystemService(Context.SEARCH_SERVICE);
- sv.setSearchableInfo(searchManager.getSearchableInfo(searchableComponent));
- }
-
- public static Object newOnQueryTextListener(final OnQueryTextListenerCompatBridge listener) {
- return new OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String query) {
- return listener.onQueryTextSubmit(query);
- }
-
- @Override
- public boolean onQueryTextChange(String newText) {
- return listener.onQueryTextChange(newText);
- }
- };
- }
-
- public static void setOnQueryTextListener(View searchView, Object listener) {
- ((SearchView) searchView).setOnQueryTextListener((OnQueryTextListener) listener);
- }
-
- public static Object newOnCloseListener(final OnCloseListenerCompatBridge listener) {
- return new OnCloseListener() {
- @Override
- public boolean onClose() {
- return listener.onClose();
- }
- };
- }
-
- public static void setOnCloseListener(View searchView, Object listener) {
- ((SearchView) searchView).setOnCloseListener((OnCloseListener) listener);
- }
-
- public static CharSequence getQuery(View searchView) {
- return ((SearchView) searchView).getQuery();
- }
-
- public static void setQuery(View searchView, CharSequence query, boolean submit) {
- ((SearchView) searchView).setQuery(query, submit);
- }
-
- public static void setQueryHint(View searchView, CharSequence hint) {
- ((SearchView) searchView).setQueryHint(hint);
- }
-
- public static void setIconified(View searchView, boolean iconify) {
- ((SearchView) searchView).setIconified(iconify);
- }
-
- public static boolean isIconified(View searchView) {
- return ((SearchView) searchView).isIconified();
- }
-
- public static void setSubmitButtonEnabled(View searchView, boolean enabled) {
- ((SearchView) searchView).setSubmitButtonEnabled(enabled);
- }
-
- public static boolean isSubmitButtonEnabled(View searchView) {
- return ((SearchView) searchView).isSubmitButtonEnabled();
- }
-
- public static void setQueryRefinementEnabled(View searchView, boolean enable) {
- ((SearchView) searchView).setQueryRefinementEnabled(enable);
- }
-
- public static boolean isQueryRefinementEnabled(View searchView) {
- return ((SearchView) searchView).isQueryRefinementEnabled();
- }
-
- public static void setMaxWidth(View searchView, int maxpixels) {
- ((SearchView) searchView).setMaxWidth(maxpixels);
- }
-}
diff --git a/compat/honeycomb_mr2/android/support/v4/net/ConnectivityManagerCompatHoneycombMR2.java b/compat/honeycomb_mr2/android/support/v4/net/ConnectivityManagerCompatHoneycombMR2.java
deleted file mode 100644
index 5a93799..0000000
--- a/compat/honeycomb_mr2/android/support/v4/net/ConnectivityManagerCompatHoneycombMR2.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.net;
-
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.support.annotation.RequiresApi;
-
-import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
-import static android.net.ConnectivityManager.TYPE_ETHERNET;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
-import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
-import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
-import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.ConnectivityManager.TYPE_WIMAX;
-
-/**
- * Implementation of ConnectivityManagerCompat that can use Honeycomb MR2 APIs.
- */
-
-@RequiresApi(13)
-class ConnectivityManagerCompatHoneycombMR2 {
- public static boolean isActiveNetworkMetered(ConnectivityManager cm) {
- final NetworkInfo info = cm.getActiveNetworkInfo();
- if (info == null) {
- // err on side of caution
- return true;
- }
-
- final int type = info.getType();
- switch (type) {
- case TYPE_MOBILE:
- case TYPE_MOBILE_DUN:
- case TYPE_MOBILE_HIPRI:
- case TYPE_MOBILE_MMS:
- case TYPE_MOBILE_SUPL:
- case TYPE_WIMAX:
- return true;
- case TYPE_WIFI:
- case TYPE_BLUETOOTH:
- case TYPE_ETHERNET:
- return false;
- default:
- // err on side of caution
- return true;
- }
- }
-}
diff --git a/compat/ics-mr1/android/support/v4/content/IntentCompatIcsMr1.java b/compat/ics-mr1/android/support/v4/content/IntentCompatIcsMr1.java
deleted file mode 100644
index 8dd75d8..0000000
--- a/compat/ics-mr1/android/support/v4/content/IntentCompatIcsMr1.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.content;
-
-import android.content.Intent;
-import android.support.annotation.RequiresApi;
-
-@RequiresApi(15)
-class IntentCompatIcsMr1 {
-
- public static Intent makeMainSelectorActivity(String selectorAction, String selectorCategory) {
- return Intent.makeMainSelectorActivity(selectorAction, selectorCategory);
- }
-
-}
diff --git a/compat/ics/android/support/v4/net/TrafficStatsCompatIcs.java b/compat/ics/android/support/v4/net/TrafficStatsCompatIcs.java
deleted file mode 100644
index 4066386..0000000
--- a/compat/ics/android/support/v4/net/TrafficStatsCompatIcs.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.net;
-
-import android.net.TrafficStats;
-import android.os.ParcelFileDescriptor;
-import android.support.annotation.RequiresApi;
-
-import java.net.DatagramSocket;
-import java.net.Socket;
-import java.net.SocketException;
-
-/**
- * Implementation of TrafficStatsCompat that can call ICS APIs.
- */
-
-@RequiresApi(14)
-class TrafficStatsCompatIcs {
- public static void clearThreadStatsTag() {
- TrafficStats.clearThreadStatsTag();
- }
-
- public static int getThreadStatsTag() {
- return TrafficStats.getThreadStatsTag();
- }
-
- public static void incrementOperationCount(int operationCount) {
- TrafficStats.incrementOperationCount(operationCount);
- }
-
- public static void incrementOperationCount(int tag, int operationCount) {
- TrafficStats.incrementOperationCount(tag, operationCount);
- }
-
- public static void setThreadStatsTag(int tag) {
- TrafficStats.setThreadStatsTag(tag);
- }
-
- public static void tagSocket(Socket socket) throws SocketException {
- TrafficStats.tagSocket(socket);
- }
-
- public static void untagSocket(Socket socket) throws SocketException {
- TrafficStats.untagSocket(socket);
- }
-
- public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
- final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
- TrafficStats.tagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
- // The developer is still using the FD, so we need to detach it to
- // prevent the PFD finalizer from closing it in their face. We had to
- // wait until after the tagging call above, since detaching clears out
- // the getFileDescriptor() result which tagging depends on.
- pfd.detachFd();
- }
-
- public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
- final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
- TrafficStats.untagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
- // The developer is still using the FD, so we need to detach it to
- // prevent the PFD finalizer from closing it in their face. We had to
- // wait until after the tagging call above, since detaching clears out
- // the getFileDescriptor() result which tagging depends on.
- pfd.detachFd();
- }
-}
diff --git a/compat/ics/android/support/v4/widget/SearchViewCompatIcs.java b/compat/ics/android/support/v4/widget/SearchViewCompatIcs.java
deleted file mode 100644
index bf5c44e..0000000
--- a/compat/ics/android/support/v4/widget/SearchViewCompatIcs.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.widget;
-
-import android.content.Context;
-import android.support.annotation.RequiresApi;
-import android.view.View;
-import android.widget.SearchView;
-
-/**
- * Implementation of SearchView compatibility that can call ICS APIs.
- */
-
-@RequiresApi(14)
-class SearchViewCompatIcs {
-
- public static class MySearchView extends SearchView {
- public MySearchView(Context context) {
- super(context);
- }
-
- // The normal SearchView doesn't clear its search text when
- // collapsed, so we will do this for it.
- @Override
- public void onActionViewCollapsed() {
- setQuery("", false);
- super.onActionViewCollapsed();
- }
- }
-
- public static View newSearchView(Context context) {
- return new MySearchView(context);
- }
-
- public static void setImeOptions(View searchView, int imeOptions) {
- ((SearchView) searchView).setImeOptions(imeOptions);
- }
-
- public static void setInputType(View searchView, int inputType) {
- ((SearchView) searchView).setInputType(inputType);
- }
-}
diff --git a/compat/java/android/support/v4/content/IntentCompat.java b/compat/java/android/support/v4/content/IntentCompat.java
index 179824e..d34c914 100644
--- a/compat/java/android/support/v4/content/IntentCompat.java
+++ b/compat/java/android/support/v4/content/IntentCompat.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Build;
+import android.support.annotation.RequiresApi;
/**
* Helper for accessing features in {@link android.content.Intent}
@@ -27,22 +28,7 @@
*/
public final class IntentCompat {
- interface IntentCompatImpl {
- Intent makeMainActivity(ComponentName componentName);
- Intent makeMainSelectorActivity(String selectorAction, String selectorCategory);
- Intent makeRestartActivityTask(ComponentName mainActivity);
- }
-
- static class IntentCompatImplBase implements IntentCompatImpl {
- @Override
- public Intent makeMainActivity(ComponentName componentName) {
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setComponent(componentName);
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
- return intent;
- }
-
- @Override
+ static class IntentCompatBaseImpl {
public Intent makeMainSelectorActivity(String selectorAction,
String selectorCategory) {
// Before api 15 you couldn't set a selector intent.
@@ -52,43 +38,23 @@
intent.addCategory(selectorCategory);
return intent;
}
-
- @Override
- public Intent makeRestartActivityTask(ComponentName mainActivity) {
- Intent intent = makeMainActivity(mainActivity);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
- return intent;
- }
}
- static class IntentCompatImplHC extends IntentCompatImplBase {
- @Override
- public Intent makeMainActivity(ComponentName componentName) {
- return IntentCompatHoneycomb.makeMainActivity(componentName);
- }
- @Override
- public Intent makeRestartActivityTask(ComponentName componentName) {
- return IntentCompatHoneycomb.makeRestartActivityTask(componentName);
- }
- }
-
- static class IntentCompatImplIcsMr1 extends IntentCompatImplHC {
+ @RequiresApi(15)
+ static class IntentCompatApi15Impl extends IntentCompatBaseImpl {
@Override
public Intent makeMainSelectorActivity(String selectorAction, String selectorCategory) {
- return IntentCompatIcsMr1.makeMainSelectorActivity(selectorAction, selectorCategory);
+ return Intent.makeMainSelectorActivity(selectorAction, selectorCategory);
}
}
- private static final IntentCompatImpl IMPL;
+ private static final IntentCompatBaseImpl IMPL;
static {
final int version = Build.VERSION.SDK_INT;
if (version >= 15) {
- IMPL = new IntentCompatImplIcsMr1();
- } else if (version >= 11) {
- IMPL = new IntentCompatImplHC();
+ IMPL = new IntentCompatApi15Impl();
} else {
- IMPL = new IntentCompatImplBase();
+ IMPL = new IntentCompatBaseImpl();
}
}
@@ -118,7 +84,10 @@
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
+ *
+ * @deprecated Use {@link Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE} directly.
*/
+ @Deprecated
public static final String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE =
"android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
@@ -141,7 +110,10 @@
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
+ *
+ * @deprecated Use {@link Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE} directly.
*/
+ @Deprecated
public static final String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE =
"android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
@@ -150,7 +122,10 @@
* {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE},
* {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE}
* and contains a string array of all of the components that have changed.
+ *
+ * @deprecated Use {@link Intent#EXTRA_CHANGED_PACKAGE_LIST} directly.
*/
+ @Deprecated
public static final String EXTRA_CHANGED_PACKAGE_LIST =
"android.intent.extra.changed_package_list";
@@ -160,7 +135,10 @@
* {@link android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE}
* and contains an integer array of uids of all of the components
* that have changed.
+ *
+ * @deprecated Use {@link Intent#EXTRA_CHANGED_UID_LIST} directly.
*/
+ @Deprecated
public static final String EXTRA_CHANGED_UID_LIST =
"android.intent.extra.changed_uid_list";
@@ -186,7 +164,10 @@
* will always return the user to home even if that was not the last activity they
* saw. This can only be used in conjunction with
* {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}.
+ *
+ * @deprecated Use {@link Intent#FLAG_ACTIVITY_TASK_ON_HOME} directly.
*/
+ @Deprecated
public static final int FLAG_ACTIVITY_TASK_ON_HOME = 0x00004000;
/**
@@ -198,7 +179,10 @@
* {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}.
*
* <p>This flag will only be obeyed on devices supporting API 11 or higher.</p>
+ *
+ * @deprecated Use {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} directly.
*/
+ @Deprecated
public static final int FLAG_ACTIVITY_CLEAR_TASK = 0x00008000;
/**
@@ -222,12 +206,14 @@
*
* @see Intent#setClass
* @see Intent#setComponent
+ *
+ * @deprecated Use {@link Intent#makeMainActivity(ComponentName)} directly.
*/
+ @Deprecated
public static Intent makeMainActivity(ComponentName mainActivity) {
- return IMPL.makeMainActivity(mainActivity);
+ return Intent.makeMainActivity(mainActivity);
}
-
/**
* Make an Intent for the main activity of an application, without
* specifying a specific activity to run but giving a selector to find
@@ -257,7 +243,7 @@
* Make an Intent that can be used to re-launch an application's task
* in its base state. This is like {@link #makeMainActivity(ComponentName)},
* but also sets the flags {@link Intent#FLAG_ACTIVITY_NEW_TASK} and
- * {@link IntentCompat#FLAG_ACTIVITY_CLEAR_TASK}.
+ * {@link Intent#FLAG_ACTIVITY_CLEAR_TASK}.
*
* @param mainActivity The activity component that is the root of the
* task; this is the activity that has been published in the application's
@@ -265,8 +251,11 @@
*
* @return Returns a newly created Intent that can be used to relaunch the
* activity's task in its root state.
+ *
+ * @deprecated Use {@link Intent#makeRestartActivityTask(ComponentName)} directly.
*/
+ @Deprecated
public static Intent makeRestartActivityTask(ComponentName mainActivity) {
- return IMPL.makeRestartActivityTask(mainActivity);
+ return Intent.makeRestartActivityTask(mainActivity);
}
}
diff --git a/compat/java/android/support/v4/content/res/TypedArrayUtils.java b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
new file mode 100644
index 0000000..77d4672
--- /dev/null
+++ b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
@@ -0,0 +1,218 @@
+/*
+ * 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.v4.content.res;
+
+import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.AnyRes;
+import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.StyleableRes;
+import android.util.TypedValue;
+
+import org.xmlpull.v1.XmlPullParser;
+
+/**
+ * Compat methods for accessing TypedArray values.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public class TypedArrayUtils {
+
+ private static final String NAMESPACE = "http://schemas.android.com/apk/res/android";
+
+ /**
+ * @return Whether the current node ofthe {@link XmlPullParser} has an attribute with the
+ * specified {@code attrName}.
+ */
+ public static boolean hasAttribute(@NonNull XmlPullParser parser, @NonNull String attrName) {
+ return parser.getAttributeValue(NAMESPACE, attrName) != null;
+ }
+
+ /**
+ * Retrieves a float attribute value. In addition to the styleable resource ID, we also make
+ * sure that the attribute name matches.
+ *
+ * @return a float value in the {@link TypedArray} with the specified {@code resId}, or
+ * {@code defaultValue} if it does not exist.
+ */
+ public static float getNamedFloat(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+ @NonNull String attrName, @StyleableRes int resId, float defaultValue) {
+ final boolean hasAttr = hasAttribute(parser, attrName);
+ if (!hasAttr) {
+ return defaultValue;
+ } else {
+ return a.getFloat(resId, defaultValue);
+ }
+ }
+
+ /**
+ * Retrieves a boolean attribute value. In addition to the styleable resource ID, we also make
+ * sure that the attribute name matches.
+ *
+ * @return a boolean value in the {@link TypedArray} with the specified {@code resId}, or
+ * {@code defaultValue} if it does not exist.
+ */
+ public static boolean getNamedBoolean(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+ String attrName, @StyleableRes int resId, boolean defaultValue) {
+ final boolean hasAttr = hasAttribute(parser, attrName);
+ if (!hasAttr) {
+ return defaultValue;
+ } else {
+ return a.getBoolean(resId, defaultValue);
+ }
+ }
+
+ /**
+ * Retrieves an int attribute value. In addition to the styleable resource ID, we also make
+ * sure that the attribute name matches.
+ *
+ * @return an int value in the {@link TypedArray} with the specified {@code resId}, or
+ * {@code defaultValue} if it does not exist.
+ */
+ public static int getNamedInt(TypedArray a, XmlPullParser parser, String attrName,
+ int resId, int defaultValue) {
+ final boolean hasAttr = hasAttribute(parser, attrName);
+ if (!hasAttr) {
+ return defaultValue;
+ } else {
+ return a.getInt(resId, defaultValue);
+ }
+ }
+
+ /**
+ * Retrieves a color attribute value. In addition to the styleable resource ID, we also make
+ * sure that the attribute name matches.
+ *
+ * @return a color value in the {@link TypedArray} with the specified {@code resId}, or
+ * {@code defaultValue} if it does not exist.
+ */
+ @ColorInt
+ public static int getNamedColor(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+ String attrName, @StyleableRes int resId, @ColorInt int defaultValue) {
+ final boolean hasAttr = hasAttribute(parser, attrName);
+ if (!hasAttr) {
+ return defaultValue;
+ } else {
+ return a.getColor(resId, defaultValue);
+ }
+ }
+
+ /**
+ * @return a boolean value of {@code index}. If it does not exist, a boolean value of
+ * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
+ */
+ public static boolean getBoolean(TypedArray a, @StyleableRes int index,
+ @StyleableRes int fallbackIndex, boolean defaultValue) {
+ boolean val = a.getBoolean(fallbackIndex, defaultValue);
+ return a.getBoolean(index, val);
+ }
+
+ /**
+ * @return a drawable value of {@code index}. If it does not exist, a drawable value of
+ * {@code fallbackIndex}. If it still does not exist, {@code null}.
+ */
+ public static Drawable getDrawable(TypedArray a, @StyleableRes int index,
+ @StyleableRes int fallbackIndex) {
+ Drawable val = a.getDrawable(index);
+ if (val == null) {
+ val = a.getDrawable(fallbackIndex);
+ }
+ return val;
+ }
+
+ /**
+ * @return an int value of {@code index}. If it does not exist, an int value of
+ * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
+ */
+ public static int getInt(TypedArray a, @StyleableRes int index,
+ @StyleableRes int fallbackIndex, int defaultValue) {
+ int val = a.getInt(fallbackIndex, defaultValue);
+ return a.getInt(index, val);
+ }
+
+ /**
+ * @return a resource ID value of {@code index}. If it does not exist, a resource ID value of
+ * {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
+ */
+ @AnyRes
+ public static int getResourceId(TypedArray a, @StyleableRes int index,
+ @StyleableRes int fallbackIndex, @AnyRes int defaultValue) {
+ int val = a.getResourceId(fallbackIndex, defaultValue);
+ return a.getResourceId(index, val);
+ }
+
+ /**
+ * @return a string value of {@code index}. If it does not exist, a string value of
+ * {@code fallbackIndex}. If it still does not exist, {@code null}.
+ */
+ public static String getString(TypedArray a, @StyleableRes int index,
+ @StyleableRes int fallbackIndex) {
+ String val = a.getString(index);
+ if (val == null) {
+ val = a.getString(fallbackIndex);
+ }
+ return val;
+ }
+
+ /**
+ * Retrieves a text attribute value with the specified fallback ID.
+ *
+ * @return a text value of {@code index}. If it does not exist, a text value of
+ * {@code fallbackIndex}. If it still does not exist, {@code null}.
+ */
+ public static CharSequence getText(TypedArray a, @StyleableRes int index,
+ @StyleableRes int fallbackIndex) {
+ CharSequence val = a.getText(index);
+ if (val == null) {
+ val = a.getText(fallbackIndex);
+ }
+ return val;
+ }
+
+ /**
+ * Retrieves a string array attribute value with the specified fallback ID.
+ *
+ * @return a string array value of {@code index}. If it does not exist, a string array value
+ * of {@code fallbackIndex}. If it still does not exist, {@code null}.
+ */
+ public static CharSequence[] getTextArray(TypedArray a, @StyleableRes int index,
+ @StyleableRes int fallbackIndex) {
+ CharSequence[] val = a.getTextArray(index);
+ if (val == null) {
+ val = a.getTextArray(fallbackIndex);
+ }
+ return val;
+ }
+
+ /**
+ * @return The resource ID value in the {@code context} specified by {@code attr}. If it does
+ * not exist, {@code fallbackAttr}.
+ */
+ public static int getAttr(Context context, int attr, int fallbackAttr) {
+ TypedValue value = new TypedValue();
+ context.getTheme().resolveAttribute(attr, value, true);
+ if (value.resourceId != 0) {
+ return attr;
+ }
+ return fallbackAttr;
+ }
+}
diff --git a/compat/java/android/support/v4/net/ConnectivityManagerCompat.java b/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
index f9ff971..5c61193 100644
--- a/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
+++ b/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
@@ -16,6 +16,8 @@
package android.support.v4.net;
+import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -30,6 +32,7 @@
import android.net.NetworkInfo;
import android.os.Build;
import android.support.annotation.IntDef;
+import android.support.annotation.RequiresApi;
import android.support.annotation.RestrictTo;
import java.lang.annotation.Retention;
@@ -51,7 +54,7 @@
/** @hide */
@RestrictTo(LIBRARY_GROUP)
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = false, value = {
+ @IntDef(value = {
RESTRICT_BACKGROUND_STATUS_DISABLED,
RESTRICT_BACKGROUND_STATUS_WHITELISTED,
RESTRICT_BACKGROUND_STATUS_ENABLED,
@@ -82,7 +85,8 @@
*/
public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3;
- static class BaseConnectivityManagerCompatImpl implements ConnectivityManagerCompatImpl {
+ static class ConnectivityManagerCompatBaseImpl implements ConnectivityManagerCompatImpl {
+ @SuppressWarnings("deprecation")
@Override
public boolean isActiveNetworkMetered(ConnectivityManager cm) {
final NetworkInfo info = cm.getActiveNetworkInfo();
@@ -101,6 +105,8 @@
case TYPE_WIMAX:
return true;
case TYPE_WIFI:
+ case TYPE_BLUETOOTH:
+ case TYPE_ETHERNET:
return false;
default:
// err on side of caution
@@ -114,28 +120,20 @@
}
}
- static class HoneycombMR2ConnectivityManagerCompatImpl
- extends BaseConnectivityManagerCompatImpl {
+ @RequiresApi(16)
+ static class ConnectivityManagerCompatApi16Impl extends ConnectivityManagerCompatBaseImpl {
@Override
public boolean isActiveNetworkMetered(ConnectivityManager cm) {
- return ConnectivityManagerCompatHoneycombMR2.isActiveNetworkMetered(cm);
+ return cm.isActiveNetworkMetered();
}
}
- static class JellyBeanConnectivityManagerCompatImpl
- extends HoneycombMR2ConnectivityManagerCompatImpl {
- @Override
- public boolean isActiveNetworkMetered(ConnectivityManager cm) {
- return ConnectivityManagerCompatJellyBean.isActiveNetworkMetered(cm);
- }
- }
-
- static class Api24ConnectivityManagerCompatImpl
- extends JellyBeanConnectivityManagerCompatImpl {
+ @RequiresApi(24)
+ static class ConnectivityManagerCompatApi24Impl extends ConnectivityManagerCompatApi16Impl {
@Override
public int getRestrictBackgroundStatus(ConnectivityManager cm) {
//noinspection ResourceType
- return ConnectivityManagerCompatApi24.getRestrictBackgroundStatus(cm);
+ return cm.getRestrictBackgroundStatus();
}
}
@@ -143,13 +141,11 @@
static {
if (Build.VERSION.SDK_INT >= 24) {
- IMPL = new Api24ConnectivityManagerCompatImpl();
+ IMPL = new ConnectivityManagerCompatApi24Impl();
} else if (Build.VERSION.SDK_INT >= 16) {
- IMPL = new JellyBeanConnectivityManagerCompatImpl();
- } else if (Build.VERSION.SDK_INT >= 13) {
- IMPL = new HoneycombMR2ConnectivityManagerCompatImpl();
+ IMPL = new ConnectivityManagerCompatApi16Impl();
} else {
- IMPL = new BaseConnectivityManagerCompatImpl();
+ IMPL = new ConnectivityManagerCompatBaseImpl();
}
}
diff --git a/compat/java/android/support/v4/net/TrafficStatsCompat.java b/compat/java/android/support/v4/net/TrafficStatsCompat.java
index 2e0fa69..5c76b59 100644
--- a/compat/java/android/support/v4/net/TrafficStatsCompat.java
+++ b/compat/java/android/support/v4/net/TrafficStatsCompat.java
@@ -16,171 +16,86 @@
package android.support.v4.net;
+import android.annotation.TargetApi;
+import android.net.TrafficStats;
import android.os.Build;
+import android.os.ParcelFileDescriptor;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;
/**
- * Helper for accessing features in TrafficStats introduced after API level 14
+ * Helper for accessing features in {@link TrafficStats} introduced after API level 14
* in a backwards compatible fashion.
*/
public final class TrafficStatsCompat {
-
- interface TrafficStatsCompatImpl {
- void clearThreadStatsTag();
- int getThreadStatsTag();
- void incrementOperationCount(int operationCount);
- void incrementOperationCount(int tag, int operationCount);
- void setThreadStatsTag(int tag);
- void tagSocket(Socket socket) throws SocketException;
- void untagSocket(Socket socket) throws SocketException;
- void tagDatagramSocket(DatagramSocket socket) throws SocketException;
- void untagDatagramSocket(DatagramSocket socket) throws SocketException;
- }
-
- static class BaseTrafficStatsCompatImpl implements TrafficStatsCompatImpl {
- private static class SocketTags {
- public int statsTag = -1;
-
- SocketTags() {
- }
+ static class TrafficStatsCompatBaseImpl {
+ public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
+ final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
+ TrafficStats.tagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
+ // The developer is still using the FD, so we need to detach it to
+ // prevent the PFD finalizer from closing it in their face. We had to
+ // wait until after the tagging call above, since detaching clears out
+ // the getFileDescriptor() result which tagging depends on.
+ pfd.detachFd();
}
- private ThreadLocal<SocketTags> mThreadSocketTags = new ThreadLocal<SocketTags>() {
- @Override
- protected SocketTags initialValue() {
- return new SocketTags();
- }
- };
-
- @Override
- public void clearThreadStatsTag() {
- mThreadSocketTags.get().statsTag = -1;
- }
-
- @Override
- public int getThreadStatsTag() {
- return mThreadSocketTags.get().statsTag;
- }
-
- @Override
- public void incrementOperationCount(int operationCount) {
- }
-
- @Override
- public void incrementOperationCount(int tag, int operationCount) {
- }
-
- @Override
- public void setThreadStatsTag(int tag) {
- mThreadSocketTags.get().statsTag = tag;
- }
-
- @Override
- public void tagSocket(Socket socket) {
- }
-
- @Override
- public void untagSocket(Socket socket) {
- }
-
- @Override
- public void tagDatagramSocket(DatagramSocket socket) {
- }
-
- @Override
- public void untagDatagramSocket(DatagramSocket socket) {
+ public void untagDatagramSocket(DatagramSocket socket) throws SocketException {
+ final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket);
+ TrafficStats.untagSocket(new DatagramSocketWrapper(socket, pfd.getFileDescriptor()));
+ // The developer is still using the FD, so we need to detach it to
+ // prevent the PFD finalizer from closing it in their face. We had to
+ // wait until after the tagging call above, since detaching clears out
+ // the getFileDescriptor() result which tagging depends on.
+ pfd.detachFd();
}
}
- static class IcsTrafficStatsCompatImpl implements TrafficStatsCompatImpl {
- @Override
- public void clearThreadStatsTag() {
- TrafficStatsCompatIcs.clearThreadStatsTag();
- }
-
- @Override
- public int getThreadStatsTag() {
- return TrafficStatsCompatIcs.getThreadStatsTag();
- }
-
- @Override
- public void incrementOperationCount(int operationCount) {
- TrafficStatsCompatIcs.incrementOperationCount(operationCount);
- }
-
- @Override
- public void incrementOperationCount(int tag, int operationCount) {
- TrafficStatsCompatIcs.incrementOperationCount(tag, operationCount);
- }
-
- @Override
- public void setThreadStatsTag(int tag) {
- TrafficStatsCompatIcs.setThreadStatsTag(tag);
- }
-
- @Override
- public void tagSocket(Socket socket) throws SocketException {
- TrafficStatsCompatIcs.tagSocket(socket);
- }
-
- @Override
- public void untagSocket(Socket socket) throws SocketException {
- TrafficStatsCompatIcs.untagSocket(socket);
- }
-
+ @TargetApi(24)
+ static class TrafficStatsCompatApi24Impl extends TrafficStatsCompatBaseImpl {
@Override
public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
- TrafficStatsCompatIcs.tagDatagramSocket(socket);
+ TrafficStats.tagDatagramSocket(socket);
}
@Override
public void untagDatagramSocket(DatagramSocket socket) throws SocketException {
- TrafficStatsCompatIcs.untagDatagramSocket(socket);
+ TrafficStats.untagDatagramSocket(socket);
}
}
- static class Api24TrafficStatsCompatImpl extends IcsTrafficStatsCompatImpl {
- @Override
- public void tagDatagramSocket(DatagramSocket socket) throws SocketException {
- TrafficStatsCompatApi24.tagDatagramSocket(socket);
- }
-
- @Override
- public void untagDatagramSocket(DatagramSocket socket) throws SocketException {
- TrafficStatsCompatApi24.untagDatagramSocket(socket);
- }
- }
-
- private static final TrafficStatsCompatImpl IMPL;
+ private static final TrafficStatsCompatBaseImpl IMPL;
static {
- if ("N".equals(Build.VERSION.CODENAME)) {
- IMPL = new Api24TrafficStatsCompatImpl();
- } else if (Build.VERSION.SDK_INT >= 14) {
- IMPL = new IcsTrafficStatsCompatImpl();
+ if (Build.VERSION.SDK_INT >= 24) {
+ IMPL = new TrafficStatsCompatApi24Impl();
} else {
- IMPL = new BaseTrafficStatsCompatImpl();
+ IMPL = new TrafficStatsCompatBaseImpl();
}
}
/**
* Clear active tag used when accounting {@link Socket} traffic originating
* from the current thread.
+ *
+ * @deprecated Use {@link TrafficStats#clearThreadStatsTag()} directly.
*/
+ @Deprecated
public static void clearThreadStatsTag() {
- IMPL.clearThreadStatsTag();
+ TrafficStats.clearThreadStatsTag();
}
/**
* Get the active tag used when accounting {@link Socket} traffic originating
* from the current thread. Only one active tag per thread is supported.
* {@link #tagSocket(Socket)}.
+ *
+ * @deprecated Use {@link TrafficStats#getThreadStatsTag()} directly.
*/
+ @Deprecated
public static int getThreadStatsTag() {
- return IMPL.getThreadStatsTag();
+ return TrafficStats.getThreadStatsTag();
}
/**
@@ -189,9 +104,12 @@
* bytes-per-operation.
*
* @param operationCount Number of operations to increment count by.
+ *
+ * @deprecated Use {@link TrafficStats#incrementOperationCount(int)} directly.
*/
+ @Deprecated
public static void incrementOperationCount(int operationCount) {
- IMPL.incrementOperationCount(operationCount);
+ TrafficStats.incrementOperationCount(operationCount);
}
/**
@@ -200,9 +118,12 @@
*
* @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
* @param operationCount Number of operations to increment count by.
+ *
+ * @deprecated Use {@link TrafficStats#incrementOperationCount(int, int)} directly.
*/
+ @Deprecated
public static void incrementOperationCount(int tag, int operationCount) {
- IMPL.incrementOperationCount(tag, operationCount);
+ TrafficStats.incrementOperationCount(tag, operationCount);
}
/**
@@ -215,9 +136,12 @@
* Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
* used internally by system services like DownloadManager when performing
* traffic on behalf of an application.
+ *
+ * @deprecated Use {@link TrafficStats#setThreadStatsTag(int)} directly.
*/
+ @Deprecated
public static void setThreadStatsTag(int tag) {
- IMPL.setThreadStatsTag(tag);
+ TrafficStats.setThreadStatsTag(tag);
}
/**
@@ -227,16 +151,22 @@
* statistics parameters.
*
* @see #setThreadStatsTag(int)
+ *
+ * @deprecated Use {@link TrafficStats#tagSocket(Socket)} directly.
*/
+ @Deprecated
public static void tagSocket(Socket socket) throws SocketException {
- IMPL.tagSocket(socket);
+ TrafficStats.tagSocket(socket);
}
/**
* Remove any statistics parameters from the given {@link Socket}.
+ *
+ * @deprecated Use {@link TrafficStats#untagSocket(Socket)} directly.
*/
+ @Deprecated
public static void untagSocket(Socket socket) throws SocketException {
- IMPL.untagSocket(socket);
+ TrafficStats.untagSocket(socket);
}
/**
diff --git a/compat/java/android/support/v4/text/ICUCompat.java b/compat/java/android/support/v4/text/ICUCompat.java
index 0632513..cd26961 100644
--- a/compat/java/android/support/v4/text/ICUCompat.java
+++ b/compat/java/android/support/v4/text/ICUCompat.java
@@ -16,47 +16,35 @@
package android.support.v4.text;
+import android.annotation.TargetApi;
import android.os.Build;
+import android.support.annotation.Nullable;
import java.util.Locale;
public final class ICUCompat {
-
- interface ICUCompatImpl {
- public String maximizeAndGetScript(Locale locale);
- }
-
- static class ICUCompatImplBase implements ICUCompatImpl {
- @Override
- public String maximizeAndGetScript(Locale locale) {
- return null;
- }
- }
-
- static class ICUCompatImplIcs implements ICUCompatImpl {
- @Override
+ static class ICUCompatBaseImpl {
public String maximizeAndGetScript(Locale locale) {
return ICUCompatIcs.maximizeAndGetScript(locale);
}
}
- static class ICUCompatImplLollipop implements ICUCompatImpl {
+ @TargetApi(23)
+ static class ICUCompatApi21Impl extends ICUCompatBaseImpl {
@Override
public String maximizeAndGetScript(Locale locale) {
- return ICUCompatApi23.maximizeAndGetScript(locale);
+ return ICUCompatApi21.maximizeAndGetScript(locale);
}
}
- private static final ICUCompatImpl IMPL;
+ private static final ICUCompatBaseImpl IMPL;
static {
final int version = Build.VERSION.SDK_INT;
if (version >= 21) {
- IMPL = new ICUCompatImplLollipop();
- } else if (version >= 14) {
- IMPL = new ICUCompatImplIcs();
+ IMPL = new ICUCompatApi21Impl();
} else {
- IMPL = new ICUCompatImplBase();
+ IMPL = new ICUCompatBaseImpl();
}
}
@@ -81,8 +69,9 @@
* "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.)
* "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.)
*
- * @return
+ * @return The script for a given Locale if ICU library is available, otherwise null.
*/
+ @Nullable
public static String maximizeAndGetScript(Locale locale) {
return IMPL.maximizeAndGetScript(locale);
}
diff --git a/compat/java/android/support/v4/widget/SearchViewCompat.java b/compat/java/android/support/v4/widget/SearchViewCompat.java
index 2b69f55..83cb0fc 100644
--- a/compat/java/android/support/v4/widget/SearchViewCompat.java
+++ b/compat/java/android/support/v4/widget/SearchViewCompat.java
@@ -17,267 +17,28 @@
package android.support.v4.widget;
import android.app.SearchManager;
+import android.app.SearchableInfo;
import android.content.ComponentName;
import android.content.Context;
-import android.os.Build;
import android.view.View;
+import android.widget.SearchView;
import android.widget.TextView;
/**
- * Helper for accessing features in {@link android.widget.SearchView}
+ * Helper for accessing features in {@link SearchView}
* introduced after API level 4 in a backwards compatible fashion.
+ *
+ * @deprecated Use {@link SearchView} directly.
*/
+@Deprecated
public final class SearchViewCompat {
-
- interface SearchViewCompatImpl {
- View newSearchView(Context context);
- void setSearchableInfo(View searchView, ComponentName searchableComponent);
- void setImeOptions(View searchView, int imeOptions);
- void setInputType(View searchView, int inputType);
- Object newOnQueryTextListener(OnQueryTextListener listener);
- void setOnQueryTextListener(View searchView, OnQueryTextListener listener);
- Object newOnCloseListener(OnCloseListener listener);
- void setOnCloseListener(View searchView, OnCloseListener listener);
- CharSequence getQuery(View searchView);
- void setQuery(View searchView, CharSequence query, boolean submit);
- void setQueryHint(View searchView, CharSequence hint);
- void setIconified(View searchView, boolean iconify);
- boolean isIconified(View searchView);
- void setSubmitButtonEnabled(View searchView, boolean enabled);
- boolean isSubmitButtonEnabled(View searchView);
- void setQueryRefinementEnabled(View searchView, boolean enable);
- boolean isQueryRefinementEnabled(View searchView);
- void setMaxWidth(View searchView, int maxpixels);
- }
-
- static class SearchViewCompatStubImpl implements SearchViewCompatImpl {
-
- @Override
- public View newSearchView(Context context) {
- return null;
+ private static void checkIfLegalArg(View searchView) {
+ if (searchView == null) {
+ throw new IllegalArgumentException("searchView must be non-null");
}
-
- @Override
- public void setSearchableInfo(View searchView, ComponentName searchableComponent) {
- }
-
- @Override
- public void setImeOptions(View searchView, int imeOptions) {
- }
-
- @Override
- public void setInputType(View searchView, int inputType) {
- }
-
- @Override
- public Object newOnQueryTextListener(OnQueryTextListener listener) {
- return null;
- }
-
- @Override
- public void setOnQueryTextListener(View searchView, OnQueryTextListener listener) {
- }
-
- @Override
- public Object newOnCloseListener(OnCloseListener listener) {
- return null;
- }
-
- @Override
- public void setOnCloseListener(View searchView, OnCloseListener listener) {
- }
-
- @Override
- public CharSequence getQuery(View searchView) {
- return null;
- }
-
- @Override
- public void setQuery(View searchView, CharSequence query, boolean submit) {
- }
-
- @Override
- public void setQueryHint(View searchView, CharSequence hint) {
- }
-
- @Override
- public void setIconified(View searchView, boolean iconify) {
- }
-
- @Override
- public boolean isIconified(View searchView) {
- return true;
- }
-
- @Override
- public void setSubmitButtonEnabled(View searchView, boolean enabled) {
- }
-
- @Override
- public boolean isSubmitButtonEnabled(View searchView) {
- return false;
- }
-
- @Override
- public void setQueryRefinementEnabled(View searchView, boolean enable) {
- }
-
- @Override
- public boolean isQueryRefinementEnabled(View searchView) {
- return false;
- }
-
- @Override
- public void setMaxWidth(View searchView, int maxpixels) {
- }
- }
-
- static class SearchViewCompatHoneycombImpl extends SearchViewCompatStubImpl {
-
- @Override
- public View newSearchView(Context context) {
- return SearchViewCompatHoneycomb.newSearchView(context);
- }
-
- @Override
- public void setSearchableInfo(View searchView, ComponentName searchableComponent) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setSearchableInfo(searchView, searchableComponent);
- }
-
- @Override
- public Object newOnQueryTextListener(final OnQueryTextListener listener) {
- return SearchViewCompatHoneycomb.newOnQueryTextListener(
- new SearchViewCompatHoneycomb.OnQueryTextListenerCompatBridge() {
- @Override
- public boolean onQueryTextSubmit(String query) {
- return listener.onQueryTextSubmit(query);
- }
- @Override
- public boolean onQueryTextChange(String newText) {
- return listener.onQueryTextChange(newText);
- }
- });
- }
-
- @Override
- public void setOnQueryTextListener(View searchView, OnQueryTextListener listener) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setOnQueryTextListener(searchView,
- newOnQueryTextListener(listener));
- }
-
- @Override
- public Object newOnCloseListener(final OnCloseListener listener) {
- return SearchViewCompatHoneycomb.newOnCloseListener(
- new SearchViewCompatHoneycomb.OnCloseListenerCompatBridge() {
- @Override
- public boolean onClose() {
- return listener.onClose();
- }
- });
- }
-
- @Override
- public void setOnCloseListener(View searchView, OnCloseListener listener) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setOnCloseListener(searchView, newOnCloseListener(listener));
- }
-
- @Override
- public CharSequence getQuery(View searchView) {
- checkIfLegalArg(searchView);
- return SearchViewCompatHoneycomb.getQuery(searchView);
- }
-
- @Override
- public void setQuery(View searchView, CharSequence query, boolean submit) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setQuery(searchView, query, submit);
- }
-
- @Override
- public void setQueryHint(View searchView, CharSequence hint) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setQueryHint(searchView, hint);
- }
-
- @Override
- public void setIconified(View searchView, boolean iconify) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setIconified(searchView, iconify);
- }
-
- @Override
- public boolean isIconified(View searchView) {
- checkIfLegalArg(searchView);
- return SearchViewCompatHoneycomb.isIconified(searchView);
- }
-
- @Override
- public void setSubmitButtonEnabled(View searchView, boolean enabled) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setSubmitButtonEnabled(searchView, enabled);
- }
-
- @Override
- public boolean isSubmitButtonEnabled(View searchView) {
- checkIfLegalArg(searchView);
- return SearchViewCompatHoneycomb.isSubmitButtonEnabled(searchView);
- }
-
- @Override
- public void setQueryRefinementEnabled(View searchView, boolean enable) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setQueryRefinementEnabled(searchView, enable);
- }
-
- @Override
- public boolean isQueryRefinementEnabled(View searchView) {
- checkIfLegalArg(searchView);
- return SearchViewCompatHoneycomb.isQueryRefinementEnabled(searchView);
- }
-
- @Override
- public void setMaxWidth(View searchView, int maxpixels) {
- checkIfLegalArg(searchView);
- SearchViewCompatHoneycomb.setMaxWidth(searchView, maxpixels);
- }
-
- protected void checkIfLegalArg(View searchView) {
- SearchViewCompatHoneycomb.checkIfLegalArg(searchView);
- }
- }
-
- static class SearchViewCompatIcsImpl extends SearchViewCompatHoneycombImpl {
-
- @Override
- public View newSearchView(Context context) {
- return SearchViewCompatIcs.newSearchView(context);
- }
-
- @Override
- public void setImeOptions(View searchView, int imeOptions) {
- checkIfLegalArg(searchView);
- SearchViewCompatIcs.setImeOptions(searchView, imeOptions);
- }
-
- @Override
- public void setInputType(View searchView, int inputType) {
- checkIfLegalArg(searchView);
- SearchViewCompatIcs.setInputType(searchView, inputType);
- }
- }
-
- private static final SearchViewCompatImpl IMPL;
-
- static {
- if (Build.VERSION.SDK_INT >= 14) { // ICS
- IMPL = new SearchViewCompatIcsImpl();
- } else if (Build.VERSION.SDK_INT >= 11) { // Honeycomb
- IMPL = new SearchViewCompatHoneycombImpl();
- } else {
- IMPL = new SearchViewCompatStubImpl();
+ if (!(searchView instanceof SearchView)) {
+ throw new IllegalArgumentException("searchView must be an instance of "
+ + "android.widget.SearchView");
}
}
@@ -291,9 +52,12 @@
* @param context The Context the view is running in.
* @return A SearchView instance if the class is present on the current
* platform, null otherwise.
+ *
+ * @deprecated Use {@link SearchView} constructor directly.
*/
+ @Deprecated
public static View newSearchView(Context context) {
- return IMPL.newSearchView(context);
+ return new SearchView(context);
}
/**
@@ -305,9 +69,16 @@
* @param searchableComponent The application component whose
* {@link android.app.SearchableInfo} should be loaded and applied to
* the SearchView.
+ *
+ * @deprecated Use {@link SearchView#setSearchableInfo(SearchableInfo)} directly.
*/
+ @Deprecated
public static void setSearchableInfo(View searchView, ComponentName searchableComponent) {
- IMPL.setSearchableInfo(searchView, searchableComponent);
+ checkIfLegalArg(searchView);
+ SearchManager searchManager = (SearchManager)
+ searchView.getContext().getSystemService(Context.SEARCH_SERVICE);
+ ((SearchView) searchView).setSearchableInfo(
+ searchManager.getSearchableInfo(searchableComponent));
}
/**
@@ -318,9 +89,13 @@
* @see TextView#setImeOptions(int)
* @param searchView The SearchView to operate on.
* @param imeOptions the options to set on the query text field
+ *
+ * @deprecated Use {@link SearchView#setImeOptions(int)} directly.
*/
+ @Deprecated
public static void setImeOptions(View searchView, int imeOptions) {
- IMPL.setImeOptions(searchView, imeOptions);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setImeOptions(imeOptions);
}
/**
@@ -331,9 +106,13 @@
* @see TextView#setInputType(int)
* @param searchView The SearchView to operate on.
* @param inputType the input type to set on the query text field
+ *
+ * @deprecated Use {@link SearchView#setInputType(int)} directly.
*/
+ @Deprecated
public static void setInputType(View searchView, int inputType) {
- IMPL.setInputType(searchView, inputType);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setInputType(inputType);
}
/**
@@ -342,13 +121,33 @@
* @param searchView The SearchView in which to register the listener.
* @param listener the listener object that receives callbacks when the user performs
* actions in the SearchView such as clicking on buttons or typing a query.
+ *
+ * @deprecated Use {@link SearchView#setOnQueryTextListener(SearchView.OnQueryTextListener)}
+ * directly.
*/
+ @Deprecated
public static void setOnQueryTextListener(View searchView, OnQueryTextListener listener) {
- IMPL.setOnQueryTextListener(searchView, listener);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setOnQueryTextListener(newOnQueryTextListener(listener));
+ }
+
+ private static SearchView.OnQueryTextListener newOnQueryTextListener(
+ final OnQueryTextListener listener) {
+ return new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ return listener.onQueryTextSubmit(query);
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ return listener.onQueryTextChange(newText);
+ }
+ };
}
/**
- * @deprecated Use {@link OnQueryTextListener} instead.
+ * @deprecated Use {@link SearchView.OnQueryTextListener} instead.
*/
@Deprecated
public static abstract class OnQueryTextListenerCompat implements OnQueryTextListener {
@@ -364,8 +163,9 @@
}
/**
- * Callbacks for changes to the query text.
+ * @deprecated Use {@link SearchView.OnQueryTextListener} instead.
*/
+ @Deprecated
public interface OnQueryTextListener {
/**
* Called when the user submits the query. This could be due to a key press on the
@@ -397,13 +197,26 @@
*
* @param searchView The SearchView in which to register the listener.
* @param listener the listener to call when the user closes the SearchView.
+ *
+ * @deprecated Use {@link SearchView#setOnCloseListener(SearchView.OnCloseListener)} directly.
*/
+ @Deprecated
public static void setOnCloseListener(View searchView, OnCloseListener listener) {
- IMPL.setOnCloseListener(searchView, listener);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setOnCloseListener(newOnCloseListener(listener));
+ }
+
+ private static SearchView.OnCloseListener newOnCloseListener(final OnCloseListener listener) {
+ return new SearchView.OnCloseListener() {
+ @Override
+ public boolean onClose() {
+ return listener.onClose();
+ }
+ };
}
/**
- * @deprecated Use {@link OnCloseListener} instead.
+ * @deprecated Use {@link SearchView.OnCloseListener} instead.
*/
@Deprecated
public static abstract class OnCloseListenerCompat implements OnCloseListener {
@@ -415,7 +228,10 @@
/**
* Callback for closing the query UI.
+ *
+ * @deprecated Use {@link SearchView.OnCloseListener} instead.
*/
+ @Deprecated
public interface OnCloseListener {
/**
* The user is attempting to close the SearchView.
@@ -432,9 +248,13 @@
* @param searchView The SearchView to operate on.
*
* @return the query string
+ *
+ * @deprecated Use {@link SearchView#getQuery()} directly.
*/
+ @Deprecated
public static CharSequence getQuery(View searchView) {
- return IMPL.getQuery(searchView);
+ checkIfLegalArg(searchView);
+ return ((SearchView) searchView).getQuery();
}
/**
@@ -445,9 +265,13 @@
* text field.
* @param submit whether to submit the query right now or only update the contents of
* text field.
+ *
+ * @deprecated Use {@link SearchView#setQuery(CharSequence, boolean)} directly.
*/
+ @Deprecated
public static void setQuery(View searchView, CharSequence query, boolean submit) {
- IMPL.setQuery(searchView, query, submit);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setQuery(query, submit);
}
/**
@@ -456,9 +280,13 @@
*
* @param searchView The SearchView to operate on.
* @param hint the hint text to display
+ *
+ * @deprecated Use {@link SearchView#setQueryHint(CharSequence)} directly.
*/
+ @Deprecated
public static void setQueryHint(View searchView, CharSequence hint) {
- IMPL.setQueryHint(searchView, hint);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setQueryHint(hint);
}
/**
@@ -471,9 +299,13 @@
* @param searchView The SearchView to operate on.
* @param iconify a true value will collapse the SearchView to an icon, while a false will
* expand it.
+ *
+ * @deprecated Use {@link SearchView#setIconified(boolean)} directly.
*/
+ @Deprecated
public static void setIconified(View searchView, boolean iconify) {
- IMPL.setIconified(searchView, iconify);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setIconified(iconify);
}
/**
@@ -482,9 +314,13 @@
* @param searchView The SearchView to operate on.
* @return true if the SearchView is currently iconified, false if the search field is
* fully visible.
+ *
+ * @deprecated Use {@link SearchView#isIconified()} directly.
*/
+ @Deprecated
public static boolean isIconified(View searchView) {
- return IMPL.isIconified(searchView);
+ checkIfLegalArg(searchView);
+ return ((SearchView) searchView).isIconified();
}
/**
@@ -495,9 +331,13 @@
* @param searchView The SearchView to operate on.
* @param enabled true to show a submit button for submitting queries, false if a submit
* button is not required.
+ *
+ * @deprecated Use {@link SearchView#setSubmitButtonEnabled(boolean)} directly.
*/
+ @Deprecated
public static void setSubmitButtonEnabled(View searchView, boolean enabled) {
- IMPL.setSubmitButtonEnabled(searchView, enabled);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setSubmitButtonEnabled(enabled);
}
/**
@@ -505,9 +345,13 @@
*
* @param searchView The SearchView to operate on.
* @return whether the submit button is enabled automatically when necessary
+ *
+ * @deprecated Use {@link SearchView#isSubmitButtonEnabled()} directly.
*/
+ @Deprecated
public static boolean isSubmitButtonEnabled(View searchView) {
- return IMPL.isSubmitButtonEnabled(searchView);
+ checkIfLegalArg(searchView);
+ return ((SearchView) searchView).isSubmitButtonEnabled();
}
/**
@@ -524,25 +368,37 @@
*
* @see SearchManager#SUGGEST_COLUMN_FLAGS
* @see SearchManager#FLAG_QUERY_REFINEMENT
+ *
+ * @deprecated Use {@link SearchView#setQueryRefinementEnabled(boolean)} directly.
*/
+ @Deprecated
public static void setQueryRefinementEnabled(View searchView, boolean enable) {
- IMPL.setQueryRefinementEnabled(searchView, enable);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setQueryRefinementEnabled(enable);
}
/**
* Returns whether query refinement is enabled for all items or only specific ones.
* @param searchView The SearchView to operate on.
* @return true if enabled for all items, false otherwise.
+ *
+ * @deprecated Use {@link SearchView#isQueryRefinementEnabled()} directly.
*/
+ @Deprecated
public static boolean isQueryRefinementEnabled(View searchView) {
- return IMPL.isQueryRefinementEnabled(searchView);
+ checkIfLegalArg(searchView);
+ return ((SearchView) searchView).isQueryRefinementEnabled();
}
/**
* Makes the view at most this many pixels wide
* @param searchView The SearchView to operate on.
+ *
+ * @deprecated Use {@link SearchView#setMaxWidth(int)} directly.
*/
+ @Deprecated
public static void setMaxWidth(View searchView, int maxpixels) {
- IMPL.setMaxWidth(searchView, maxpixels);
+ checkIfLegalArg(searchView);
+ ((SearchView) searchView).setMaxWidth(maxpixels);
}
}
diff --git a/compat/jellybean/android/support/v4/net/ConnectivityManagerCompatJellyBean.java b/compat/jellybean/android/support/v4/net/ConnectivityManagerCompatJellyBean.java
deleted file mode 100644
index 7e47298..0000000
--- a/compat/jellybean/android/support/v4/net/ConnectivityManagerCompatJellyBean.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.net;
-
-import android.net.ConnectivityManager;
-import android.support.annotation.RequiresApi;
-
-/**
- * Implementation of ConnectivityManagerCompat that can use Jellybean APIs.
- */
-
-@RequiresApi(16)
-class ConnectivityManagerCompatJellyBean {
- public static boolean isActiveNetworkMetered(ConnectivityManager cm) {
- return cm.isActiveNetworkMetered();
- }
-}
diff --git a/compat/tests/java/android/support/v4/app/RemoteInputTest.java b/compat/tests/java/android/support/v4/app/RemoteInputTest.java
index 08fdf0e..4c3d81b 100644
--- a/compat/tests/java/android/support/v4/app/RemoteInputTest.java
+++ b/compat/tests/java/android/support/v4/app/RemoteInputTest.java
@@ -94,6 +94,7 @@
assertTrue(input.getAllowedDataTypes().contains(MIME_TYPE));
}
+ @SdkSuppress(minSdkVersion = 17)
@Test
public void testRemoteInputBuilder_addAndGetDataResultsFromIntent() throws Throwable {
Uri uri = Uri.parse("Some Uri");
@@ -106,6 +107,7 @@
verifyIntentHasDataResults(intent, uri);
}
+ @SdkSuppress(minSdkVersion = 17)
@Test
public void testRemoteInputBuilder_addAndGetTextResultsFromIntent() throws Throwable {
CharSequence charSequence = "value doesn't matter";
diff --git a/compat/tests/java/android/support/v4/graphics/PaintCompatHasGlyphTest.java b/compat/tests/java/android/support/v4/graphics/PaintCompatHasGlyphTest.java
index 202d30f..26f0691 100644
--- a/compat/tests/java/android/support/v4/graphics/PaintCompatHasGlyphTest.java
+++ b/compat/tests/java/android/support/v4/graphics/PaintCompatHasGlyphTest.java
@@ -16,6 +16,8 @@
package android.support.v4.graphics;
+import static android.os.Build.VERSION.SDK_INT;
+
import static org.junit.Assert.assertEquals;
import android.graphics.Paint;
@@ -37,10 +39,14 @@
return Arrays.asList(new Object[][]{
{"B", true},
{"\uDB3F\uDFFD", false},
- {"☺", true},
+ {"Ō", true},
+ {"£", true},
+ {"⅓", true},
{"Hello", false},
{"\u0020", true}, // white space
{"\t\t\t", false}, // more white space
+ {"☺", SDK_INT >= 16}, // glyph added in API 16
+ {"\uD83D\uDC66\uD83C\uDFFF", SDK_INT >= 24}, // glyph added in API 24
});
}
@@ -54,6 +60,8 @@
@Test
public void testHasGlyph() {
- assertEquals(mExpectedResult, PaintCompat.hasGlyph(new Paint(), mTestString));
+ final boolean hasGlyph = PaintCompat.hasGlyph(new Paint(), mTestString);
+ assertEquals("hasGlyph() returned " + hasGlyph + " for '" + mTestString + "'",
+ mExpectedResult, hasGlyph);
}
}
diff --git a/core-ui/tests/res/values/styles.xml b/core-ui/tests/res/values/styles.xml
index ae6325b..e530e60 100644
--- a/core-ui/tests/res/values/styles.xml
+++ b/core-ui/tests/res/values/styles.xml
@@ -13,8 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <style name="TestActivityTheme">
+<resources>
+ <style name="TestActivityTheme" parent="android:Theme.Holo">
<item name="android:windowAnimationStyle">@null</item>
</style>
<style name="TextMediumStyle" parent="@android:style/TextAppearance.Medium">
diff --git a/core-utils/honeycomb/android/support/v4/app/TaskStackBuilderHoneycomb.java b/core-utils/honeycomb/android/support/v4/app/TaskStackBuilderHoneycomb.java
deleted file mode 100644
index e41fdd8..0000000
--- a/core-utils/honeycomb/android/support/v4/app/TaskStackBuilderHoneycomb.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.app;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.support.annotation.RequiresApi;
-
-/**
- * Implementation of TaskStackBuilder that can call Honeycomb APIs.
- */
-@RequiresApi(11)
-class TaskStackBuilderHoneycomb {
- public static PendingIntent getActivitiesPendingIntent(Context context, int requestCode,
- Intent[] intents, int flags) {
- return PendingIntent.getActivities(context, requestCode, intents, flags);
- }
-}
diff --git a/core-utils/java/android/support/v4/app/NavUtils.java b/core-utils/java/android/support/v4/app/NavUtils.java
index f9661a7..ae1bb10 100644
--- a/core-utils/java/android/support/v4/app/NavUtils.java
+++ b/core-utils/java/android/support/v4/app/NavUtils.java
@@ -16,6 +16,7 @@
package android.support.v4.app;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
@@ -24,7 +25,6 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.support.annotation.Nullable;
-import android.support.v4.content.IntentCompat;
import android.util.Log;
/**
@@ -58,7 +58,7 @@
try {
final String grandparent = NavUtils.getParentActivityName(activity, target);
final Intent parentIntent = grandparent == null
- ? IntentCompat.makeMainActivity(target)
+ ? Intent.makeMainActivity(target)
: new Intent().setComponent(target);
return parentIntent;
} catch (NameNotFoundException e) {
@@ -93,6 +93,7 @@
}
}
+ @TargetApi(16)
static class NavUtilsImplJB extends NavUtilsImplBase {
@Override
@@ -236,7 +237,7 @@
final ComponentName target = new ComponentName(context, parentActivity);
final String grandparent = getParentActivityName(context, target);
final Intent parentIntent = grandparent == null
- ? IntentCompat.makeMainActivity(target)
+ ? Intent.makeMainActivity(target)
: new Intent().setComponent(target);
return parentIntent;
}
@@ -261,7 +262,7 @@
componentName.getPackageName(), parentActivity);
final String grandparent = getParentActivityName(context, target);
final Intent parentIntent = grandparent == null
- ? IntentCompat.makeMainActivity(target)
+ ? Intent.makeMainActivity(target)
: new Intent().setComponent(target);
return parentIntent;
}
diff --git a/core-utils/java/android/support/v4/app/TaskStackBuilder.java b/core-utils/java/android/support/v4/app/TaskStackBuilder.java
index 0358b46..d95e1a4 100644
--- a/core-utils/java/android/support/v4/app/TaskStackBuilder.java
+++ b/core-utils/java/android/support/v4/app/TaskStackBuilder.java
@@ -16,6 +16,7 @@
package android.support.v4.app;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -25,7 +26,6 @@
import android.os.Build;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
-import android.support.v4.content.IntentCompat;
import android.util.Log;
import java.util.ArrayList;
@@ -73,49 +73,32 @@
Intent getSupportParentActivityIntent();
}
- interface TaskStackBuilderImpl {
- PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
- int flags, Bundle options);
- }
-
- static class TaskStackBuilderImplBase implements TaskStackBuilderImpl {
+ static class TaskStackBuilderBaseImpl {
public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
int flags, Bundle options) {
- Intent topIntent = new Intent(intents[intents.length - 1]);
- topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- return PendingIntent.getActivity(context, requestCode, topIntent, flags);
+ intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+ return PendingIntent.getActivities(context, requestCode, intents, flags);
}
}
- static class TaskStackBuilderImplHoneycomb implements TaskStackBuilderImpl {
+ @TargetApi(16)
+ static class TaskStackBuilderApi16Impl extends TaskStackBuilderBaseImpl {
public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
int flags, Bundle options) {
- intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
- IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
- return TaskStackBuilderHoneycomb.getActivitiesPendingIntent(context, requestCode,
- intents, flags);
+ intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+ return PendingIntent.getActivities(context, requestCode, intents, flags, options);
}
}
- static class TaskStackBuilderImplJellybean implements TaskStackBuilderImpl {
- public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
- int flags, Bundle options) {
- intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
- IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
- return TaskStackBuilderJellybean.getActivitiesPendingIntent(context, requestCode,
- intents, flags, options);
- }
- }
-
- private static final TaskStackBuilderImpl IMPL;
+ private static final TaskStackBuilderBaseImpl IMPL;
static {
- if (Build.VERSION.SDK_INT >= 11) {
- IMPL = new TaskStackBuilderImplHoneycomb();
+ if (Build.VERSION.SDK_INT >= 16) {
+ IMPL = new TaskStackBuilderApi16Impl();
} else {
- IMPL = new TaskStackBuilderImplBase();
+ IMPL = new TaskStackBuilderBaseImpl();
}
}
@@ -322,9 +305,8 @@
}
Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
- intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
- IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
+ intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
if (!ContextCompat.startActivities(mSourceContext, intents, options)) {
Intent topIntent = new Intent(intents[intents.length - 1]);
topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -367,9 +349,8 @@
}
Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
- intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
- IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
+ intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
// Appropriate flags will be added by the call below.
return IMPL.getPendingIntent(mSourceContext, intents, requestCode, flags, options);
}
@@ -385,9 +366,8 @@
Intent[] intents = new Intent[mIntents.size()];
if (intents.length == 0) return intents;
- intents[0] = new Intent(mIntents.get(0)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
- IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
+ intents[0] = new Intent(mIntents.get(0)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
for (int i = 1; i < intents.length; i++) {
intents[i] = new Intent(mIntents.get(i));
}
diff --git a/core-utils/java/android/support/v4/content/res/TypedArrayUtils.java b/core-utils/java/android/support/v4/content/res/TypedArrayUtils.java
deleted file mode 100644
index be4ff11..0000000
--- a/core-utils/java/android/support/v4/content/res/TypedArrayUtils.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.v4.content.res;
-
-import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.AnyRes;
-import android.support.annotation.RestrictTo;
-import android.support.annotation.StyleableRes;
-import android.util.TypedValue;
-
-/**
- * Compat methods for accessing TypedArray values.
- *
- * @hide
- */
-@RestrictTo(LIBRARY_GROUP)
-public class TypedArrayUtils {
- public static boolean getBoolean(TypedArray a, @StyleableRes int index,
- @StyleableRes int fallbackIndex, boolean defaultValue) {
- boolean val = a.getBoolean(fallbackIndex, defaultValue);
- return a.getBoolean(index, val);
- }
-
- public static Drawable getDrawable(TypedArray a, @StyleableRes int index,
- @StyleableRes int fallbackIndex) {
- Drawable val = a.getDrawable(index);
- if (val == null) {
- val = a.getDrawable(fallbackIndex);
- }
- return val;
- }
-
- public static int getInt(TypedArray a, @StyleableRes int index,
- @StyleableRes int fallbackIndex, int defaultValue) {
- int val = a.getInt(fallbackIndex, defaultValue);
- return a.getInt(index, val);
- }
-
- public static @AnyRes int getResourceId(TypedArray a, @StyleableRes int index,
- @StyleableRes int fallbackIndex, @AnyRes int defaultValue) {
- int val = a.getResourceId(fallbackIndex, defaultValue);
- return a.getResourceId(index, val);
- }
-
- public static String getString(TypedArray a, @StyleableRes int index,
- @StyleableRes int fallbackIndex) {
- String val = a.getString(index);
- if (val == null) {
- val = a.getString(fallbackIndex);
- }
- return val;
- }
-
- public static CharSequence getText(TypedArray a, @StyleableRes int index,
- @StyleableRes int fallbackIndex) {
- CharSequence val = a.getText(index);
- if (val == null) {
- val = a.getText(fallbackIndex);
- }
- return val;
- }
-
- public static CharSequence[] getTextArray(TypedArray a, @StyleableRes int index,
- @StyleableRes int fallbackIndex) {
- CharSequence[] val = a.getTextArray(index);
- if (val == null) {
- val = a.getTextArray(fallbackIndex);
- }
- return val;
- }
-
- public static int getAttr(Context context, int attr, int fallbackAttr) {
- TypedValue value = new TypedValue();
- context.getTheme().resolveAttribute(attr, value, true);
- if (value.resourceId != 0) {
- return attr;
- }
- return fallbackAttr;
- }
-}
diff --git a/core-utils/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java b/core-utils/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java
deleted file mode 100644
index 2a18971..0000000
--- a/core-utils/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-package android.support.v4.app;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.RequiresApi;
-
-@RequiresApi(16)
-class TaskStackBuilderJellybean {
-
- public static PendingIntent getActivitiesPendingIntent(Context context, int requestCode,
- Intent[] intents, int flags, Bundle options) {
- return PendingIntent.getActivities(context, requestCode, intents, flags, options);
- }
-
-}
diff --git a/design/src/android/support/design/widget/TabLayout.java b/design/src/android/support/design/widget/TabLayout.java
index 7f3e231..8b81eaa 100755
--- a/design/src/android/support/design/widget/TabLayout.java
+++ b/design/src/android/support/design/widget/TabLayout.java
@@ -1084,17 +1084,7 @@
final int targetScrollX = calculateScrollXForTab(newPosition, 0);
if (startScrollX != targetScrollX) {
- if (mScrollAnimator == null) {
- mScrollAnimator = new ValueAnimator();
- mScrollAnimator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
- mScrollAnimator.setDuration(ANIMATION_DURATION);
- mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animator) {
- scrollTo((int) animator.getAnimatedValue(), 0);
- }
- });
- }
+ ensureScrollAnimator();
mScrollAnimator.setIntValues(startScrollX, targetScrollX);
mScrollAnimator.start();
@@ -1104,6 +1094,25 @@
mTabStrip.animateIndicatorToPosition(newPosition, ANIMATION_DURATION);
}
+ private void ensureScrollAnimator() {
+ if (mScrollAnimator == null) {
+ mScrollAnimator = new ValueAnimator();
+ mScrollAnimator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
+ mScrollAnimator.setDuration(ANIMATION_DURATION);
+ mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animator) {
+ scrollTo((int) animator.getAnimatedValue(), 0);
+ }
+ });
+ }
+ }
+
+ void setScrollAnimatorListener(Animator.AnimatorListener listener) {
+ ensureScrollAnimator();
+ mScrollAnimator.addListener(listener);
+ }
+
private void setSelectedTabView(int position) {
final int tabCount = mTabStrip.getChildCount();
if (position < tabCount) {
@@ -1177,10 +1186,14 @@
final int selectedWidth = selectedChild != null ? selectedChild.getWidth() : 0;
final int nextWidth = nextChild != null ? nextChild.getWidth() : 0;
- return selectedChild.getLeft()
- + ((int) ((selectedWidth + nextWidth) * positionOffset * 0.5f))
- + (selectedChild.getWidth() / 2)
- - (getWidth() / 2);
+ // base scroll amount: places center of tab in center of parent
+ int scrollBase = selectedChild.getLeft() + (selectedWidth / 2) - (getWidth() / 2);
+ // offset amount: fraction of the distance between centers of tabs
+ int scrollOffset = (int) ((selectedWidth + nextWidth) * 0.5f * positionOffset);
+
+ return (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_LTR)
+ ? scrollBase + scrollOffset
+ : scrollBase - scrollOffset;
}
return 0;
}
diff --git a/design/tests/res/layout/design_tabs_fixed_width.xml b/design/tests/res/layout/design_tabs_fixed_width.xml
new file mode 100644
index 0000000..752034f
--- /dev/null
+++ b/design/tests/res/layout/design_tabs_fixed_width.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Width is fixed to test scrolling -->
+<android.support.design.widget.TabLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/tabs"
+ android:layout_width="160dp"
+ android:layout_height="wrap_content"
+ app:tabMode="scrollable">
+
+ <android.support.design.widget.TabItem
+ android:text="Tab 0" />
+
+ <android.support.design.widget.TabItem
+ android:text="Tab 1" />
+
+ <android.support.design.widget.TabItem
+ android:text="Tab 2" />
+
+ <android.support.design.widget.TabItem
+ android:text="Tab 3" />
+
+ <android.support.design.widget.TabItem
+ android:text="Tab 4" />
+
+ <android.support.design.widget.TabItem
+ android:text="Tab 5" />
+
+ <android.support.design.widget.TabItem
+ android:text="Tab 6" />
+
+ <android.support.design.widget.TabItem
+ android:text="Tab 7" />
+
+</android.support.design.widget.TabLayout>
diff --git a/design/tests/src/android/support/design/testutils/TabLayoutActions.java b/design/tests/src/android/support/design/testutils/TabLayoutActions.java
index 149b14f..7c17850 100644
--- a/design/tests/src/android/support/design/testutils/TabLayoutActions.java
+++ b/design/tests/src/android/support/design/testutils/TabLayoutActions.java
@@ -16,23 +16,17 @@
package android.support.design.testutils;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
+
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
-import android.support.test.espresso.action.CoordinatesProvider;
-import android.support.test.espresso.action.GeneralClickAction;
-import android.support.test.espresso.action.Press;
-import android.support.test.espresso.action.Tap;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.PagerTitleStrip;
+import android.support.test.espresso.matcher.ViewMatchers;
import android.support.v4.view.ViewPager;
import android.view.View;
-import android.widget.TextView;
-import org.hamcrest.Matcher;
-import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
+import org.hamcrest.Matcher;
public class TabLayoutActions {
/**
@@ -143,4 +137,30 @@
}
};
}
+
+ /**
+ * Calls <code>setScrollPosition(position, positionOffset, true)</code> on the
+ * <code>TabLayout</code>
+ */
+ public static ViewAction setScrollPosition(final int position, final float positionOffset) {
+ return new ViewAction() {
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return ViewMatchers.isAssignableFrom(TabLayout.class);
+ }
+
+ @Override
+ public String getDescription() {
+ return "setScrollPosition(" + position + ", " + positionOffset + ", true)";
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ TabLayout tabs = (TabLayout) view;
+ tabs.setScrollPosition(position, positionOffset, true);
+ uiController.loopMainThreadUntilIdle();
+ }
+ };
+ }
}
diff --git a/design/tests/src/android/support/design/widget/TabLayoutTest.java b/design/tests/src/android/support/design/widget/TabLayoutTest.java
index cb4e669..1806019 100755
--- a/design/tests/src/android/support/design/widget/TabLayoutTest.java
+++ b/design/tests/src/android/support/design/widget/TabLayoutTest.java
@@ -16,6 +16,12 @@
package android.support.design.widget;
+import static android.support.design.testutils.TabLayoutActions.selectTab;
+import static android.support.design.testutils.TabLayoutActions.setScrollPosition;
+import static android.support.design.testutils.TestUtilsActions.setLayoutDirection;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -27,11 +33,18 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.os.Build;
import android.support.design.test.R;
import android.support.test.annotation.UiThreadTest;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.IdlingResource;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.ViewAssertion;
import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
+import android.support.v4.view.ViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.InflateException;
import android.view.LayoutInflater;
@@ -41,6 +54,8 @@
import org.junit.Test;
+import java.util.concurrent.atomic.AtomicInteger;
+
@SmallTest
public class TabLayoutTest extends BaseInstrumentationTestCase<AppCompatActivity> {
public TabLayoutTest() {
@@ -210,4 +225,105 @@
}
}
}
+
+ @Test
+ public void setScrollPositionLtr() throws Throwable {
+ testSetScrollPosition(true);
+ }
+
+ @Test
+ public void setScrollPositionRtl() throws Throwable {
+ testSetScrollPosition(false);
+ }
+
+ private void testSetScrollPosition(final boolean isLtr) throws Throwable {
+ mActivityTestRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivityTestRule.getActivity().setContentView(R.layout.design_tabs_fixed_width);
+ }
+ });
+ final TabLayout tabs = (TabLayout) mActivityTestRule.getActivity().findViewById(R.id.tabs);
+ assertEquals(TabLayout.MODE_SCROLLABLE, tabs.getTabMode());
+
+ final TabLayoutScrollIdlingResource idler = new TabLayoutScrollIdlingResource(tabs);
+ Espresso.registerIdlingResources(idler);
+
+ // We're going to call setScrollPosition() incrementally, as if scrolling between one tab
+ // and the next. Use the middle tab for best results. The positionOffsets should be in the
+ // range [0, 1), so the final call will wrap to 0 but use the next tab's position.
+ final int middleTab = tabs.getTabCount() / 2;
+ final int[] positions = {middleTab, middleTab, middleTab, middleTab, middleTab + 1};
+ final float[] positionOffsets = {0f, .25f, .5f, .75f, 0f};
+
+ // Set layout direction
+ onView(withId(R.id.tabs)).perform(setLayoutDirection(
+ isLtr ? ViewCompat.LAYOUT_DIRECTION_LTR : ViewCompat.LAYOUT_DIRECTION_RTL));
+ // Make sure it's scrolled all the way to the start
+ onView(withId(R.id.tabs)).perform(selectTab(0));
+
+ // Perform a series of setScrollPosition() calls
+ final AtomicInteger lastScrollX = new AtomicInteger(tabs.getScrollX());
+ for (int i = 0; i < positions.length; i++) {
+ onView(withId(R.id.tabs))
+ .perform(setScrollPosition(positions[i], positionOffsets[i]))
+ .check(new ViewAssertion() {
+ @Override
+ public void check(View view, NoMatchingViewException notFoundException) {
+ if (view == null) {
+ throw notFoundException;
+ }
+ // Verify increasing or decreasing scroll X values
+ int sx = view.getScrollX();
+ assertTrue(isLtr ? sx > lastScrollX.get() : sx < lastScrollX.get());
+ lastScrollX.set(sx);
+ }
+ });
+ }
+
+ Espresso.unregisterIdlingResources(idler);
+ }
+
+ static class TabLayoutScrollIdlingResource implements IdlingResource {
+
+ private boolean mIsIdle = true;
+ private ResourceCallback mCallback;
+
+ TabLayoutScrollIdlingResource(final TabLayout tabLayout) {
+ tabLayout.setScrollAnimatorListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ setIdle(false);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ setIdle(true);
+ }
+ });
+ }
+
+ @Override
+ public String getName() {
+ return "TabLayoutScrollIdlingResource";
+ }
+
+ @Override
+ public boolean isIdleNow() {
+ return mIsIdle;
+ }
+
+ @Override
+ public void registerIdleTransitionCallback(ResourceCallback callback) {
+ mCallback = callback;
+ }
+
+ private void setIdle(boolean idle) {
+ boolean wasIdle = mIsIdle;
+ mIsIdle = idle;
+ if (mIsIdle && !wasIdle && mCallback != null) {
+ mCallback.onTransitionToIdle();
+ }
+ }
+ }
}
diff --git a/exifinterface/src/android/support/media/ExifInterface.java b/exifinterface/src/android/support/media/ExifInterface.java
index fccab43..4830ecc 100644
--- a/exifinterface/src/android/support/media/ExifInterface.java
+++ b/exifinterface/src/android/support/media/ExifInterface.java
@@ -1850,11 +1850,31 @@
}
/**
- * Stores the latitude and longitude value in a float array. The first element is
- * the latitude, and the second element is the longitude. Returns false if the
- * Exif tags are not available.
+ * Stores the latitude and longitude value in a float array. The first element is the latitude,
+ * and the second element is the longitude. Returns false if the Exif tags are not available.
+ *
+ * @deprecated Use {@link #getLatLong()} instead.
*/
+ @Deprecated
public boolean getLatLong(float output[]) {
+ double[] latLong = getLatLong();
+ if (latLong == null) {
+ return false;
+ }
+
+ output[0] = (float) latLong[0];
+ output[1] = (float) latLong[1];
+ return true;
+ }
+
+ /**
+ * Gets the latitude and longitude values.
+ * <p>
+ * If there are valid latitude and longitude values in the image, this method returns a double
+ * array where the first element is the latitude and the second element is the longitude.
+ * Otherwise, it returns null.
+ */
+ public double[] getLatLong() {
String latValue = getAttribute(TAG_GPS_LATITUDE);
String latRef = getAttribute(TAG_GPS_LATITUDE_REF);
String lngValue = getAttribute(TAG_GPS_LONGITUDE);
@@ -1862,16 +1882,39 @@
if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
try {
- output[0] = convertRationalLatLonToFloat(latValue, latRef);
- output[1] = convertRationalLatLonToFloat(lngValue, lngRef);
- return true;
+ double latitude = convertRationalLatLonToDouble(latValue, latRef);
+ double longitude = convertRationalLatLonToDouble(lngValue, lngRef);
+ return new double[] {latitude, longitude};
} catch (IllegalArgumentException e) {
Log.w(TAG, "Latitude/longitude values are not parseable. " +
String.format("latValue=%s, latRef=%s, lngValue=%s, lngRef=%s",
latValue, latRef, lngValue, lngRef));
}
}
- return false;
+ return null;
+ }
+
+ /**
+ * Sets the latitude and longitude values.
+ *
+ * @param latitude the decimal value of latitude. Must be a valid double value between -90.0 and
+ * 90.0.
+ * @param longitude the decimal value of longitude. Must be a valid double value between -180.0
+ * and 180.0.
+ * @throws IllegalArgumentException If {@code latitude} or {@code longitude} is outside the
+ * specified range.
+ */
+ public void setLatLong(double latitude, double longitude) {
+ if (latitude < -90.0 || latitude > 90.0 || Double.isNaN(latitude)) {
+ throw new IllegalArgumentException("Latitude value " + latitude + " is not valid.");
+ }
+ if (longitude < -180.0 || longitude > 180.0 || Double.isNaN(longitude)) {
+ throw new IllegalArgumentException("Longitude value " + longitude + " is not valid.");
+ }
+ setAttribute(TAG_GPS_LATITUDE_REF, latitude >= 0 ? "N" : "S");
+ setAttribute(TAG_GPS_LATITUDE, convertDecimalDegree(Math.abs(latitude)));
+ setAttribute(TAG_GPS_LONGITUDE_REF, longitude >= 0 ? "E" : "W");
+ setAttribute(TAG_GPS_LONGITUDE, convertDecimalDegree(Math.abs(longitude)));
}
/**
@@ -1953,7 +1996,7 @@
}
}
- private static float convertRationalLatLonToFloat(String rationalString, String ref) {
+ private static double convertRationalLatLonToDouble(String rationalString, String ref) {
try {
String [] parts = rationalString.split(",");
@@ -1972,15 +2015,26 @@
double result = degrees + (minutes / 60.0) + (seconds / 3600.0);
if ((ref.equals("S") || ref.equals("W"))) {
- return (float) -result;
+ return -result;
+ } else if (ref.equals("N") || ref.equals("E")) {
+ return result;
+ } else {
+ // Not valid
+ throw new IllegalArgumentException();
}
- return (float) result;
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
// Not valid
throw new IllegalArgumentException();
}
}
+ private String convertDecimalDegree(double decimalDegree) {
+ long degrees = (long) decimalDegree;
+ long minutes = (long) ((decimalDegree - degrees) * 60.0);
+ long seconds = Math.round((decimalDegree - degrees - minutes / 60.0) * 3600.0 * 1e7);
+ return degrees + "/1," + minutes + "/1," + seconds + "/10000000";
+ }
+
// Checks the type of image file
private int getMimeType(BufferedInputStream in) throws IOException {
in.mark(SIGNATURE_CHECK_SIZE);
diff --git a/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java b/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
index 87fb950..ee9e38e 100644
--- a/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
+++ b/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
@@ -16,6 +16,13 @@
package android.support.media;
+import static android.support.test.InstrumentationRegistry.getContext;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.fail;
+
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.os.Environment;
@@ -40,12 +47,6 @@
import java.io.InputStream;
import java.io.OutputStream;
-import static android.support.test.InstrumentationRegistry.getContext;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.fail;
-
/**
* Test {@link ExifInterface}.
*/
@@ -53,7 +54,6 @@
public class ExifInterfaceTest {
private static final String TAG = ExifInterface.class.getSimpleName();
private static final boolean VERBOSE = false; // lots of logging
-
private static final double DIFFERENCE_TOLERANCE = .001;
private static final String EXIF_BYTE_ORDER_II_JPEG = "image_exif_byte_order_ii.jpg";
@@ -64,6 +64,20 @@
private static final String[] IMAGE_FILENAMES = new String[] {
EXIF_BYTE_ORDER_II_JPEG, EXIF_BYTE_ORDER_MM_JPEG, LG_G4_ISO_800_DNG};
+ private static final String TEST_TEMP_FILE_NAME = "testImage";
+ private static final double DELTA = 1e-8;
+ private static final int TEST_LAT_LONG_VALUES_ARRAY_LENGTH = 8;
+ private static final double[] TEST_LATITUDE_VALID_VALUES = new double[]
+ {0, 45, 90, -60, 0.00000001, -89.999999999, 14.2465923626, -68.3434534737};
+ private static final double[] TEST_LONGITUDE_VALID_VALUES = new double[]
+ {0, -45, 90, -120, 180, 0.00000001, -179.99999999999, -58.57834236352};
+ private static final double[] TEST_LATITUDE_INVALID_VALUES = new double[]
+ {Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 90.0000000001,
+ 263.34763236326, -1e5, 347.32525, -176.346347754};
+ private static final double[] TEST_LONGITUDE_INVALID_VALUES = new double[]
+ {Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 180.0000000001,
+ 263.34763236326, -1e10, 347.325252623, -4000.346323236};
+
private static final String[] EXIF_TAGS = {
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
@@ -235,6 +249,52 @@
}
}
+ @Test
+ @SmallTest
+ public void testSetLatLong_withValidValues() throws IOException {
+ for (int i = 0; i < TEST_LAT_LONG_VALUES_ARRAY_LENGTH; i++) {
+ ExifInterface exif = createTestExifInterface();
+ exif.setLatLong(TEST_LATITUDE_VALID_VALUES[i], TEST_LONGITUDE_VALID_VALUES[i]);
+
+ double[] latLong = exif.getLatLong();
+ assertNotNull(latLong);
+ assertEquals(TEST_LATITUDE_VALID_VALUES[i], latLong[0], DELTA);
+ assertEquals(TEST_LONGITUDE_VALID_VALUES[i], latLong[1], DELTA);
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void testSetLatLong_withInvalidLatitude() throws IOException {
+ for (int i = 0; i < TEST_LAT_LONG_VALUES_ARRAY_LENGTH; i++) {
+ ExifInterface exif = createTestExifInterface();
+ try {
+ exif.setLatLong(TEST_LATITUDE_INVALID_VALUES[i], TEST_LONGITUDE_VALID_VALUES[i]);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ assertNull(exif.getLatLong());
+ assertLatLongValuesAreNotSet(exif);
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void testSetLatLong_withInvalidLongitude() throws IOException {
+ for (int i = 0; i < TEST_LAT_LONG_VALUES_ARRAY_LENGTH; i++) {
+ ExifInterface exif = createTestExifInterface();
+ try {
+ exif.setLatLong(TEST_LATITUDE_VALID_VALUES[i], TEST_LONGITUDE_INVALID_VALUES[i]);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ assertNull(exif.getLatLong());
+ assertLatLongValuesAreNotSet(exif);
+ }
+ }
+
private void printExifTagsAndValues(String fileName, ExifInterface exifInterface) {
// Prints thumbnail information.
if (exifInterface.hasThumbnail()) {
@@ -264,8 +324,8 @@
// Prints GPS information.
Log.v(TAG, fileName + " Altitude = " + exifInterface.getAltitude(.0));
- float[] latLong = new float[2];
- if (exifInterface.getLatLong(latLong)) {
+ double[] latLong = exifInterface.getLatLong();
+ if (latLong != null) {
Log.v(TAG, fileName + " Latitude = " + latLong[0]);
Log.v(TAG, fileName + " Longitude = " + latLong[1]);
} else {
@@ -318,8 +378,8 @@
}
// Checks GPS information.
- float[] latLong = new float[2];
- assertEquals(expectedValue.hasLatLong, exifInterface.getLatLong(latLong));
+ double[] latLong = exifInterface.getLatLong();
+ assertEquals(expectedValue.hasLatLong, latLong != null);
if (expectedValue.hasLatLong) {
assertEquals(expectedValue.latitude, latLong[0], DIFFERENCE_TOLERANCE);
assertEquals(expectedValue.longitude, latLong[1], DIFFERENCE_TOLERANCE);
@@ -443,4 +503,17 @@
}
return total;
}
+
+ private void assertLatLongValuesAreNotSet(ExifInterface exif) {
+ assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
+ assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF));
+ assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
+ assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF));
+ }
+
+ private ExifInterface createTestExifInterface() throws IOException {
+ File image = File.createTempFile(TEST_TEMP_FILE_NAME, ".jpg");
+ image.deleteOnExit();
+ return new ExifInterface(image.getAbsolutePath());
+ }
}
diff --git a/fragment/java/android/support/v4/app/BackStackRecord.java b/fragment/java/android/support/v4/app/BackStackRecord.java
index 0debe7a..108d2e6 100644
--- a/fragment/java/android/support/v4/app/BackStackRecord.java
+++ b/fragment/java/android/support/v4/app/BackStackRecord.java
@@ -798,8 +798,11 @@
/**
* Reverses the execution of the operations within this transaction. The Fragment states will
* only be modified if optimizations are not allowed.
+ *
+ * @param moveToState {@code true} if added fragments should be moved to their final state
+ * in unoptimized transactions
*/
- void executePopOps() {
+ void executePopOps(boolean moveToState) {
for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
final Op op = mOps.get(opNum);
Fragment f = op.fragment;
@@ -845,7 +848,7 @@
mManager.moveFragmentToExpectedState(f);
}
}
- if (!mAllowOptimization) {
+ if (!mAllowOptimization && moveToState) {
mManager.moveToState(mManager.mCurState, true);
}
}
diff --git a/fragment/java/android/support/v4/app/Fragment.java b/fragment/java/android/support/v4/app/Fragment.java
index 297d4bf..09b1464 100644
--- a/fragment/java/android/support/v4/app/Fragment.java
+++ b/fragment/java/android/support/v4/app/Fragment.java
@@ -66,9 +66,9 @@
final boolean mDetached;
final Bundle mArguments;
final boolean mHidden;
-
+
Bundle mSavedFragmentState;
-
+
Fragment mInstance;
public FragmentState(Fragment frag) {
@@ -83,7 +83,7 @@
mArguments = frag.mArguments;
mHidden = frag.mHidden;
}
-
+
public FragmentState(Parcel in) {
mClassName = in.readString();
mIndex = in.readInt();
@@ -153,7 +153,7 @@
dest.writeInt(mHidden? 1 : 0);
dest.writeBundle(mSavedFragmentState);
}
-
+
public static final Parcelable.Creator<FragmentState> CREATOR
= new Parcelable.Creator<FragmentState>() {
@Override
@@ -195,19 +195,19 @@
static final int STOPPED = 3; // Fully created, not started.
static final int STARTED = 4; // Created and started, not resumed.
static final int RESUMED = 5; // Created started and resumed.
-
+
int mState = INITIALIZING;
-
+
// When instantiated from saved state, this is the saved state.
Bundle mSavedFragmentState;
SparseArray<Parcelable> mSavedViewState;
-
+
// Index into active fragment array.
int mIndex = -1;
-
+
// Internal unique name for this fragment;
String mWho;
-
+
// Construction arguments;
Bundle mArguments;
@@ -222,13 +222,13 @@
// True if the fragment is in the list of added fragments.
boolean mAdded;
-
+
// If set this fragment is being removed from its activity.
boolean mRemoving;
-
+
// Set to true if this fragment was instantiated from a layout file.
boolean mFromLayout;
-
+
// Set to true when the view has actually been inflated in its layout.
boolean mInLayout;
@@ -264,19 +264,19 @@
// was dynamically added to the view hierarchy, or the ID supplied in
// layout.
int mFragmentId;
-
+
// When a fragment is being dynamically added to the view hierarchy, this
// is the identifier of the parent container it is being added to.
int mContainerId;
-
+
// The optional named tag for this fragment -- usually used to find
// fragments that are not part of the layout.
String mTag;
-
+
// Set to true when the app has requested that this fragment be hidden
// from the user.
boolean mHidden;
-
+
// Set to true when the app has requested that this fragment be deactivated.
boolean mDetached;
@@ -286,7 +286,7 @@
// If set this fragment is being retained across the current config change.
boolean mRetaining;
-
+
// If set this fragment has menu items to contribute.
boolean mHasMenu;
@@ -295,20 +295,20 @@
// Used to verify that subclasses call through to super class.
boolean mCalled;
-
+
// The parent container of the fragment after dynamically added to UI.
ViewGroup mContainer;
-
+
// The View generated for this fragment.
View mView;
-
+
// The real inner view that will save/restore state.
View mInnerView;
// Whether this fragment should defer starting until after other fragments
// have been started and their loaders are finished.
boolean mDeferStart;
-
+
// Hint provided by the app that this fragment is currently visible to the user.
boolean mUserVisibleHint = true;
@@ -395,7 +395,7 @@
* will not be called when the fragment is re-instantiated; instead,
* arguments can be supplied by the caller with {@link #setArguments}
* and later retrieved by the Fragment with {@link #getArguments}.
- *
+ *
* <p>Applications should generally not implement a constructor. Prefer
* {@link #onAttach(Context)} instead. It is the first place application code can run where
* the fragment is ready to be used - the point where the fragment is actually associated with
@@ -477,7 +477,7 @@
return false;
}
}
-
+
final void restoreViewState(Bundle savedInstanceState) {
if (mSavedViewState != null) {
mInnerView.restoreHierarchyState(mSavedViewState);
@@ -517,7 +517,7 @@
@Override final public int hashCode() {
return super.hashCode();
}
-
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
@@ -537,7 +537,7 @@
sb.append('}');
return sb.toString();
}
-
+
/**
* Return the identifier this fragment is known by. This is either
* the android:id value supplied in a layout or the container view ID
@@ -546,14 +546,14 @@
final public int getId() {
return mFragmentId;
}
-
+
/**
* Get the tag name of the fragment, if specified.
*/
final public String getTag() {
return mTag;
}
-
+
/**
* Supply the construction arguments for this fragment.
* The arguments supplied here will be retained across fragment destroy and
@@ -796,7 +796,7 @@
final public boolean isRemoving() {
return mRemoving;
}
-
+
/**
* Return true if the layout is included as part of an activity view
* hierarchy via the <fragment> tag. This will always be true when
@@ -815,17 +815,17 @@
final public boolean isResumed() {
return mState >= RESUMED;
}
-
+
/**
* Return true if the fragment is currently visible to the user. This means
- * it: (1) has been added, (2) has its view attached to the window, and
+ * it: (1) has been added, (2) has its view attached to the window, and
* (3) is not hidden.
*/
final public boolean isVisible() {
return isAdded() && !isHidden() && mView != null
&& mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
}
-
+
/**
* Return true if the fragment has been hidden. By default fragments
* are shown. You can find out about changes to this state with
@@ -857,7 +857,7 @@
*/
public void onHiddenChanged(boolean hidden) {
}
-
+
/**
* Control whether a fragment instance is retained across Activity
* re-creation (such as from a configuration change). This can only
@@ -875,11 +875,11 @@
public void setRetainInstance(boolean retain) {
mRetainInstance = retain;
}
-
+
final public boolean getRetainInstance() {
return mRetainInstance;
}
-
+
/**
* Report that this fragment would like to participate in populating
* the options menu by receiving a call to {@link #onCreateOptionsMenu}
@@ -1181,7 +1181,7 @@
* tag in a layout file. Note this is <em>before</em> the fragment's
* {@link #onAttach(Activity)} has been called; all you should do here is
* parse the attributes and save them away.
- *
+ *
* <p>This is called every time the fragment is inflated, even if it is
* being inflated into a new instance with saved state. It typically makes
* sense to re-parse the parameters each time, to allow them to change with
@@ -1197,7 +1197,7 @@
* declaration for the styleable used here is:</p>
*
* {@sample frameworks/support/samples/Support4Demos/res/values/attrs.xml fragment_arguments}
- *
+ *
* <p>The fragment can then be declared within its activity's content layout
* through a tag like this:</p>
*
@@ -1287,7 +1287,7 @@
* Called to do initial creation of a fragment. This is called after
* {@link #onAttach(Activity)} and before
* {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
- *
+ *
* <p>Note that this can be called while the fragment's activity is
* still in the process of being created. As such, you can not rely
* on things like the activity's content view hierarchy being initialized
@@ -1296,7 +1296,7 @@
*
* <p>Any restored child fragments will be created before the base
* <code>Fragment.onCreate</code> method returns.</p>
- *
+ *
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
@@ -1342,10 +1342,10 @@
* This is optional, and non-graphical fragments can return null (which
* is the default implementation). This will be called between
* {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}.
- *
+ *
* <p>If you return a View from here, you will later be called in
* {@link #onDestroyView} when the view is being released.
- *
+ *
* @param inflater The LayoutInflater object that can be used to inflate
* any views in the fragment,
* @param container If non-null, this is the parent view that the fragment's
@@ -1353,7 +1353,7 @@
* but this can be used to generate the LayoutParams of the view.
* @param savedInstanceState If non-null, this fragment is being re-constructed
* from a previous saved state as given here.
- *
+ *
* @return Return the View for the fragment's UI, or null.
*/
@Nullable
@@ -1378,14 +1378,14 @@
/**
* Get the root view for the fragment's layout (the one returned by {@link #onCreateView}),
* if provided.
- *
+ *
* @return The fragment's root view, or null if it has no layout.
*/
@Nullable
public View getView() {
return mView;
}
-
+
/**
* Called when the fragment's activity has been created and this
* fragment's view hierarchy instantiated. It can be used to do final
@@ -1451,7 +1451,7 @@
public void onResume() {
mCalled = true;
}
-
+
/**
* Called to ask the fragment to save its current dynamic state, so it
* can later be reconstructed in a new instance of its process is
@@ -1508,7 +1508,7 @@
public void onPause() {
mCalled = true;
}
-
+
/**
* Called when the Fragment is no longer started. This is generally
* tied to {@link Activity#onStop() Activity.onStop} of the containing
@@ -1524,7 +1524,7 @@
public void onLowMemory() {
mCalled = true;
}
-
+
/**
* Called when the view previously created by {@link #onCreateView} has
* been detached from the fragment. The next time the fragment needs
@@ -1538,7 +1538,7 @@
public void onDestroyView() {
mCalled = true;
}
-
+
/**
* Called when the fragment is no longer in use. This is called
* after {@link #onStop()} and before {@link #onDetach()}.
@@ -1594,16 +1594,16 @@
public void onDetach() {
mCalled = true;
}
-
+
/**
* Initialize the contents of the Fragment host's standard options menu. You
* should place your menu items in to <var>menu</var>. For this method
* to be called, you must have first called {@link #setHasOptionsMenu}. See
* {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu}
* for more information.
- *
+ *
* @param menu The options menu in which you place your items.
- *
+ *
* @see #setHasOptionsMenu
* @see #onPrepareOptionsMenu
* @see #onOptionsItemSelected
@@ -1618,10 +1618,10 @@
* dynamically modify the contents. See
* {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu}
* for more information.
- *
+ *
* @param menu The options menu as last shown or first initialized by
* onCreateOptionsMenu().
- *
+ *
* @see #setHasOptionsMenu
* @see #onCreateOptionsMenu
*/
@@ -1637,7 +1637,7 @@
*/
public void onDestroyOptionsMenu() {
}
-
+
/**
* This hook is called whenever an item in your options menu is selected.
* The default implementation simply returns false to have the normal
@@ -1645,15 +1645,15 @@
* its Handler as appropriate). You can use this method for any items
* for which you would like to do processing without those other
* facilities.
- *
+ *
* <p>Derived classes should call through to the base class for it to
* perform the default menu handling.
- *
+ *
* @param item The menu item that was selected.
- *
+ *
* @return boolean Return false to allow normal menu processing to
* proceed, true to consume it here.
- *
+ *
* @see #onCreateOptionsMenu
*/
public boolean onOptionsItemSelected(MenuItem item) {
@@ -1663,13 +1663,13 @@
/**
* This hook is called whenever the options menu is being closed (either by the user canceling
* the menu with the back/menu button, or when an item is selected).
- *
+ *
* @param menu The options menu as last shown or first initialized by
* onCreateOptionsMenu().
*/
public void onOptionsMenuClosed(Menu menu) {
}
-
+
/**
* Called when a context menu for the {@code view} is about to be shown.
* Unlike {@link #onCreateOptionsMenu}, this will be called every
@@ -1698,25 +1698,25 @@
* {@link OnCreateContextMenuListener} on the view to this fragment, so
* {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be
* called when it is time to show the context menu.
- *
+ *
* @see #unregisterForContextMenu(View)
* @param view The view that should show a context menu.
*/
public void registerForContextMenu(View view) {
view.setOnCreateContextMenuListener(this);
}
-
+
/**
* Prevents a context menu to be shown for the given view. This method will
* remove the {@link OnCreateContextMenuListener} on the view.
- *
+ *
* @see #registerForContextMenu(View)
* @param view The view that should stop showing a context menu.
*/
public void unregisterForContextMenu(View view) {
view.setOnCreateContextMenuListener(null);
}
-
+
/**
* This hook is called whenever an item in a context menu is selected. The
* default implementation simply returns false to have the normal processing
@@ -1729,7 +1729,7 @@
* <p>
* Derived classes should call through to the base class for it to perform
* the default menu handling.
- *
+ *
* @param item The context menu item that was selected.
* @return boolean Return false to allow normal context menu processing to
* proceed, true to consume it here.
diff --git a/fragment/java/android/support/v4/app/FragmentManager.java b/fragment/java/android/support/v4/app/FragmentManager.java
index 97c13c0..17b6306 100644
--- a/fragment/java/android/support/v4/app/FragmentManager.java
+++ b/fragment/java/android/support/v4/app/FragmentManager.java
@@ -2283,7 +2283,7 @@
if (isPop) {
record.executeOps();
} else {
- record.executePopOps();
+ record.executePopOps(false);
}
// move to the end
@@ -2402,7 +2402,10 @@
final boolean isPop = isRecordPop.get(i);
if (isPop) {
record.bumpBackStackNesting(-1);
- record.executePopOps();
+ // Only execute the add operations at the end of
+ // all transactions.
+ boolean moveToState = i == (endIndex - 1);
+ record.executePopOps(moveToState);
} else {
record.bumpBackStackNesting(1);
record.executeOps();
diff --git a/fragment/tests/java/android/support/v4/app/FragmentViewTests.java b/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
index 211ec35..ace24e9 100644
--- a/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
+++ b/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
@@ -1036,6 +1036,10 @@
FragmentTestUtil.executePendingTransactions(mActivityRule);
+ assertEquals(1, fragment1.onCreateViewCount);
+ assertEquals(1, fragment2.onCreateViewCount);
+ assertEquals(1, fragment3.onCreateViewCount);
+
FragmentTestUtil.popBackStackImmediate(mActivityRule, "two",
FragmentManager.POP_BACK_STACK_INCLUSIVE);
@@ -1043,6 +1047,10 @@
mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
FragmentTestUtil.assertChildren(container, fragment1);
+
+ assertEquals(2, fragment1.onCreateViewCount);
+ assertEquals(1, fragment2.onCreateViewCount);
+ assertEquals(1, fragment3.onCreateViewCount);
}
private View findViewById(int viewId) {
@@ -1091,10 +1099,13 @@
}
public static class SimpleViewFragment extends Fragment {
+ public int onCreateViewCount;
+
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
+ onCreateViewCount++;
return inflater.inflate(R.layout.fragment_a, container, false);
}
}
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/TypedArrayUtils.java b/graphics/drawable/static/src/android/support/graphics/drawable/TypedArrayUtils.java
deleted file mode 100644
index 14200c1..0000000
--- a/graphics/drawable/static/src/android/support/graphics/drawable/TypedArrayUtils.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.graphics.drawable;
-
-import android.content.res.TypedArray;
-
-import org.xmlpull.v1.XmlPullParser;
-
-class TypedArrayUtils {
- private static final String NAMESPACE = "http://schemas.android.com/apk/res/android";
-
- public static boolean hasAttribute(XmlPullParser parser, String attrName) {
- return parser.getAttributeValue(NAMESPACE, attrName) != null;
- }
-
- public static float getNamedFloat(TypedArray a, XmlPullParser parser, String attrName,
- int resId, float defaultValue) {
- final boolean hasAttr = hasAttribute(parser, attrName);
- if (!hasAttr) {
- return defaultValue;
- } else {
- return a.getFloat(resId, defaultValue);
- }
- }
-
- public static boolean getNamedBoolean(TypedArray a, XmlPullParser parser, String attrName,
- int resId, boolean defaultValue) {
- final boolean hasAttr = hasAttribute(parser, attrName);
- if (!hasAttr) {
- return defaultValue;
- } else {
- return a.getBoolean(resId, defaultValue);
- }
- }
-
- public static int getNamedInt(TypedArray a, XmlPullParser parser, String attrName,
- int resId, int defaultValue) {
- final boolean hasAttr = hasAttribute(parser, attrName);
- if (!hasAttr) {
- return defaultValue;
- } else {
- return a.getInt(resId, defaultValue);
- }
- }
-
- public static int getNamedColor(TypedArray a, XmlPullParser parser, String attrName,
- int resId, int defaultValue) {
- final boolean hasAttr = hasAttribute(parser, attrName);
- if (!hasAttr) {
- return defaultValue;
- } else {
- return a.getColor(resId, defaultValue);
- }
- }
-}
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
index 5704d6f..5f61127 100644
--- a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -42,6 +42,7 @@
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
import android.support.v4.content.res.ResourcesCompat;
+import android.support.v4.content.res.TypedArrayUtils;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v4.util.ArrayMap;
import android.util.AttributeSet;
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCursorSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCursorSupport.java
index f2f9b3c..90747ae 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCursorSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCursorSupport.java
@@ -16,6 +16,10 @@
package com.example.android.supportv4.app;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Contacts.People;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.ListFragment;
@@ -23,16 +27,7 @@
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
-import android.support.v4.widget.SearchViewCompat;
-import android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat;
-import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat;
import android.support.v4.widget.SimpleCursorAdapter;
-
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.BaseColumns;
-import android.provider.Contacts.People;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
@@ -40,6 +35,7 @@
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
+import android.widget.SearchView;
/**
* Demonstration of the use of a CursorLoader to load and display contacts
@@ -102,42 +98,42 @@
item.setIcon(android.R.drawable.ic_menu_search);
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS
| MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
- final View searchView = SearchViewCompat.newSearchView(getActivity());
- if (searchView != null) {
- SearchViewCompat.setOnQueryTextListener(searchView,
- new OnQueryTextListenerCompat() {
- @Override
- public boolean onQueryTextChange(String newText) {
- // Called when the action bar search text has changed. Update
- // the search filter, and restart the loader to do a new query
- // with this filter.
- String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
- // Don't do anything if the filter hasn't actually changed.
- // Prevents restarting the loader when restoring state.
- if (mCurFilter == null && newFilter == null) {
- return true;
- }
- if (mCurFilter != null && mCurFilter.equals(newFilter)) {
- return true;
- }
- mCurFilter = newFilter;
- getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
+ final SearchView searchView = new SearchView(getActivity());
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ // Called when the action bar search text has changed. Update
+ // the search filter, and restart the loader to do a new query
+ // with this filter.
+ String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
+ // Don't do anything if the filter hasn't actually changed.
+ // Prevents restarting the loader when restoring state.
+ if (mCurFilter == null && newFilter == null) {
return true;
}
- });
- SearchViewCompat.setOnCloseListener(searchView,
- new OnCloseListenerCompat() {
- @Override
- public boolean onClose() {
- if (!TextUtils.isEmpty(SearchViewCompat.getQuery(searchView))) {
- SearchViewCompat.setQuery(searchView, null, true);
- }
- return true;
- }
-
- });
- MenuItemCompat.setActionView(item, searchView);
- }
+ if (mCurFilter != null && mCurFilter.equals(newFilter)) {
+ return true;
+ }
+ mCurFilter = newFilter;
+ getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextSubmit(String s) {
+ return false;
+ }
+ });
+ searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+ @Override
+ public boolean onClose() {
+ if (!TextUtils.isEmpty(searchView.getQuery())) {
+ searchView.setQuery(null, true);
+ }
+ return true;
+ }
+ });
+ MenuItemCompat.setActionView(item, searchView);
}
@Override public void onListItemClick(ListView l, View v, int position, long id) {
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
index d9689d2..5dbb78c 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
@@ -33,11 +33,9 @@
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.ContextCompat;
-import android.support.v4.content.IntentCompat;
import android.support.v4.content.Loader;
import android.support.v4.content.pm.ActivityInfoCompat;
import android.support.v4.view.MenuItemCompat;
-import android.support.v4.widget.SearchViewCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -49,6 +47,7 @@
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
+import android.widget.SearchView;
import android.widget.TextView;
import com.example.android.supportv4.R;
@@ -193,8 +192,8 @@
mLoader.getContext().registerReceiver(this, filter);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
- sdFilter.addAction(IntentCompat.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
- sdFilter.addAction(IntentCompat.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+ sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mLoader.getContext().registerReceiver(this, sdFilter);
}
@@ -438,36 +437,34 @@
item.setIcon(android.R.drawable.ic_menu_search);
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM
| MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
- final View searchView = SearchViewCompat.newSearchView(getActivity());
- if (searchView != null) {
- SearchViewCompat.setOnQueryTextListener(searchView,
- new SearchViewCompat.OnQueryTextListener() {
- @Override
- public boolean onQueryTextChange(String newText) {
- // Called when the action bar search text has changed. Since this
- // is a simple array adapter, we can just have it do the filtering.
- mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
- mAdapter.getFilter().filter(mCurFilter);
- return true;
- }
+ final SearchView searchView = new SearchView(getActivity());
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ // Called when the action bar search text has changed. Since this
+ // is a simple array adapter, we can just have it do the filtering.
+ mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
+ mAdapter.getFilter().filter(mCurFilter);
+ return true;
+ }
- @Override
- public boolean onQueryTextSubmit(String query) {
- return false;
- }
- });
- SearchViewCompat.setOnCloseListener(searchView,
- new SearchViewCompat.OnCloseListener() {
- @Override
- public boolean onClose() {
- if (!TextUtils.isEmpty(SearchViewCompat.getQuery(searchView))) {
- SearchViewCompat.setQuery(searchView, null, true);
- }
- return true;
- }
- });
- MenuItemCompat.setActionView(item, searchView);
- }
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ return false;
+ }
+ });
+
+ searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+ @Override
+ public boolean onClose() {
+ if (!TextUtils.isEmpty(searchView.getQuery())) {
+ searchView.setQuery(null, true);
+ }
+ return true;
+ }
+ });
+
+ MenuItemCompat.setActionView(item, searchView);
}
@Override public void onListItemClick(ListView l, View v, int position, long id) {
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderRetainedSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderRetainedSupport.java
index 8ea47e3..c54d781 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderRetainedSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderRetainedSupport.java
@@ -16,6 +16,10 @@
package com.example.android.supportv4.app;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Contacts.People;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.ListFragment;
@@ -23,15 +27,7 @@
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
-import android.support.v4.widget.SearchViewCompat;
-import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat;
import android.support.v4.widget.SimpleCursorAdapter;
-
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.BaseColumns;
-import android.provider.Contacts.People;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
@@ -39,6 +35,7 @@
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
+import android.widget.SearchView;
/**
* Demonstration of the use of a CursorLoader to load and display contacts
@@ -104,31 +101,33 @@
item.setIcon(android.R.drawable.ic_menu_search);
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS
| MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
- View searchView = SearchViewCompat.newSearchView(getActivity());
- if (searchView != null) {
- SearchViewCompat.setOnQueryTextListener(searchView,
- new OnQueryTextListenerCompat() {
- @Override
- public boolean onQueryTextChange(String newText) {
- // Called when the action bar search text has changed. Update
- // the search filter, and restart the loader to do a new query
- // with this filter.
- String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
- // Don't do anything if the filter hasn't actually changed.
- // Prevents restarting the loader when restoring state.
- if (mCurFilter == null && newFilter == null) {
- return true;
- }
- if (mCurFilter != null && mCurFilter.equals(newFilter)) {
- return true;
- }
- mCurFilter = newFilter;
- getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
+ SearchView searchView = new SearchView(getActivity());
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ // Called when the action bar search text has changed. Update
+ // the search filter, and restart the loader to do a new query
+ // with this filter.
+ String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
+ // Don't do anything if the filter hasn't actually changed.
+ // Prevents restarting the loader when restoring state.
+ if (mCurFilter == null && newFilter == null) {
return true;
}
- });
- MenuItemCompat.setActionView(item, searchView);
- }
+ if (mCurFilter != null && mCurFilter.equals(newFilter)) {
+ return true;
+ }
+ mCurFilter = newFilter;
+ getLoaderManager().restartLoader(0, null, CursorLoaderListFragment.this);
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextSubmit(String s) {
+ return false;
+ }
+ });
+ MenuItemCompat.setActionView(item, searchView);
}
@Override public void onListItemClick(ListView l, View v, int position, long id) {
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
index 5d33a1f..363245f 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/media/SampleMediaRouterActivity.java
@@ -234,15 +234,13 @@
DiscoveryFragment fragment = (DiscoveryFragment) fm.findFragmentByTag(
DISCOVERY_FRAGMENT_TAG);
if (fragment == null) {
- fragment = new DiscoveryFragment(mMediaRouterCB);
- fragment.setRouteSelector(mSelector);
+ fragment = new DiscoveryFragment();
fm.beginTransaction()
.add(fragment, DISCOVERY_FRAGMENT_TAG)
.commit();
- } else {
- fragment.setCallback(mMediaRouterCB);
- fragment.setRouteSelector(mSelector);
}
+ fragment.setCallback(mMediaRouterCB);
+ fragment.setRouteSelector(mSelector);
// Populate an array adapter with streaming media items.
String[] mediaNames = getResources().getStringArray(R.array.media_names);
@@ -639,14 +637,6 @@
private static final String TAG = "DiscoveryFragment";
private Callback mCallback;
- public DiscoveryFragment() {
- mCallback = null;
- }
-
- public DiscoveryFragment(Callback cb) {
- mCallback = cb;
- }
-
public void setCallback(Callback cb) {
mCallback = cb;
}
diff --git a/tv-provider/src/android/support/media/tv/Program.java b/tv-provider/src/android/support/media/tv/Program.java
index 266755b..c766f96 100644
--- a/tv-provider/src/android/support/media/tv/Program.java
+++ b/tv-provider/src/android/support/media/tv/Program.java
@@ -517,8 +517,8 @@
public int hashCode() {
return Objects.hash(mChannelId, mStartTimeUtcMillis, mEndTimeUtcMillis,
mTitle, mEpisodeTitle, mDescription, mLongDescription, mVideoWidth, mVideoHeight,
- mPosterArtUri, mThumbnailUri, mContentRatings, mCanonicalGenres, mSeasonNumber,
- mEpisodeNumber);
+ mPosterArtUri, mThumbnailUri, Arrays.hashCode(mContentRatings),
+ Arrays.hashCode(mCanonicalGenres), mSeasonNumber, mEpisodeNumber);
}
@Override
diff --git a/v17/leanback/res/layout/lb_playback_fragment.xml b/v17/leanback/res/layout/lb_playback_fragment.xml
index 85d52cf..1b0ffa1 100644
--- a/v17/leanback/res/layout/lb_playback_fragment.xml
+++ b/v17/leanback/res/layout/lb_playback_fragment.xml
@@ -18,11 +18,12 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/playback_fragment_root"
android:layout_width="match_parent"
+ android:transitionGroup="false"
android:layout_height="match_parent">
<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/playback_controls_dock"
+ android:transitionGroup="true"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</FrameLayout>
diff --git a/v17/leanback/res/layout/lb_video_surface.xml b/v17/leanback/res/layout/lb_video_surface.xml
index a3b0fe0..9c6c8fd 100644
--- a/v17/leanback/res/layout/lb_video_surface.xml
+++ b/v17/leanback/res/layout/lb_video_surface.xml
@@ -14,7 +14,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.v17.leanback.widget.VideoSurfaceView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/video_surface"
android:layout_width="match_parent"
android:layout_height="match_parent" />
diff --git a/v17/leanback/res/transition-v21/lb_details_enter_transition.xml b/v17/leanback/res/transition-v21/lb_details_enter_transition.xml
index 3bb7c9f..d535ff4 100644
--- a/v17/leanback/res/transition-v21/lb_details_enter_transition.xml
+++ b/v17/leanback/res/transition-v21/lb_details_enter_transition.xml
@@ -25,6 +25,7 @@
<target android:excludeId="@id/title_text" />
<target android:excludeId="@id/title_orb" />
<target android:excludeId="@id/details_background_view" />
+ <target android:excludeId="@id/video_surface" />
</targets>
</transition>
<!-- The ParallaxTransition runs with with Slide transition, must use same duration
@@ -37,5 +38,8 @@
</transition>
<fade
android:duration="350">
+ <targets>
+ <target android:excludeId="@id/video_surface" />
+ </targets>
</fade>
</transitionSet>
\ No newline at end of file
diff --git a/v17/leanback/res/transition-v21/lb_details_return_transition.xml b/v17/leanback/res/transition-v21/lb_details_return_transition.xml
index 5e54d2c..82a55f4 100644
--- a/v17/leanback/res/transition-v21/lb_details_return_transition.xml
+++ b/v17/leanback/res/transition-v21/lb_details_return_transition.xml
@@ -24,6 +24,7 @@
<target android:excludeId="@id/title_text" />
<target android:excludeId="@id/title_orb" />
<target android:excludeId="@id/details_background_view" />
+ <target android:excludeId="@id/video_surface" />
</targets>
</transition>
<!-- The ParallaxTransition runs with with Slide transition, must use same duration
@@ -36,5 +37,8 @@
</transition>
<fade
android:duration="350">
+ <targets>
+ <target android:excludeId="@id/video_surface" />
+ </targets>
</fade>
</transitionSet>
\ No newline at end of file
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java
index cb3fa2f..72072a2 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java
@@ -22,6 +22,7 @@
import android.support.v17.leanback.media.PlaybackGlue;
import android.support.v17.leanback.widget.DetailsParallax;
import android.support.v17.leanback.widget.Parallax;
+import android.support.v17.leanback.widget.ParallaxEffect;
import android.support.v17.leanback.widget.ParallaxTarget;
/**
@@ -36,19 +37,19 @@
*/
final class DetailsBackgroundVideoHelper {
private static final long BACKGROUND_CROSS_FADE_DURATION = 500;
- private static final long CROSSFADE_DELAY = 1000;
+ private static final long CROSSFADE_DELAY = 0;
/**
* Different states {@link DetailsFragment} can be in.
*/
- enum STATE {
- INITIAL,
- PLAY_VIDEO,
- NO_VIDEO
- }
+ static final int INITIAL = 0;
+ static final int PLAY_VIDEO = 1;
+ static final int NO_VIDEO = 2;
private final DetailsParallax mDetailsParallax;
- private STATE mCurrentState = STATE.INITIAL;
+ private ParallaxEffect mParallaxEffect;
+
+ private int mCurrentState = INITIAL;
private ValueAnimator mBackgroundAnimator;
private Drawable mBackgroundDrawable;
@@ -72,14 +73,17 @@
this.mPlaybackGlue = playbackGlue;
this.mDetailsParallax = detailsParallax;
this.mBackgroundDrawable = backgroundDrawable;
- setupParallax();
+ startParallax();
}
- void setupParallax() {
+ void startParallax() {
+ if (mParallaxEffect != null) {
+ return;
+ }
Parallax.IntProperty frameTop = mDetailsParallax.getOverviewRowTop();
final float maxFrameTop = 1f;
final float minFrameTop = 0f;
- mDetailsParallax
+ mParallaxEffect = mDetailsParallax
.addEffect(frameTop.atFraction(maxFrameTop), frameTop.atFraction(minFrameTop))
.target(new ParallaxTarget() {
@@ -87,9 +91,9 @@
@Override
public void update(float fraction) {
if (fraction == maxFrameTop) {
- updateState(STATE.NO_VIDEO);
+ updateState(NO_VIDEO);
} else {
- updateState(STATE.PLAY_VIDEO);
+ updateState(PLAY_VIDEO);
}
mFraction = fraction;
}
@@ -101,7 +105,15 @@
});
}
- private void updateState(STATE state) {
+ void stopParallax() {
+ mDetailsParallax.removeEffect(mParallaxEffect);
+ }
+
+ boolean isVideoVisible() {
+ return mCurrentState == PLAY_VIDEO;
+ }
+
+ private void updateState(int state) {
if (state == mCurrentState) {
return;
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
index b26aabc..ac11fde 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
@@ -13,13 +13,16 @@
*/
package android.support.v17.leanback.app;
+import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.CallSuper;
import android.support.v17.leanback.R;
import android.support.v17.leanback.transition.TransitionHelper;
+import android.support.v17.leanback.transition.TransitionListener;
import android.support.v17.leanback.widget.BaseOnItemViewClickedListener;
import android.support.v17.leanback.widget.BaseOnItemViewSelectedListener;
import android.support.v17.leanback.widget.BrowseFrameLayout;
@@ -38,6 +41,8 @@
import android.view.View;
import android.view.ViewGroup;
+import java.lang.ref.WeakReference;
+
/**
* A fragment for creating Leanback details screens.
*
@@ -76,6 +81,23 @@
static final String TAG = "DetailsFragment";
static boolean DEBUG = false;
+ /**
+ * Flag for "possibly" having enter transition not finished yet.
+ * @see #mStartAndTransitionFlag
+ */
+ static final int PF_ENTER_TRANSITION_PENDING = 0x1 << 0;
+ /**
+ * Flag for having entrance transition not finished yet.
+ * @see #mStartAndTransitionFlag
+ */
+ static final int PF_ENTRANCE_TRANSITION_PENDING = 0x1 << 1;
+ /**
+ * Flag that onStart() has been called and about to call onSafeStart() when
+ * pending transitions are finished.
+ * @see #mStartAndTransitionFlag
+ */
+ static final int PF_PENDING_START = 0x1 << 2;
+
private class SetSelectionRunnable implements Runnable {
int mPosition;
boolean mSmooth = true;
@@ -92,6 +114,61 @@
}
}
+ /**
+ * Start this task when first DetailsOverviewRow is created, if there is no entrance transition
+ * started, it will clear PF_ENTRANCE_TRANSITION_PENDING.
+ * @see #mStartAndTransitionFlag
+ */
+ static class WaitEnterTransitionTimeout implements Runnable {
+ static final long WAIT_ENTERTRANSITION_START = 200;
+
+ final WeakReference<DetailsFragment> mRef;
+
+ WaitEnterTransitionTimeout(DetailsFragment f) {
+ mRef = new WeakReference(f);
+ f.getView().postDelayed(this, WAIT_ENTERTRANSITION_START);
+ }
+
+ @Override
+ public void run() {
+ DetailsFragment f = mRef.get();
+ if (f != null) {
+ f.clearPendingEnterTransition();
+ }
+ }
+ }
+
+ /**
+ * @see #mStartAndTransitionFlag
+ */
+ TransitionListener mEnterTransitionListener = new TransitionListener() {
+ @Override
+ public void onTransitionStart(Object transition) {
+ if (mWaitEnterTransitionTimeout != null) {
+ // cancel task of WaitEnterTransitionTimeout, we will clearPendingEnterTransition
+ // when transition finishes.
+ mWaitEnterTransitionTimeout.mRef.clear();
+ }
+ }
+
+ @Override
+ public void onTransitionCancel(Object transition) {
+ clearPendingEnterTransition();
+ }
+
+ @Override
+ public void onTransitionEnd(Object transition) {
+ clearPendingEnterTransition();
+ }
+ };
+
+ TransitionListener mReturnTransitionListener = new TransitionListener() {
+ @Override
+ public void onTransitionStart(Object transition) {
+ onReturnTransitionStart();
+ }
+ };
+
BrowseFrameLayout mRootView;
View mBackgroundView;
Drawable mBackgroundDrawable;
@@ -104,6 +181,25 @@
BaseOnItemViewClickedListener mOnItemViewClickedListener;
DetailsFragmentBackgroundController mDetailsBackgroundController;
+
+ /**
+ * Flags for enter transition, entrance transition and onStart. When onStart() is called
+ * and both enter transiton and entrance transition are finished, we could call onSafeStart().
+ * 1. in onCreate:
+ * if user call prepareEntranceTransition, set PF_ENTRANCE_TRANSITION_PENDING
+ * if there is enterTransition, set PF_ENTER_TRANSITION_PENDING, but we dont know if
+ * user will run enterTransition or not.
+ * 2. when user add row, start WaitEnterTransitionTimeout to wait possible enter transition
+ * start. If enter transition onTransitionStart is not invoked with a period, we can assume
+ * there is no enter transition running, then WaitEnterTransitionTimeout will clear
+ * PF_ENTER_TRANSITION_PENDING.
+ * 3. When enterTransition runs (either postponed or not), we will stop the
+ * WaitEnterTransitionTimeout, and let onTransitionEnd/onTransitionCancel to clear
+ * PF_ENTER_TRANSITION_PENDING.
+ */
+ int mStartAndTransitionFlag = 0;
+ WaitEnterTransitionTimeout mWaitEnterTransitionTimeout;
+
Object mSceneAfterEntranceTransition;
final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable();
@@ -181,6 +277,19 @@
super.onCreate(savedInstanceState);
mContainerListAlignTop =
getResources().getDimensionPixelSize(R.dimen.lb_details_rows_align_top);
+
+ Activity activity = getActivity();
+ if (activity != null) {
+ Object transition = TransitionHelper.getEnterTransition(activity.getWindow());
+ if (transition != null) {
+ mStartAndTransitionFlag |= PF_ENTER_TRANSITION_PENDING;
+ TransitionHelper.addTransitionListener(transition, mEnterTransitionListener);
+ }
+ transition = TransitionHelper.getReturnTransition(activity.getWindow());
+ if (transition != null) {
+ TransitionHelper.addTransitionListener(transition, mReturnTransitionListener);
+ }
+ }
}
@Override
@@ -369,6 +478,11 @@
if (adapter != null && adapter.size() > selectedPosition) {
final VerticalGridView gridView = getVerticalGridView();
final int count = gridView.getChildCount();
+ if (count > 0 && (mStartAndTransitionFlag & PF_ENTER_TRANSITION_PENDING) != 0) {
+ if (mWaitEnterTransitionTimeout == null) {
+ mWaitEnterTransitionTimeout = new WaitEnterTransitionTimeout(this);
+ }
+ }
for (int i = 0; i < count; i++) {
ItemBridgeAdapter.ViewHolder bridgeViewHolder = (ItemBridgeAdapter.ViewHolder)
gridView.getChildViewHolder(gridView.getChildAt(i));
@@ -381,6 +495,52 @@
}
}
+ void clearPendingEnterTransition() {
+ if ((mStartAndTransitionFlag & PF_ENTER_TRANSITION_PENDING) != 0) {
+ mStartAndTransitionFlag &= ~PF_ENTER_TRANSITION_PENDING;
+ dispatchOnStartAndTransitionFinished();
+ }
+ }
+
+ void dispatchOnStartAndTransitionFinished() {
+ /**
+ * if onStart() was called and there is no pending enter transition or entrance transition.
+ */
+ if ((mStartAndTransitionFlag & PF_PENDING_START) != 0
+ && (mStartAndTransitionFlag
+ & (PF_ENTER_TRANSITION_PENDING | PF_ENTRANCE_TRANSITION_PENDING)) == 0) {
+ mStartAndTransitionFlag &= ~PF_PENDING_START;
+ onSafeStart();
+ }
+ }
+
+ /**
+ * Called when onStart and enter transition (postponed/none postponed) and entrance transition
+ * are all finished.
+ */
+ @CallSuper
+ void onSafeStart() {
+ if (mDetailsBackgroundController != null) {
+ mDetailsBackgroundController.enablePlaybackHost();
+ }
+ }
+
+ @CallSuper
+ void onReturnTransitionStart() {
+ if (mDetailsBackgroundController != null) {
+ // first disable parallax effect that auto-start PlaybackGlue.
+ boolean isVideoVisible = mDetailsBackgroundController.disableVideoParallax();
+ // if video is not visible we can safely remove VideoFragment,
+ // otherwise let video playing during return transition.
+ if (!isVideoVisible && mVideoFragment != null) {
+ FragmentTransaction ft2 = getChildFragmentManager().beginTransaction();
+ ft2.remove(mVideoFragment);
+ ft2.commit();
+ mVideoFragment = null;
+ }
+ }
+ }
+
/**
* Called on every visible row to change view status when current selected row position
* or selected sub position changed. Subclass may override. The default
@@ -439,6 +599,10 @@
@Override
public void onStart() {
super.onStart();
+
+ mStartAndTransitionFlag |= PF_PENDING_START;
+ dispatchOnStartAndTransitionFinished();
+
setupChildFragmentLayout();
if (isEntranceTransitionEnabled()) {
mRowsFragment.setEntranceTransitionState(false);
@@ -462,11 +626,14 @@
@Override
protected void onEntranceTransitionEnd() {
+ mStartAndTransitionFlag &= ~PF_ENTRANCE_TRANSITION_PENDING;
+ dispatchOnStartAndTransitionFinished();
mRowsFragment.onTransitionEnd();
}
@Override
protected void onEntranceTransitionPrepare() {
+ mStartAndTransitionFlag |= PF_ENTRANCE_TRANSITION_PENDING;
mRowsFragment.onTransitionPrepare();
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java
index 9f9ed26..a0bf00c 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java
@@ -114,6 +114,7 @@
private DetailsBackgroundVideoHelper mVideoHelper;
private Bitmap mCoverBitmap;
private int mSolidColor;
+ private boolean mCanUseHost = false;
/**
* Creates a DetailsFragmentBackgroundController for a DetailsFragment. Note that
@@ -208,17 +209,47 @@
/**
* Enable video playback and set proper {@link PlaybackGlueHost}. This method by default
* creates a VideoFragment and VideoFragmentGlueHost to host the PlaybackGlue.
- * This method must be called after calling Fragment super.onCreate().
+ * This method must be called after calling details Fragment super.onCreate().
*
* @param playbackGlue
* @see #onCreateVideoFragment()
* @see #onCreateGlueHost().
*/
public void setupVideoPlayback(@NonNull PlaybackGlue playbackGlue) {
+ if (mPlaybackGlue == playbackGlue) {
+ return;
+ }
mPlaybackGlue = playbackGlue;
- mPlaybackGlue.setHost(onCreateGlueHost());
mVideoHelper = new DetailsBackgroundVideoHelper(mPlaybackGlue,
mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
+ if (mCanUseHost) {
+ mPlaybackGlue.setHost(onCreateGlueHost());
+ }
+ }
+
+ /**
+ * Enable Host for PlaybackGlue. This is delayed until: onStart() is called,
+ * activity transitions are finished.
+ */
+ void enablePlaybackHost() {
+ if (!mCanUseHost) {
+ mCanUseHost = true;
+ if (mPlaybackGlue != null) {
+ mPlaybackGlue.setHost(onCreateGlueHost());
+ }
+ }
+ }
+
+ /**
+ * Disable parallax that would auto-start video playback
+ * @return true if video fragment is visible or false otherwise.
+ */
+ boolean disableVideoParallax() {
+ if (mVideoHelper != null) {
+ mVideoHelper.stopParallax();
+ return mVideoHelper.isVideoVisible();
+ }
+ return false;
}
/**
@@ -360,15 +391,4 @@
return mParallaxDrawableMaxOffset;
}
- void onStart() {
- if (mPlaybackGlue != null) {
- mPlaybackGlue.play();
- }
- }
-
- void onStop() {
- if (mPlaybackGlue != null) {
- mPlaybackGlue.pause();
- }
- }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
index 2a759de..53300ac 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
@@ -16,13 +16,16 @@
*/
package android.support.v17.leanback.app;
+import android.support.v4.app.FragmentActivity;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.CallSuper;
import android.support.v17.leanback.R;
import android.support.v17.leanback.transition.TransitionHelper;
+import android.support.v17.leanback.transition.TransitionListener;
import android.support.v17.leanback.widget.BaseOnItemViewClickedListener;
import android.support.v17.leanback.widget.BaseOnItemViewSelectedListener;
import android.support.v17.leanback.widget.BrowseFrameLayout;
@@ -41,6 +44,8 @@
import android.view.View;
import android.view.ViewGroup;
+import java.lang.ref.WeakReference;
+
/**
* A fragment for creating Leanback details screens.
*
@@ -79,6 +84,23 @@
static final String TAG = "DetailsSupportFragment";
static boolean DEBUG = false;
+ /**
+ * Flag for "possibly" having enter transition not finished yet.
+ * @see #mStartAndTransitionFlag
+ */
+ static final int PF_ENTER_TRANSITION_PENDING = 0x1 << 0;
+ /**
+ * Flag for having entrance transition not finished yet.
+ * @see #mStartAndTransitionFlag
+ */
+ static final int PF_ENTRANCE_TRANSITION_PENDING = 0x1 << 1;
+ /**
+ * Flag that onStart() has been called and about to call onSafeStart() when
+ * pending transitions are finished.
+ * @see #mStartAndTransitionFlag
+ */
+ static final int PF_PENDING_START = 0x1 << 2;
+
private class SetSelectionRunnable implements Runnable {
int mPosition;
boolean mSmooth = true;
@@ -95,6 +117,61 @@
}
}
+ /**
+ * Start this task when first DetailsOverviewRow is created, if there is no entrance transition
+ * started, it will clear PF_ENTRANCE_TRANSITION_PENDING.
+ * @see #mStartAndTransitionFlag
+ */
+ static class WaitEnterTransitionTimeout implements Runnable {
+ static final long WAIT_ENTERTRANSITION_START = 200;
+
+ final WeakReference<DetailsSupportFragment> mRef;
+
+ WaitEnterTransitionTimeout(DetailsSupportFragment f) {
+ mRef = new WeakReference(f);
+ f.getView().postDelayed(this, WAIT_ENTERTRANSITION_START);
+ }
+
+ @Override
+ public void run() {
+ DetailsSupportFragment f = mRef.get();
+ if (f != null) {
+ f.clearPendingEnterTransition();
+ }
+ }
+ }
+
+ /**
+ * @see #mStartAndTransitionFlag
+ */
+ TransitionListener mEnterTransitionListener = new TransitionListener() {
+ @Override
+ public void onTransitionStart(Object transition) {
+ if (mWaitEnterTransitionTimeout != null) {
+ // cancel task of WaitEnterTransitionTimeout, we will clearPendingEnterTransition
+ // when transition finishes.
+ mWaitEnterTransitionTimeout.mRef.clear();
+ }
+ }
+
+ @Override
+ public void onTransitionCancel(Object transition) {
+ clearPendingEnterTransition();
+ }
+
+ @Override
+ public void onTransitionEnd(Object transition) {
+ clearPendingEnterTransition();
+ }
+ };
+
+ TransitionListener mReturnTransitionListener = new TransitionListener() {
+ @Override
+ public void onTransitionStart(Object transition) {
+ onReturnTransitionStart();
+ }
+ };
+
BrowseFrameLayout mRootView;
View mBackgroundView;
Drawable mBackgroundDrawable;
@@ -107,6 +184,25 @@
BaseOnItemViewClickedListener mOnItemViewClickedListener;
DetailsSupportFragmentBackgroundController mDetailsBackgroundController;
+
+ /**
+ * Flags for enter transition, entrance transition and onStart. When onStart() is called
+ * and both enter transiton and entrance transition are finished, we could call onSafeStart().
+ * 1. in onCreate:
+ * if user call prepareEntranceTransition, set PF_ENTRANCE_TRANSITION_PENDING
+ * if there is enterTransition, set PF_ENTER_TRANSITION_PENDING, but we dont know if
+ * user will run enterTransition or not.
+ * 2. when user add row, start WaitEnterTransitionTimeout to wait possible enter transition
+ * start. If enter transition onTransitionStart is not invoked with a period, we can assume
+ * there is no enter transition running, then WaitEnterTransitionTimeout will clear
+ * PF_ENTER_TRANSITION_PENDING.
+ * 3. When enterTransition runs (either postponed or not), we will stop the
+ * WaitEnterTransitionTimeout, and let onTransitionEnd/onTransitionCancel to clear
+ * PF_ENTER_TRANSITION_PENDING.
+ */
+ int mStartAndTransitionFlag = 0;
+ WaitEnterTransitionTimeout mWaitEnterTransitionTimeout;
+
Object mSceneAfterEntranceTransition;
final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable();
@@ -184,6 +280,19 @@
super.onCreate(savedInstanceState);
mContainerListAlignTop =
getResources().getDimensionPixelSize(R.dimen.lb_details_rows_align_top);
+
+ FragmentActivity activity = getActivity();
+ if (activity != null) {
+ Object transition = TransitionHelper.getEnterTransition(activity.getWindow());
+ if (transition != null) {
+ mStartAndTransitionFlag |= PF_ENTER_TRANSITION_PENDING;
+ TransitionHelper.addTransitionListener(transition, mEnterTransitionListener);
+ }
+ transition = TransitionHelper.getReturnTransition(activity.getWindow());
+ if (transition != null) {
+ TransitionHelper.addTransitionListener(transition, mReturnTransitionListener);
+ }
+ }
}
@Override
@@ -372,6 +481,11 @@
if (adapter != null && adapter.size() > selectedPosition) {
final VerticalGridView gridView = getVerticalGridView();
final int count = gridView.getChildCount();
+ if (count > 0 && (mStartAndTransitionFlag & PF_ENTER_TRANSITION_PENDING) != 0) {
+ if (mWaitEnterTransitionTimeout == null) {
+ mWaitEnterTransitionTimeout = new WaitEnterTransitionTimeout(this);
+ }
+ }
for (int i = 0; i < count; i++) {
ItemBridgeAdapter.ViewHolder bridgeViewHolder = (ItemBridgeAdapter.ViewHolder)
gridView.getChildViewHolder(gridView.getChildAt(i));
@@ -384,6 +498,52 @@
}
}
+ void clearPendingEnterTransition() {
+ if ((mStartAndTransitionFlag & PF_ENTER_TRANSITION_PENDING) != 0) {
+ mStartAndTransitionFlag &= ~PF_ENTER_TRANSITION_PENDING;
+ dispatchOnStartAndTransitionFinished();
+ }
+ }
+
+ void dispatchOnStartAndTransitionFinished() {
+ /**
+ * if onStart() was called and there is no pending enter transition or entrance transition.
+ */
+ if ((mStartAndTransitionFlag & PF_PENDING_START) != 0
+ && (mStartAndTransitionFlag
+ & (PF_ENTER_TRANSITION_PENDING | PF_ENTRANCE_TRANSITION_PENDING)) == 0) {
+ mStartAndTransitionFlag &= ~PF_PENDING_START;
+ onSafeStart();
+ }
+ }
+
+ /**
+ * Called when onStart and enter transition (postponed/none postponed) and entrance transition
+ * are all finished.
+ */
+ @CallSuper
+ void onSafeStart() {
+ if (mDetailsBackgroundController != null) {
+ mDetailsBackgroundController.enablePlaybackHost();
+ }
+ }
+
+ @CallSuper
+ void onReturnTransitionStart() {
+ if (mDetailsBackgroundController != null) {
+ // first disable parallax effect that auto-start PlaybackGlue.
+ boolean isVideoVisible = mDetailsBackgroundController.disableVideoParallax();
+ // if video is not visible we can safely remove VideoSupportFragment,
+ // otherwise let video playing during return transition.
+ if (!isVideoVisible && mVideoSupportFragment != null) {
+ FragmentTransaction ft2 = getChildFragmentManager().beginTransaction();
+ ft2.remove(mVideoSupportFragment);
+ ft2.commit();
+ mVideoSupportFragment = null;
+ }
+ }
+ }
+
/**
* Called on every visible row to change view status when current selected row position
* or selected sub position changed. Subclass may override. The default
@@ -442,6 +602,10 @@
@Override
public void onStart() {
super.onStart();
+
+ mStartAndTransitionFlag |= PF_PENDING_START;
+ dispatchOnStartAndTransitionFinished();
+
setupChildFragmentLayout();
if (isEntranceTransitionEnabled()) {
mRowsSupportFragment.setEntranceTransitionState(false);
@@ -465,11 +629,14 @@
@Override
protected void onEntranceTransitionEnd() {
+ mStartAndTransitionFlag &= ~PF_ENTRANCE_TRANSITION_PENDING;
+ dispatchOnStartAndTransitionFinished();
mRowsSupportFragment.onTransitionEnd();
}
@Override
protected void onEntranceTransitionPrepare() {
+ mStartAndTransitionFlag |= PF_ENTRANCE_TRANSITION_PENDING;
mRowsSupportFragment.onTransitionPrepare();
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java
index e450c3b..5ab42c3 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java
@@ -117,6 +117,7 @@
private DetailsBackgroundVideoHelper mVideoHelper;
private Bitmap mCoverBitmap;
private int mSolidColor;
+ private boolean mCanUseHost = false;
/**
* Creates a DetailsSupportFragmentBackgroundController for a DetailsSupportFragment. Note that
@@ -211,17 +212,47 @@
/**
* Enable video playback and set proper {@link PlaybackGlueHost}. This method by default
* creates a VideoSupportFragment and VideoSupportFragmentGlueHost to host the PlaybackGlue.
- * This method must be called after calling Fragment super.onCreate().
+ * This method must be called after calling details Fragment super.onCreate().
*
* @param playbackGlue
* @see #onCreateVideoSupportFragment()
* @see #onCreateGlueHost().
*/
public void setupVideoPlayback(@NonNull PlaybackGlue playbackGlue) {
+ if (mPlaybackGlue == playbackGlue) {
+ return;
+ }
mPlaybackGlue = playbackGlue;
- mPlaybackGlue.setHost(onCreateGlueHost());
mVideoHelper = new DetailsBackgroundVideoHelper(mPlaybackGlue,
mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
+ if (mCanUseHost) {
+ mPlaybackGlue.setHost(onCreateGlueHost());
+ }
+ }
+
+ /**
+ * Enable Host for PlaybackGlue. This is delayed until: onStart() is called,
+ * activity transitions are finished.
+ */
+ void enablePlaybackHost() {
+ if (!mCanUseHost) {
+ mCanUseHost = true;
+ if (mPlaybackGlue != null) {
+ mPlaybackGlue.setHost(onCreateGlueHost());
+ }
+ }
+ }
+
+ /**
+ * Disable parallax that would auto-start video playback
+ * @return true if video fragment is visible or false otherwise.
+ */
+ boolean disableVideoParallax() {
+ if (mVideoHelper != null) {
+ mVideoHelper.stopParallax();
+ return mVideoHelper.isVideoVisible();
+ }
+ return false;
}
/**
@@ -363,15 +394,4 @@
return mParallaxDrawableMaxOffset;
}
- void onStart() {
- if (mPlaybackGlue != null) {
- mPlaybackGlue.play();
- }
- }
-
- void onStop() {
- if (mPlaybackGlue != null) {
- mPlaybackGlue.pause();
- }
- }
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
index cf9d424..87f8402 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -1334,7 +1334,7 @@
if (DEBUG) Log.v(getTag(), "request Layout from runnable");
requestLayout();
}
- };
+ };
@Override
public void onMeasure(Recycler recycler, State state, int widthSpec, int heightSpec) {
@@ -1374,18 +1374,18 @@
processRowSizeSecondary(true);
switch (modeSecondary) {
- case MeasureSpec.UNSPECIFIED:
- measuredSizeSecondary = getSizeSecondary() + paddingSecondary;
- break;
- case MeasureSpec.AT_MOST:
- measuredSizeSecondary = Math.min(getSizeSecondary() + paddingSecondary,
- mMaxSizeSecondary);
- break;
- case MeasureSpec.EXACTLY:
- measuredSizeSecondary = mMaxSizeSecondary;
- break;
- default:
- throw new IllegalStateException("wrong spec");
+ case MeasureSpec.UNSPECIFIED:
+ measuredSizeSecondary = getSizeSecondary() + paddingSecondary;
+ break;
+ case MeasureSpec.AT_MOST:
+ measuredSizeSecondary = Math.min(getSizeSecondary() + paddingSecondary,
+ mMaxSizeSecondary);
+ break;
+ case MeasureSpec.EXACTLY:
+ measuredSizeSecondary = mMaxSizeSecondary;
+ break;
+ default:
+ throw new IllegalStateException("wrong spec");
}
} else {
@@ -1395,7 +1395,7 @@
? sizeSecondary - paddingSecondary : mRowSizeSecondaryRequested;
mNumRows = mNumRowsRequested == 0 ? 1 : mNumRowsRequested;
measuredSizeSecondary = mFixedRowSizeSecondary * mNumRows + mSpacingSecondary
- * (mNumRows - 1) + paddingSecondary;
+ * (mNumRows - 1) + paddingSecondary;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
@@ -1405,7 +1405,7 @@
} else if (mNumRowsRequested == 0) {
mFixedRowSizeSecondary = mRowSizeSecondaryRequested;
mNumRows = (sizeSecondary + mSpacingSecondary)
- / (mRowSizeSecondaryRequested + mSpacingSecondary);
+ / (mRowSizeSecondaryRequested + mSpacingSecondary);
} else if (mRowSizeSecondaryRequested == 0) {
mNumRows = mNumRowsRequested;
mFixedRowSizeSecondary = (sizeSecondary - paddingSecondary
@@ -1646,7 +1646,7 @@
final int verticalGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
final int horizontalGravity = (mReverseFlowPrimary || mReverseFlowSecondary)
? Gravity.getAbsoluteGravity(mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK,
- View.LAYOUT_DIRECTION_RTL)
+ View.LAYOUT_DIRECTION_RTL)
: mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
if (mOrientation == HORIZONTAL && verticalGravity == Gravity.TOP
|| mOrientation == VERTICAL && horizontalGravity == Gravity.LEFT) {
@@ -2442,7 +2442,7 @@
if (DEBUG) Log.v(getTag(), "onItemsRemoved positionStart "
+ positionStart + " itemCount " + itemCount);
if (mFocusPosition != NO_POSITION && mGrid != null && mGrid.getFirstVisibleIndex() >= 0
- && mFocusPositionOffset != Integer.MIN_VALUE) {
+ && mFocusPositionOffset != Integer.MIN_VALUE) {
int pos = mFocusPosition + mFocusPositionOffset;
if (positionStart <= pos) {
if (positionStart + itemCount > pos) {
@@ -2638,12 +2638,12 @@
boolean getScrollPosition(View view, View childView, int[] deltas) {
switch (mFocusScrollStrategy) {
- case BaseGridView.FOCUS_SCROLL_ALIGNED:
- default:
- return getAlignedPosition(view, childView, deltas);
- case BaseGridView.FOCUS_SCROLL_ITEM:
- case BaseGridView.FOCUS_SCROLL_PAGE:
- return getNoneAlignedPosition(view, deltas);
+ case BaseGridView.FOCUS_SCROLL_ALIGNED:
+ default:
+ return getAlignedPosition(view, childView, deltas);
+ case BaseGridView.FOCUS_SCROLL_ITEM:
+ case BaseGridView.FOCUS_SCROLL_PAGE:
+ return getNoneAlignedPosition(view, deltas);
}
}
@@ -3083,14 +3083,14 @@
boolean gridOnRequestFocusInDescendants(RecyclerView recyclerView, int direction,
Rect previouslyFocusedRect) {
switch (mFocusScrollStrategy) {
- case BaseGridView.FOCUS_SCROLL_ALIGNED:
- default:
- return gridOnRequestFocusInDescendantsAligned(recyclerView,
- direction, previouslyFocusedRect);
- case BaseGridView.FOCUS_SCROLL_PAGE:
- case BaseGridView.FOCUS_SCROLL_ITEM:
- return gridOnRequestFocusInDescendantsUnaligned(recyclerView,
- direction, previouslyFocusedRect);
+ case BaseGridView.FOCUS_SCROLL_ALIGNED:
+ default:
+ return gridOnRequestFocusInDescendantsAligned(recyclerView,
+ direction, previouslyFocusedRect);
+ case BaseGridView.FOCUS_SCROLL_PAGE:
+ case BaseGridView.FOCUS_SCROLL_ITEM:
+ return gridOnRequestFocusInDescendantsUnaligned(recyclerView,
+ direction, previouslyFocusedRect);
}
}
@@ -3161,22 +3161,22 @@
movement = NEXT_ROW;
break;
}
- } else if (mOrientation == VERTICAL) {
- switch(direction) {
- case View.FOCUS_LEFT:
- movement = (!mReverseFlowSecondary) ? PREV_ROW : NEXT_ROW;
- break;
- case View.FOCUS_RIGHT:
- movement = (!mReverseFlowSecondary) ? NEXT_ROW : PREV_ROW;
- break;
- case View.FOCUS_UP:
- movement = PREV_ITEM;
- break;
- case View.FOCUS_DOWN:
- movement = NEXT_ITEM;
- break;
- }
- }
+ } else if (mOrientation == VERTICAL) {
+ switch(direction) {
+ case View.FOCUS_LEFT:
+ movement = (!mReverseFlowSecondary) ? PREV_ROW : NEXT_ROW;
+ break;
+ case View.FOCUS_RIGHT:
+ movement = (!mReverseFlowSecondary) ? NEXT_ROW : PREV_ROW;
+ break;
+ case View.FOCUS_UP:
+ movement = PREV_ITEM;
+ break;
+ case View.FOCUS_DOWN:
+ movement = NEXT_ITEM;
+ break;
+ }
+ }
return movement;
}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/VideoSurfaceView.java b/v17/leanback/src/android/support/v17/leanback/widget/VideoSurfaceView.java
new file mode 100644
index 0000000..29d778c
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/VideoSurfaceView.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.SurfaceView;
+
+/**
+ * Activity transition will change transitionVisibility multiple times even the view is not
+ * running transition, which causes visual flickering during activity return transition.
+ * This class disables setTransitionVisibility() to avoid the problem.
+ * @hide
+ */
+public class VideoSurfaceView extends SurfaceView {
+
+ public VideoSurfaceView(Context context) {
+ super(context);
+ }
+
+ public VideoSurfaceView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ /**
+ * Overrides hidden method View.setTransitionVisibility() to disable visibility changes
+ * in activity transition.
+ */
+ public void setTransitionVisibility(int visibility) {
+ }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java b/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
index 1c95194..28d7aeb 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/picker/Picker.java
@@ -197,6 +197,11 @@
// Width is dynamic, so has fixed size is false.
columnView.setHasFixedSize(false);
columnView.setFocusable(isActivated());
+ // Setting cache size to zero in order to rebind item views when picker widget becomes
+ // activated. Rebinding is necessary to update the alphas when the columns are expanded
+ // as a result of the picker getting activated, otherwise the cached views with the
+ // wrong alphas could be laid out.
+ columnView.setItemViewCacheSize(0);
mColumnViews.add(columnView);
// add view to root
@@ -550,9 +555,6 @@
@Override
public void setActivated(boolean activated) {
- if (activated && !isFocusable()) {
- throw new IllegalStateException("Cannot activate an unfocusable Picker widget.");
- }
if (activated == isActivated()) {
super.setActivated(activated);
return;
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/DatePickerTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/DatePickerTest.java
index fc0df10..9a0b1c5 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/DatePickerTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/DatePickerTest.java
@@ -18,6 +18,7 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.content.Intent;
@@ -314,6 +315,66 @@
mDatePickerInnerView.getChildAt(4).hasFocus(), is(true));
}
+ @Test
+ public void testInvisibleColumnsAlpha() throws Throwable {
+ Intent intent = new Intent();
+ intent.putExtra(DatePickerActivity.EXTRA_LAYOUT_RESOURCE_ID,
+ R.layout.datepicker_with_other_widgets);
+ initActivity(intent);
+
+ mActivityTestRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mDatePickerView.updateDate(2017, 2, 21, false);
+ }
+ });
+
+ Thread.sleep(TRANSITION_LENGTH);
+ mActivityTestRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mDatePickerView.updateDate(2017, 2, 20, false);
+ }
+ });
+ Thread.sleep(TRANSITION_LENGTH);
+
+ sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+ Thread.sleep(TRANSITION_LENGTH);
+ // Click once to activate
+ sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+ Thread.sleep(TRANSITION_LENGTH);
+
+ int activeColumn = 0;
+ // For the inactive columns: the alpha for all the rows except the selected row should be
+ // zero: Picker#mInvisibleColumnAlpha (they should all be invisible).
+ for (int i = 0; i < 3; i++) {
+ ViewGroup gridView = (ViewGroup) mDatePickerInnerView.getChildAt(2 * i);
+ int childCount = gridView.getChildCount();
+ int alpha1RowsCount = 0;
+ int alphaNonZeroRowsCount = 0;
+ for (int j = 0; j < childCount; j++) {
+ View pickerItem = gridView.getChildAt(j);
+ if (pickerItem.getAlpha() > 0) {
+ alphaNonZeroRowsCount++;
+ }
+ if (pickerItem.getAlpha() == 1) {
+ alpha1RowsCount++;
+ }
+ }
+ if (i == activeColumn) {
+ assertThat("The active column " + i + " should have only one row with an alpha of "
+ + "1", alpha1RowsCount, is(1));
+ assertTrue("The active column " + i + " should have more than one view with alpha "
+ + "greater than 1", alphaNonZeroRowsCount > 1);
+ } else {
+ assertThat("The inactive column " + i + " should have only one row with an alpha of"
+ + " 1", alpha1RowsCount, is(1));
+ assertThat("The inactive column " + i + " should have only one row with a non-zero"
+ + " alpha", alphaNonZeroRowsCount, is(1));
+ }
+ }
+ }
+
private void sendKeys(int ...keys) {
for (int i = 0; i < keys.length; i++) {
InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keys[i]);
diff --git a/v7/mediarouter/res/drawable-hdpi/ic_media_stop_dark.png b/v7/mediarouter/res/drawable-hdpi/ic_media_stop_dark.png
new file mode 100644
index 0000000..801d341
--- /dev/null
+++ b/v7/mediarouter/res/drawable-hdpi/ic_media_stop_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/ic_media_stop_light.png b/v7/mediarouter/res/drawable-hdpi/ic_media_stop_light.png
new file mode 100644
index 0000000..9d6b65d
--- /dev/null
+++ b/v7/mediarouter/res/drawable-hdpi/ic_media_stop_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/ic_media_stop_dark.png b/v7/mediarouter/res/drawable-mdpi/ic_media_stop_dark.png
new file mode 100644
index 0000000..3ad2c9c
--- /dev/null
+++ b/v7/mediarouter/res/drawable-mdpi/ic_media_stop_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/ic_media_stop_light.png b/v7/mediarouter/res/drawable-mdpi/ic_media_stop_light.png
new file mode 100644
index 0000000..b002ab7
--- /dev/null
+++ b/v7/mediarouter/res/drawable-mdpi/ic_media_stop_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_dark.png b/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_dark.png
new file mode 100644
index 0000000..5239336
--- /dev/null
+++ b/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_light.png b/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_light.png
new file mode 100644
index 0000000..5bc5a6c
--- /dev/null
+++ b/v7/mediarouter/res/drawable-xhdpi/ic_media_stop_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_dark.png b/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_dark.png
new file mode 100644
index 0000000..035ca18
--- /dev/null
+++ b/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_light.png b/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_light.png
new file mode 100644
index 0000000..eac183d
--- /dev/null
+++ b/v7/mediarouter/res/drawable-xxhdpi/ic_media_stop_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable/mr_media_stop_dark.xml b/v7/mediarouter/res/drawable/mr_media_stop_dark.xml
new file mode 100644
index 0000000..9757552
--- /dev/null
+++ b/v7/mediarouter/res/drawable/mr_media_stop_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/ic_media_stop_dark" />
+</selector>
diff --git a/v7/mediarouter/res/drawable/mr_media_stop_light.xml b/v7/mediarouter/res/drawable/mr_media_stop_light.xml
new file mode 100644
index 0000000..c7717c7
--- /dev/null
+++ b/v7/mediarouter/res/drawable/mr_media_stop_light.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <bitmap
+ android:src="@drawable/ic_media_stop_light"
+ android:alpha="0.87" />
+ </item>
+</selector>
diff --git a/v7/mediarouter/res/layout/mr_playback_control.xml b/v7/mediarouter/res/layout/mr_playback_control.xml
index b441254..9d788f6 100644
--- a/v7/mediarouter/res/layout/mr_playback_control.xml
+++ b/v7/mediarouter/res/layout/mr_playback_control.xml
@@ -20,7 +20,7 @@
android:orientation="horizontal"
android:paddingLeft="24dp"
android:paddingRight="12dp" >
- <ImageButton android:id="@+id/mr_control_play_pause"
+ <ImageButton android:id="@+id/mr_control_playback_ctrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
@@ -33,7 +33,7 @@
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_toLeftOf="@id/mr_control_play_pause"
+ android:layout_toLeftOf="@id/mr_control_playback_ctrl"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true">
<TextView android:id="@+id/mr_control_title"
diff --git a/v7/mediarouter/res/values-af/strings.xml b/v7/mediarouter/res/values-af/strings.xml
index 444ffc2..9d311a9 100644
--- a/v7/mediarouter/res/values-af/strings.xml
+++ b/v7/mediarouter/res/values-af/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Saai uit na"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Vind tans toestelle"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Ontkoppel"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Hou op uitsaai"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Hou op uitsaai"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Maak toe"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Speel"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Laat wag"</string>
diff --git a/v7/mediarouter/res/values-am/strings.xml b/v7/mediarouter/res/values-am/strings.xml
index 96a2c09..ef7f3be 100644
--- a/v7/mediarouter/res/values-am/strings.xml
+++ b/v7/mediarouter/res/values-am/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Cast አድርግ ወደ"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"መሣሪያዎችን በማግኘት ላይ"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"ግንኙነት አቋርጥ"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Cast ማድረግ አቁም"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Cast ማድረግ አቁም"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"ዝጋ"</string>
<string name="mr_controller_play" msgid="683634565969987458">"አጫውት"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"ለአፍታ አቁም"</string>
diff --git a/v7/mediarouter/res/values-ar/strings.xml b/v7/mediarouter/res/values-ar/strings.xml
index 3caf4b6..897460c 100644
--- a/v7/mediarouter/res/values-ar/strings.xml
+++ b/v7/mediarouter/res/values-ar/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"إرسال إلى"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"جارٍ البحث عن أجهزة"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"قطع الاتصال"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"إيقاف الإرسال"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"إيقاف الإرسال"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"إغلاق"</string>
<string name="mr_controller_play" msgid="683634565969987458">"تشغيل"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"إيقاف مؤقت"</string>
diff --git a/v7/mediarouter/res/values-az/strings.xml b/v7/mediarouter/res/values-az/strings.xml
index 31574c3..a7cc571 100644
--- a/v7/mediarouter/res/values-az/strings.xml
+++ b/v7/mediarouter/res/values-az/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Bura yayımlayın"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Cihazlar axtarılır"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Bağlantını kəsin"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Yayımı dayandırın"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Yayımı dayandırın"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Qapadın"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Oynadın"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Durdurun"</string>
diff --git a/v7/mediarouter/res/values-b+sr+Latn/strings.xml b/v7/mediarouter/res/values-b+sr+Latn/strings.xml
index 4bc9baa..3aeaa7e 100644
--- a/v7/mediarouter/res/values-b+sr+Latn/strings.xml
+++ b/v7/mediarouter/res/values-b+sr+Latn/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Prebacuj na"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Pronalaženje uređaja"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Prekini vezu"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Zaustavi prebacivanje"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zaustavi prebacivanje"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Zatvori"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Pusti"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pauziraj"</string>
diff --git a/v7/mediarouter/res/values-be/strings.xml b/v7/mediarouter/res/values-be/strings.xml
index 75c24d5..93ccc1a 100644
--- a/v7/mediarouter/res/values-be/strings.xml
+++ b/v7/mediarouter/res/values-be/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Трансляваць на"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Пошук прылад"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Адлучыць"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Спыніць трансляцыю"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Спыніць трансляцыю"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Закрыць"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Прайграць"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Прыпыніць"</string>
diff --git a/v7/mediarouter/res/values-bg/strings.xml b/v7/mediarouter/res/values-bg/strings.xml
index d756d6c..ef4db0a 100644
--- a/v7/mediarouter/res/values-bg/strings.xml
+++ b/v7/mediarouter/res/values-bg/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Предаване към"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Търсят се устройства"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Прекратяване на връзката"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Спиране на предаването"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Спиране на предаването"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Затваряне"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Пускане"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Поставяне на пауза"</string>
diff --git a/v7/mediarouter/res/values-bn/strings.xml b/v7/mediarouter/res/values-bn/strings.xml
index b94b9af..d542100 100644
--- a/v7/mediarouter/res/values-bn/strings.xml
+++ b/v7/mediarouter/res/values-bn/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"এতে কাস্ট করুন"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"ডিভাইসগুলিকে খোঁজা হচ্ছে"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"সংযোগ বিচ্ছিন্ন করুন"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"কাস্ট করা বন্ধ করুন"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"কাস্ট করা বন্ধ করুন"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"বন্ধ করুন"</string>
<string name="mr_controller_play" msgid="683634565969987458">"চালান"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"বিরাম দিন"</string>
diff --git a/v7/mediarouter/res/values-bs/strings.xml b/v7/mediarouter/res/values-bs/strings.xml
index df4e3ef..cd8e586 100644
--- a/v7/mediarouter/res/values-bs/strings.xml
+++ b/v7/mediarouter/res/values-bs/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Prebacujte na"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Traženje uređaja"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Prekini vezu"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Zaustavi prebacivanje"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zaustavi prebacivanje"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Zatvori"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reproduciraj"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pauziraj"</string>
diff --git a/v7/mediarouter/res/values-ca/strings.xml b/v7/mediarouter/res/values-ca/strings.xml
index 400d424..875290f 100644
--- a/v7/mediarouter/res/values-ca/strings.xml
+++ b/v7/mediarouter/res/values-ca/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Emet a"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"S\'estan cercant dispositius"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconnecta"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Atura l\'emissió"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Atura l\'emissió"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Tanca"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reprodueix"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Posa en pausa"</string>
diff --git a/v7/mediarouter/res/values-cs/strings.xml b/v7/mediarouter/res/values-cs/strings.xml
index 5a29bac..532612a 100644
--- a/v7/mediarouter/res/values-cs/strings.xml
+++ b/v7/mediarouter/res/values-cs/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Odesílat do"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Hledání zařízení"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Odpojit"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Zastavit odesílání"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zastavit odesílání"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Zavřít"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Přehrát"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pozastavit"</string>
diff --git a/v7/mediarouter/res/values-da/strings.xml b/v7/mediarouter/res/values-da/strings.xml
index f33a4ee..55864a0 100644
--- a/v7/mediarouter/res/values-da/strings.xml
+++ b/v7/mediarouter/res/values-da/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Cast til"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Finder enheder"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Afbryd"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Stop med at caste"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stop med at caste"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Luk"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Afspil"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Sæt på pause"</string>
diff --git a/v7/mediarouter/res/values-de/strings.xml b/v7/mediarouter/res/values-de/strings.xml
index 13686aa..50025de 100644
--- a/v7/mediarouter/res/values-de/strings.xml
+++ b/v7/mediarouter/res/values-de/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Streamen auf"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Geräte werden gesucht."</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Verbindung trennen"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Streaming stoppen"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Streaming stoppen"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Schließen"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Wiedergeben"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausieren"</string>
diff --git a/v7/mediarouter/res/values-el/strings.xml b/v7/mediarouter/res/values-el/strings.xml
index 3f45621..fd415cc 100644
--- a/v7/mediarouter/res/values-el/strings.xml
+++ b/v7/mediarouter/res/values-el/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Μετάδοση σε"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Εύρεση συσκευών"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Αποσύνδεση"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Διακοπή μετάδοσης"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Διακοπή μετάδοσης"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Κλείσιμο"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Αναπαραγωγή"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Παύση"</string>
diff --git a/v7/mediarouter/res/values-en-rAU/strings.xml b/v7/mediarouter/res/values-en-rAU/strings.xml
index 9201c1f..7ce2f28 100644
--- a/v7/mediarouter/res/values-en-rAU/strings.xml
+++ b/v7/mediarouter/res/values-en-rAU/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Cast to"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Finding devices"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Disconnect"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Stop casting"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stop casting"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Close"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Play"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pause"</string>
diff --git a/v7/mediarouter/res/values-en-rGB/strings.xml b/v7/mediarouter/res/values-en-rGB/strings.xml
index 9201c1f..7ce2f28 100644
--- a/v7/mediarouter/res/values-en-rGB/strings.xml
+++ b/v7/mediarouter/res/values-en-rGB/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Cast to"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Finding devices"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Disconnect"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Stop casting"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stop casting"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Close"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Play"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pause"</string>
diff --git a/v7/mediarouter/res/values-en-rIN/strings.xml b/v7/mediarouter/res/values-en-rIN/strings.xml
index 9201c1f..7ce2f28 100644
--- a/v7/mediarouter/res/values-en-rIN/strings.xml
+++ b/v7/mediarouter/res/values-en-rIN/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Cast to"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Finding devices"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Disconnect"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Stop casting"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stop casting"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Close"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Play"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pause"</string>
diff --git a/v7/mediarouter/res/values-es-rUS/strings.xml b/v7/mediarouter/res/values-es-rUS/strings.xml
index 90aa823..9b411dd 100644
--- a/v7/mediarouter/res/values-es-rUS/strings.xml
+++ b/v7/mediarouter/res/values-es-rUS/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Transmitir a"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Buscando dispositivos"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Detener la transmisión"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Detener la transmisión"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Cerrar"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reproducir"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausar"</string>
diff --git a/v7/mediarouter/res/values-es/strings.xml b/v7/mediarouter/res/values-es/strings.xml
index 52a886f..057d3d2 100644
--- a/v7/mediarouter/res/values-es/strings.xml
+++ b/v7/mediarouter/res/values-es/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Enviar a"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Buscando dispositivos"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Dejar de enviar contenido"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Dejar de enviar contenido"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Cerrar"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reproducir"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausa"</string>
diff --git a/v7/mediarouter/res/values-et/strings.xml b/v7/mediarouter/res/values-et/strings.xml
index ce1847a..8fa0e94 100644
--- a/v7/mediarouter/res/values-et/strings.xml
+++ b/v7/mediarouter/res/values-et/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Ülekandmine seadmesse"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Seadmete otsimine"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Katkesta ühendus"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Peata ülekanne"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Peata ülekanne"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Sulgemine"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Esitamine"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Peatamine"</string>
diff --git a/v7/mediarouter/res/values-eu/strings.xml b/v7/mediarouter/res/values-eu/strings.xml
index c03d73b..d8efeba 100644
--- a/v7/mediarouter/res/values-eu/strings.xml
+++ b/v7/mediarouter/res/values-eu/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Igorri hona"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Gailuak bilatzen"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Deskonektatu"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Utzi igortzeari"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Utzi igortzeari"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Itxi"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Erreproduzitu"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausatu"</string>
diff --git a/v7/mediarouter/res/values-fa/strings.xml b/v7/mediarouter/res/values-fa/strings.xml
index 7cc9fbc..8d965d1 100644
--- a/v7/mediarouter/res/values-fa/strings.xml
+++ b/v7/mediarouter/res/values-fa/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"ارسال محتوا به"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"پیدا کردن دستگاهها"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"قطع ارتباط"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"توقف ارسال محتوا"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"توقف ارسال محتوا"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"بستن"</string>
<string name="mr_controller_play" msgid="683634565969987458">"پخش"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"مکث"</string>
diff --git a/v7/mediarouter/res/values-fi/strings.xml b/v7/mediarouter/res/values-fi/strings.xml
index 2465802..41727ef 100644
--- a/v7/mediarouter/res/values-fi/strings.xml
+++ b/v7/mediarouter/res/values-fi/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Suoratoiston kohde"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Etsitään laitteita"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Katkaise yhteys"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Lopeta suoratoisto"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Lopeta suoratoisto"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Sulje"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Toista"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Keskeytä"</string>
diff --git a/v7/mediarouter/res/values-fr-rCA/strings.xml b/v7/mediarouter/res/values-fr-rCA/strings.xml
index fd1ea8c..9f489f2 100644
--- a/v7/mediarouter/res/values-fr-rCA/strings.xml
+++ b/v7/mediarouter/res/values-fr-rCA/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Diffuser sur"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Recherche d\'appareils"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Se déconnecter"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Arrêter la diffusion"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Arrêter la diffusion"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Fermer"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Lire"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Interrompre"</string>
diff --git a/v7/mediarouter/res/values-fr/strings.xml b/v7/mediarouter/res/values-fr/strings.xml
index 8c96485..86f70bb 100644
--- a/v7/mediarouter/res/values-fr/strings.xml
+++ b/v7/mediarouter/res/values-fr/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Caster sur"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Recherche d\'appareils en cours…"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Déconnecter"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Arrêter de diffuser"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Arrêter de diffuser"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Fermer"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Lecture"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pause"</string>
diff --git a/v7/mediarouter/res/values-gl/strings.xml b/v7/mediarouter/res/values-gl/strings.xml
index d6d1888..7d250bf 100644
--- a/v7/mediarouter/res/values-gl/strings.xml
+++ b/v7/mediarouter/res/values-gl/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Emitir en"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Buscando dispositivos"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Deter emisión"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Deter emisión"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Pechar"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reproduce"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausa"</string>
diff --git a/v7/mediarouter/res/values-gu/strings.xml b/v7/mediarouter/res/values-gu/strings.xml
index eb7a9b8..6c2237e 100644
--- a/v7/mediarouter/res/values-gu/strings.xml
+++ b/v7/mediarouter/res/values-gu/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"આના પર કાસ્ટ કરો"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"ઉપકરણો શોધી રહ્યાં છીએ"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"ડિસ્કનેક્ટ કરો"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"કાસ્ટ કરવાનું રોકો"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"કાસ્ટ કરવાનું રોકો"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"બંધ કરો"</string>
<string name="mr_controller_play" msgid="683634565969987458">"ચલાવો"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"થોભાવો"</string>
diff --git a/v7/mediarouter/res/values-hi/strings.xml b/v7/mediarouter/res/values-hi/strings.xml
index 5b01c7c..04a8f53 100644
--- a/v7/mediarouter/res/values-hi/strings.xml
+++ b/v7/mediarouter/res/values-hi/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"इस पर कास्ट करें"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"डिवाइस ढूंढ रहा है"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"डिसकनेक्ट करें"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"कास्ट करना बंद करें"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"कास्ट करना बंद करें"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"बंद करें"</string>
<string name="mr_controller_play" msgid="683634565969987458">"चलाएं"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"रोकें"</string>
diff --git a/v7/mediarouter/res/values-hr/strings.xml b/v7/mediarouter/res/values-hr/strings.xml
index f50d748..83b2a7a 100644
--- a/v7/mediarouter/res/values-hr/strings.xml
+++ b/v7/mediarouter/res/values-hr/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Emitiranje na"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Traženje uređaja"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Prekini vezu"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Zaustavi emitiranje"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zaustavi emitiranje"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Zatvaranje"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reprodukcija"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pauziranje"</string>
diff --git a/v7/mediarouter/res/values-hu/strings.xml b/v7/mediarouter/res/values-hu/strings.xml
index 6420985..9d4b770 100644
--- a/v7/mediarouter/res/values-hu/strings.xml
+++ b/v7/mediarouter/res/values-hu/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Átküldés ide"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Eszközök keresése"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Leválasztás"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Átküldés leállítása"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Átküldés leállítása"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Bezárás"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Lejátszás"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Szüneteltetés"</string>
diff --git a/v7/mediarouter/res/values-hy/strings.xml b/v7/mediarouter/res/values-hy/strings.xml
index 6e46af8..f1221d1 100644
--- a/v7/mediarouter/res/values-hy/strings.xml
+++ b/v7/mediarouter/res/values-hy/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Ընտրեք սարքը"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Սարքերի որոնում"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Անջատել"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Դադարեցնել հեռարձակումը"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Դադարեցնել հեռարձակումը"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Փակել"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Նվագարկել"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Դադար"</string>
diff --git a/v7/mediarouter/res/values-in/strings.xml b/v7/mediarouter/res/values-in/strings.xml
index 43e0c62..fbe906a 100644
--- a/v7/mediarouter/res/values-in/strings.xml
+++ b/v7/mediarouter/res/values-in/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Transmisikan ke"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Mencari perangkat"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Putuskan sambungan"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Hentikan transmisi"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Hentikan transmisi"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Tutup"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Putar"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Jeda"</string>
diff --git a/v7/mediarouter/res/values-is/strings.xml b/v7/mediarouter/res/values-is/strings.xml
index 53de253..cf5308e 100644
--- a/v7/mediarouter/res/values-is/strings.xml
+++ b/v7/mediarouter/res/values-is/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Senda út í"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Leitað að tækjum"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Aftengjast"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Stöðva útsendingu"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stöðva útsendingu"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Loka"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Spila"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Hlé"</string>
diff --git a/v7/mediarouter/res/values-it/strings.xml b/v7/mediarouter/res/values-it/strings.xml
index df6bbfe..b8f12a5 100644
--- a/v7/mediarouter/res/values-it/strings.xml
+++ b/v7/mediarouter/res/values-it/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Trasmetti a"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Ricerca di dispositivi in corso"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Scollega"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Interrompi trasmissione"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Interrompi trasmissione"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Chiudi"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Riproduci"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausa"</string>
diff --git a/v7/mediarouter/res/values-iw/strings.xml b/v7/mediarouter/res/values-iw/strings.xml
index be705a6..89a136a 100644
--- a/v7/mediarouter/res/values-iw/strings.xml
+++ b/v7/mediarouter/res/values-iw/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"העבר אל"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"מחפש מכשירים"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"נתק"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"עצור העברה"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"עצור העברה"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"סגור"</string>
<string name="mr_controller_play" msgid="683634565969987458">"הפעל"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"השהה"</string>
diff --git a/v7/mediarouter/res/values-ja/strings.xml b/v7/mediarouter/res/values-ja/strings.xml
index 75d75d6..6b731d2 100644
--- a/v7/mediarouter/res/values-ja/strings.xml
+++ b/v7/mediarouter/res/values-ja/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"キャストするデバイス"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"端末を検索しています"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"接続を解除"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"キャストを停止"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"キャストを停止"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"閉じる"</string>
<string name="mr_controller_play" msgid="683634565969987458">"再生"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"一時停止"</string>
diff --git a/v7/mediarouter/res/values-ka/strings.xml b/v7/mediarouter/res/values-ka/strings.xml
index 3bcc513..584203f 100644
--- a/v7/mediarouter/res/values-ka/strings.xml
+++ b/v7/mediarouter/res/values-ka/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"ტრანსლირებული"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"მიმდინარეობს მოწყობილობების მოძიება"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"კავშირის გაწყვეტა"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"ტრანსლირების შეჩერება"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ტრანსლირების შეჩერება"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"დახურვა"</string>
<string name="mr_controller_play" msgid="683634565969987458">"დაკვრა"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"პაუზა"</string>
diff --git a/v7/mediarouter/res/values-kk/strings.xml b/v7/mediarouter/res/values-kk/strings.xml
index 43e75b7..185fbf9 100644
--- a/v7/mediarouter/res/values-kk/strings.xml
+++ b/v7/mediarouter/res/values-kk/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Келесіге трансляциялау"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Құрылғыларды табу"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Ажырату"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Трансляциялауды тоқтату"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Трансляциялауды тоқтату"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Жабу"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Ойнату"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Кідірту"</string>
diff --git a/v7/mediarouter/res/values-km/strings.xml b/v7/mediarouter/res/values-km/strings.xml
index 44d88f4..7a92a77 100644
--- a/v7/mediarouter/res/values-km/strings.xml
+++ b/v7/mediarouter/res/values-km/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"ខាសទៅ"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"ស្វែងរកឧបករណ៍"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"ផ្ដាច់"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"បញ្ឈប់ការខាស"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"បញ្ឈប់ការខាស"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"បិទ"</string>
<string name="mr_controller_play" msgid="683634565969987458">"ចាក់"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"ផ្អាក"</string>
diff --git a/v7/mediarouter/res/values-kn/strings.xml b/v7/mediarouter/res/values-kn/strings.xml
index 193d449..a493757 100644
--- a/v7/mediarouter/res/values-kn/strings.xml
+++ b/v7/mediarouter/res/values-kn/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"ಇದಕ್ಕೆ ಬಿತ್ತರಿಸಿ"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"ಸಾಧನಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸು"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"ಬಿತ್ತರಿಸುವಿಕೆ ನಿಲ್ಲಿಸು"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ಬಿತ್ತರಿಸುವಿಕೆ ನಿಲ್ಲಿಸು"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"ಮುಚ್ಚು"</string>
<string name="mr_controller_play" msgid="683634565969987458">"ಪ್ಲೇ ಮಾಡಿ"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"ವಿರಾಮ"</string>
diff --git a/v7/mediarouter/res/values-ko/strings.xml b/v7/mediarouter/res/values-ko/strings.xml
index 242560a..8630f4f 100644
--- a/v7/mediarouter/res/values-ko/strings.xml
+++ b/v7/mediarouter/res/values-ko/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"전송할 기기"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"기기를 찾는 중"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"연결 해제"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"전송 중지"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"전송 중지"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"닫기"</string>
<string name="mr_controller_play" msgid="683634565969987458">"재생"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"일시중지"</string>
diff --git a/v7/mediarouter/res/values-ky/strings.xml b/v7/mediarouter/res/values-ky/strings.xml
index 0898ade..82f64be 100644
--- a/v7/mediarouter/res/values-ky/strings.xml
+++ b/v7/mediarouter/res/values-ky/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Төмөнкүгө чыгаруу"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Түзмөктөр изделүүдө"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Ажыратуу"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Тышк экранга чыгарну токтотуу"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Тышк экранга чыгарну токтотуу"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Жабуу"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Ойнотуу"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Тындыруу"</string>
diff --git a/v7/mediarouter/res/values-lo/strings.xml b/v7/mediarouter/res/values-lo/strings.xml
index 65b3472..8771268 100644
--- a/v7/mediarouter/res/values-lo/strings.xml
+++ b/v7/mediarouter/res/values-lo/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"ຄາສທ໌ຫາ"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"ກຳລັງຊອກຫາອຸປະກອນ"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"ຕັດການເຊື່ອມຕໍ່"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"ຢຸດການຄາສທ໌"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ຢຸດການຄາສທ໌"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"ປິດ"</string>
<string name="mr_controller_play" msgid="683634565969987458">"ຫຼິ້ນ"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"ຢຸດຊົ່ວຄາວ"</string>
diff --git a/v7/mediarouter/res/values-lt/strings.xml b/v7/mediarouter/res/values-lt/strings.xml
index 35931cf..45398f0 100644
--- a/v7/mediarouter/res/values-lt/strings.xml
+++ b/v7/mediarouter/res/values-lt/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Perduoti į"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Randami įrenginiai"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Atjungti"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Sustabdyti perdavimą"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Sustabdyti perdavimą"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Uždaryti"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Leisti"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pristabdyti"</string>
diff --git a/v7/mediarouter/res/values-lv/strings.xml b/v7/mediarouter/res/values-lv/strings.xml
index c146174..e01705e 100644
--- a/v7/mediarouter/res/values-lv/strings.xml
+++ b/v7/mediarouter/res/values-lv/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Apraidīšana uz ierīci"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Notiek ierīču meklēšana"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Atvienot"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Pārtraukt apraidi"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Pārtraukt apraidi"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Aizvērt"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Atskaņot"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Apturēt"</string>
diff --git a/v7/mediarouter/res/values-mk/strings.xml b/v7/mediarouter/res/values-mk/strings.xml
index 6fd428f..205467e 100644
--- a/v7/mediarouter/res/values-mk/strings.xml
+++ b/v7/mediarouter/res/values-mk/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Емитувај на"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Наоѓање уреди"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Исклучи"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Запри го емитувањето"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Запри го емитувањето"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Затвори"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Репродуцирај"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Паузирај"</string>
diff --git a/v7/mediarouter/res/values-ml/strings.xml b/v7/mediarouter/res/values-ml/strings.xml
index 63a37f8..00fc9dc 100644
--- a/v7/mediarouter/res/values-ml/strings.xml
+++ b/v7/mediarouter/res/values-ml/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"ഇതിലേക്ക് കാസ്റ്റുചെയ്യുക"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"ഉപകരണങ്ങൾ കണ്ടെത്തുന്നു"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"വിച്ഛേദിക്കുക"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"കാസ്റ്റുചെയ്യൽ നിർത്തുക"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"കാസ്റ്റുചെയ്യൽ നിർത്തുക"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"അടയ്ക്കുക"</string>
<string name="mr_controller_play" msgid="683634565969987458">"പ്ലേ ചെയ്യുക"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"തൽക്കാലം നിർത്തൂ"</string>
diff --git a/v7/mediarouter/res/values-mn/strings.xml b/v7/mediarouter/res/values-mn/strings.xml
index 1197bfe..cccf05e 100644
--- a/v7/mediarouter/res/values-mn/strings.xml
+++ b/v7/mediarouter/res/values-mn/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Дамжуулах"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Төхөөрөмж хайж байна"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Салгах"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Дамжуулахыг зогсоох"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Дамжуулахыг зогсоох"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Хаах"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Тоглуулах"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Түр зогсоох"</string>
diff --git a/v7/mediarouter/res/values-mr/strings.xml b/v7/mediarouter/res/values-mr/strings.xml
index 40d7d66..37374b4 100644
--- a/v7/mediarouter/res/values-mr/strings.xml
+++ b/v7/mediarouter/res/values-mr/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"यावर कास्ट करा"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"डिव्हाइसेस शोधत आहे"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"डिस्कनेक्ट करा"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"कास्ट करणे थांबवा"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"कास्ट करणे थांबवा"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"बंद करा"</string>
<string name="mr_controller_play" msgid="683634565969987458">"प्ले करा"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"विराम"</string>
diff --git a/v7/mediarouter/res/values-ms/strings.xml b/v7/mediarouter/res/values-ms/strings.xml
index cc32b96..6474884 100644
--- a/v7/mediarouter/res/values-ms/strings.xml
+++ b/v7/mediarouter/res/values-ms/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Hantar ke"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Mencari peranti"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Putuskan sambungan"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Berhenti menghantar"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Berhenti menghantar"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Tutup"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Main"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Jeda"</string>
diff --git a/v7/mediarouter/res/values-my/strings.xml b/v7/mediarouter/res/values-my/strings.xml
index e31cc92..836d137 100644
--- a/v7/mediarouter/res/values-my/strings.xml
+++ b/v7/mediarouter/res/values-my/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"သို့ ကာစ်တ်လုပ်ရန်"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"စက်ပစ္စည်းများ ရှာဖွေခြင်း"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"ဆက်သွယ်မှု ဖြတ်ရန်"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"ကာစ်တ်လုပ်ခြင်း ရပ်တန့်ရန်"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ကာစ်တ်လုပ်ခြင်း ရပ်တန့်ရန်"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"ပိတ်ရန်"</string>
<string name="mr_controller_play" msgid="683634565969987458">"ဖွင့်ရန်"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"ခဏရပ်ရန်"</string>
diff --git a/v7/mediarouter/res/values-nb/strings.xml b/v7/mediarouter/res/values-nb/strings.xml
index 97ca73c..172d9d4 100644
--- a/v7/mediarouter/res/values-nb/strings.xml
+++ b/v7/mediarouter/res/values-nb/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Cast til"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Finner enheter"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Koble fra"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Stopp castingen"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Stopp castingen"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Lukk"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Spill av"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Sett på pause"</string>
diff --git a/v7/mediarouter/res/values-ne/strings.xml b/v7/mediarouter/res/values-ne/strings.xml
index 0e48b45..e9e4f03 100644
--- a/v7/mediarouter/res/values-ne/strings.xml
+++ b/v7/mediarouter/res/values-ne/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"यसमा Cast गर्नुहोस्"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"यन्त्रहरू पत्ता लगाउँदै"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"विच्छेद गर्नुहोस्"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"casting रोक्नुहोस्"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"casting रोक्नुहोस्"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"बन्द गर्नुहोस्"</string>
<string name="mr_controller_play" msgid="683634565969987458">"बजाउनुहोस्"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"रोक्नुहोस्"</string>
diff --git a/v7/mediarouter/res/values-nl/strings.xml b/v7/mediarouter/res/values-nl/strings.xml
index 5c899fd..21364e7 100644
--- a/v7/mediarouter/res/values-nl/strings.xml
+++ b/v7/mediarouter/res/values-nl/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Casten naar"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Apparaten zoeken"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Loskoppelen"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Casten stoppen"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Casten stoppen"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Sluiten"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Afspelen"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Onderbreken"</string>
diff --git a/v7/mediarouter/res/values-pa/strings.xml b/v7/mediarouter/res/values-pa/strings.xml
index c207246..906903f 100644
--- a/v7/mediarouter/res/values-pa/strings.xml
+++ b/v7/mediarouter/res/values-pa/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"ਇਸ ਨਾਲ ਕਾਸਟ ਕਰੋ"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"ਡਿਵਾਈਸਾਂ ਲੱਭ ਰਿਹਾ ਹੈ"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"ਕਾਸਟ ਕਰਨਾ ਰੋਕੋ"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ਕਾਸਟ ਕਰਨਾ ਰੋਕੋ"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"ਬੰਦ ਕਰੋ"</string>
<string name="mr_controller_play" msgid="683634565969987458">"ਪਲੇ ਕਰੋ"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"ਰੋਕੋ"</string>
diff --git a/v7/mediarouter/res/values-pl/strings.xml b/v7/mediarouter/res/values-pl/strings.xml
index 0320550..db0934d 100644
--- a/v7/mediarouter/res/values-pl/strings.xml
+++ b/v7/mediarouter/res/values-pl/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Przesyłaj na"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Znajdowanie urządzeń"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Odłącz"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Zatrzymaj przesyłanie"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zatrzymaj przesyłanie"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Zamknij"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Odtwórz"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Wstrzymaj"</string>
diff --git a/v7/mediarouter/res/values-pt-rBR/strings.xml b/v7/mediarouter/res/values-pt-rBR/strings.xml
index 2fd84b1..b424082 100644
--- a/v7/mediarouter/res/values-pt-rBR/strings.xml
+++ b/v7/mediarouter/res/values-pt-rBR/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Transmitir para"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Localizando dispositivos"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Interromper transmissão"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Interromper transmissão"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Fechar"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reproduzir"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausar"</string>
diff --git a/v7/mediarouter/res/values-pt-rPT/strings.xml b/v7/mediarouter/res/values-pt-rPT/strings.xml
index b62f363..c6c52f9 100644
--- a/v7/mediarouter/res/values-pt-rPT/strings.xml
+++ b/v7/mediarouter/res/values-pt-rPT/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Transmitir para"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"A localizar dispositivos"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Desassociar"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Interromper a transmissão"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Interromper a transmissão"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Fechar"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reproduzir"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Interromper"</string>
diff --git a/v7/mediarouter/res/values-pt/strings.xml b/v7/mediarouter/res/values-pt/strings.xml
index 2fd84b1..b424082 100644
--- a/v7/mediarouter/res/values-pt/strings.xml
+++ b/v7/mediarouter/res/values-pt/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Transmitir para"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Localizando dispositivos"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Desconectar"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Interromper transmissão"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Interromper transmissão"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Fechar"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Reproduzir"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausar"</string>
diff --git a/v7/mediarouter/res/values-ro/strings.xml b/v7/mediarouter/res/values-ro/strings.xml
index 769a0ac..ab2fd61 100644
--- a/v7/mediarouter/res/values-ro/strings.xml
+++ b/v7/mediarouter/res/values-ro/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Proiectați pe"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Se caută dispozitive"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Deconectați-vă"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Opriți proiecția"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Opriți proiecția"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Închideți"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Redați"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Întrerupeți"</string>
diff --git a/v7/mediarouter/res/values-ru/strings.xml b/v7/mediarouter/res/values-ru/strings.xml
index 9bd2170..768f300 100644
--- a/v7/mediarouter/res/values-ru/strings.xml
+++ b/v7/mediarouter/res/values-ru/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Выберите устройство"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Поиск устройств…"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Отключить"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Остановить трансляцию"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Остановить трансляцию"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Закрыть"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Воспроизвести"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Приостановить"</string>
diff --git a/v7/mediarouter/res/values-si/strings.xml b/v7/mediarouter/res/values-si/strings.xml
index baeac3e..e26a087 100644
--- a/v7/mediarouter/res/values-si/strings.xml
+++ b/v7/mediarouter/res/values-si/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"විකාශය"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"උපාංග සෙවීම"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"විසන්ධි කරන්න"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"විකාශ කිරීම නවත්වන්න"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"විකාශ කිරීම නවත්වන්න"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"වසන්න"</string>
<string name="mr_controller_play" msgid="683634565969987458">"ධාවනය කරන්න"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"විරාම ගන්වන්න"</string>
diff --git a/v7/mediarouter/res/values-sk/strings.xml b/v7/mediarouter/res/values-sk/strings.xml
index 4a0f4bf..92c7307 100644
--- a/v7/mediarouter/res/values-sk/strings.xml
+++ b/v7/mediarouter/res/values-sk/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Prenos do"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Vyhľadávanie zariadení"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Odpojiť"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Zastaviť prenos"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Zastaviť prenos"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Zavrieť"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Prehrať"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pozastaviť"</string>
diff --git a/v7/mediarouter/res/values-sl/strings.xml b/v7/mediarouter/res/values-sl/strings.xml
index 4ca2bdc..ba5609e 100644
--- a/v7/mediarouter/res/values-sl/strings.xml
+++ b/v7/mediarouter/res/values-sl/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Predvajanje prek:"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Iskanje naprav"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Prekini povezavo"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Ustavi predvajanje"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Ustavi predvajanje"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Zapri"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Predvajanje"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Zaustavi"</string>
diff --git a/v7/mediarouter/res/values-sq/strings.xml b/v7/mediarouter/res/values-sq/strings.xml
index 45e3a34..5ebfbab 100644
--- a/v7/mediarouter/res/values-sq/strings.xml
+++ b/v7/mediarouter/res/values-sq/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Transmeto te"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Gjetja e pajisjeve"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Shkëpute"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Ndalo transmetimin"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Ndalo transmetimin"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Mbyll"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Luaj"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pauzë"</string>
diff --git a/v7/mediarouter/res/values-sr/strings.xml b/v7/mediarouter/res/values-sr/strings.xml
index ef1b2b1..2b5e9fd 100644
--- a/v7/mediarouter/res/values-sr/strings.xml
+++ b/v7/mediarouter/res/values-sr/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Пребацуј на"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Проналажење уређаја"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Прекини везу"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Заустави пребацивање"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Заустави пребацивање"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Затвори"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Пусти"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Паузирај"</string>
diff --git a/v7/mediarouter/res/values-sv/strings.xml b/v7/mediarouter/res/values-sv/strings.xml
index 9597bf9..9be5f57 100644
--- a/v7/mediarouter/res/values-sv/strings.xml
+++ b/v7/mediarouter/res/values-sv/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Casta till"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Letar efter enheter"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Koppla från"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Sluta casta"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Sluta casta"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Stäng"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Spela upp"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Pausa"</string>
diff --git a/v7/mediarouter/res/values-sw/strings.xml b/v7/mediarouter/res/values-sw/strings.xml
index f7ae8f5..989f420 100644
--- a/v7/mediarouter/res/values-sw/strings.xml
+++ b/v7/mediarouter/res/values-sw/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Tuma kwenye"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Inatafuta vifaa"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Ondoa"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Acha kutuma"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Acha kutuma"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Funga"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Cheza"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Sitisha"</string>
diff --git a/v7/mediarouter/res/values-ta/strings.xml b/v7/mediarouter/res/values-ta/strings.xml
index 0ef3fc3..decdebd 100644
--- a/v7/mediarouter/res/values-ta/strings.xml
+++ b/v7/mediarouter/res/values-ta/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"இதில் திரையிடு"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"சாதனங்களைத் தேடுகிறது"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"தொடர்பைத் துண்டி"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"அனுப்புவதை நிறுத்து"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"அனுப்புவதை நிறுத்து"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"மூடும்"</string>
<string name="mr_controller_play" msgid="683634565969987458">"இயக்கும்"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"இடைநிறுத்தும்"</string>
diff --git a/v7/mediarouter/res/values-te/strings.xml b/v7/mediarouter/res/values-te/strings.xml
index c7ae34f..7412980 100644
--- a/v7/mediarouter/res/values-te/strings.xml
+++ b/v7/mediarouter/res/values-te/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"దీనికి ప్రసారం చేయండి"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"పరికరాలను కనుగొంటోంది"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"డిస్కనెక్ట్ చేయి"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"ప్రసారాన్ని ఆపివేయి"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"ప్రసారాన్ని ఆపివేయి"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"మూసివేస్తుంది"</string>
<string name="mr_controller_play" msgid="683634565969987458">"ప్లే చేస్తుంది"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"పాజ్ చేస్తుంది"</string>
diff --git a/v7/mediarouter/res/values-th/strings.xml b/v7/mediarouter/res/values-th/strings.xml
index 219374c..231aa2e 100644
--- a/v7/mediarouter/res/values-th/strings.xml
+++ b/v7/mediarouter/res/values-th/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"แคสต์ไปยัง"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"กำลังค้นหาอุปกรณ์"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"ยกเลิกการเชื่อมต่อ"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"หยุดการแคสต์"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"หยุดการแคสต์"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"ปิด"</string>
<string name="mr_controller_play" msgid="683634565969987458">"เล่น"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"หยุดชั่วคราว"</string>
diff --git a/v7/mediarouter/res/values-tl/strings.xml b/v7/mediarouter/res/values-tl/strings.xml
index e2bb7c7..c128aba 100644
--- a/v7/mediarouter/res/values-tl/strings.xml
+++ b/v7/mediarouter/res/values-tl/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"I-cast sa"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Naghahanap ng mga device"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Idiskonekta"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Itigil ang pagca-cast"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Itigil ang pagca-cast"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Isara"</string>
<string name="mr_controller_play" msgid="683634565969987458">"I-play"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"I-pause"</string>
diff --git a/v7/mediarouter/res/values-tr/strings.xml b/v7/mediarouter/res/values-tr/strings.xml
index 187682f..6bc7072 100644
--- a/v7/mediarouter/res/values-tr/strings.xml
+++ b/v7/mediarouter/res/values-tr/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Şuraya yayınla:"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Cihazlar bulunuyor"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Bağlantıyı kes"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Yayını durdur"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Yayını durdur"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Kapat"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Oynat"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Duraklat"</string>
diff --git a/v7/mediarouter/res/values-uk/strings.xml b/v7/mediarouter/res/values-uk/strings.xml
index 8c2a16a..1f9104e 100644
--- a/v7/mediarouter/res/values-uk/strings.xml
+++ b/v7/mediarouter/res/values-uk/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Транслювати на"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Пошук пристроїв"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Відключити"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Припинити трансляцію"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Припинити трансляцію"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Закрити"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Відтворити"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Призупинити"</string>
diff --git a/v7/mediarouter/res/values-ur/strings.xml b/v7/mediarouter/res/values-ur/strings.xml
index 053373f..667fddc 100644
--- a/v7/mediarouter/res/values-ur/strings.xml
+++ b/v7/mediarouter/res/values-ur/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"اس میں کاسٹ کریں"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"آلات تلاش ہو رہے ہیں"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"غیر منسلک کریں"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"کاسٹ کرنا بند کریں"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"کاسٹ کرنا بند کریں"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"بند کریں"</string>
<string name="mr_controller_play" msgid="683634565969987458">"چلائیں"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"موقوف کریں"</string>
diff --git a/v7/mediarouter/res/values-uz/strings.xml b/v7/mediarouter/res/values-uz/strings.xml
index 9d1e455..91b5e49 100644
--- a/v7/mediarouter/res/values-uz/strings.xml
+++ b/v7/mediarouter/res/values-uz/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Quyidagiga translatsiya qilish:"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Qurilmalarni topish"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Ulanishni uzish"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Translatsiyani to‘xtatish"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Translatsiyani to‘xtatish"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Yopish"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Boshlash"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"To‘xtatib turish"</string>
diff --git a/v7/mediarouter/res/values-vi/strings.xml b/v7/mediarouter/res/values-vi/strings.xml
index 488b9f0..44e7a6a 100644
--- a/v7/mediarouter/res/values-vi/strings.xml
+++ b/v7/mediarouter/res/values-vi/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Truyền tới"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Tìm thiết bị"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Ngắt kết nối"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Dừng truyền"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Dừng truyền"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Đóng"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Phát"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Tạm dừng"</string>
diff --git a/v7/mediarouter/res/values-zh-rCN/strings.xml b/v7/mediarouter/res/values-zh-rCN/strings.xml
index 30c7dcc..a8e8f92 100644
--- a/v7/mediarouter/res/values-zh-rCN/strings.xml
+++ b/v7/mediarouter/res/values-zh-rCN/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"投射到"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"正在查找设备"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"断开连接"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"停止投射"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"停止投射"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"关闭"</string>
<string name="mr_controller_play" msgid="683634565969987458">"播放"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"暂停"</string>
diff --git a/v7/mediarouter/res/values-zh-rHK/strings.xml b/v7/mediarouter/res/values-zh-rHK/strings.xml
index d17469b..0aebac0 100644
--- a/v7/mediarouter/res/values-zh-rHK/strings.xml
+++ b/v7/mediarouter/res/values-zh-rHK/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"投放至"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"正在尋找裝置"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"中斷連線"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"停止投放"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"停止投放"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"關閉"</string>
<string name="mr_controller_play" msgid="683634565969987458">"播放"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"暫停"</string>
diff --git a/v7/mediarouter/res/values-zh-rTW/strings.xml b/v7/mediarouter/res/values-zh-rTW/strings.xml
index 1a71c84..aa9c75b 100644
--- a/v7/mediarouter/res/values-zh-rTW/strings.xml
+++ b/v7/mediarouter/res/values-zh-rTW/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"投放到"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"正在尋找裝置"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"中斷連線"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"停止投放"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"停止投放"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"關閉"</string>
<string name="mr_controller_play" msgid="683634565969987458">"播放"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"暫停"</string>
diff --git a/v7/mediarouter/res/values-zu/strings.xml b/v7/mediarouter/res/values-zu/strings.xml
index 860aa09..db82ffa 100644
--- a/v7/mediarouter/res/values-zu/strings.xml
+++ b/v7/mediarouter/res/values-zu/strings.xml
@@ -25,7 +25,7 @@
<string name="mr_chooser_title" msgid="414301941546135990">"Sakaza ku-"</string>
<string name="mr_chooser_searching" msgid="6349900579507521956">"Ithola amadivayisi"</string>
<string name="mr_controller_disconnect" msgid="1227264889412989580">"Nqamula"</string>
- <string name="mr_controller_stop" msgid="4570331844078181931">"Misa ukusakaza"</string>
+ <string name="mr_controller_stop_casting" msgid="4570331844078181931">"Misa ukusakaza"</string>
<string name="mr_controller_close_description" msgid="7333862312480583260">"Vala"</string>
<string name="mr_controller_play" msgid="683634565969987458">"Dlala"</string>
<string name="mr_controller_pause" msgid="5451884435510905406">"Misa isikhashana"</string>
diff --git a/v7/mediarouter/res/values/attrs.xml b/v7/mediarouter/res/values/attrs.xml
index cf6a7b5..68511c8 100644
--- a/v7/mediarouter/res/values/attrs.xml
+++ b/v7/mediarouter/res/values/attrs.xml
@@ -32,6 +32,7 @@
<attr name="mediaRouteCloseDrawable" format="reference" />
<attr name="mediaRoutePlayDrawable" format="reference" />
<attr name="mediaRoutePauseDrawable" format="reference" />
+ <attr name="mediaRouteStopDrawable" format="reference" />
<attr name="mediaRouteAudioTrackDrawable" format="reference" />
<attr name="mediaRouteDefaultIconDrawable" format="reference" />
<attr name="mediaRouteTvIconDrawable" format="reference" />
diff --git a/v7/mediarouter/res/values/strings.xml b/v7/mediarouter/res/values/strings.xml
index bff7176..630a482 100644
--- a/v7/mediarouter/res/values/strings.xml
+++ b/v7/mediarouter/res/values/strings.xml
@@ -47,7 +47,7 @@
<string name="mr_controller_disconnect">Disconnect</string>
<!-- Button to stop playback and disconnect from a media route. [CHAR LIMIT=30] -->
- <string name="mr_controller_stop">Stop casting</string>
+ <string name="mr_controller_stop_casting">Stop casting</string>
<!-- Content description for accessibility (not shown on the screen): dialog close button. [CHAR LIMIT=NONE] -->
<string name="mr_controller_close_description">Close</string>
@@ -58,6 +58,9 @@
<!-- Content description for accessibility (not shown on the screen): media pause button. [CHAR LIMIT=NONE] -->
<string name="mr_controller_pause">Pause</string>
+ <!-- Content description for accessibility (not shown on the screen): media stop button. [CHAR LIMIT=NONE] -->
+ <string name="mr_controller_stop">Stop</string>
+
<!-- Content description for accessibility (not shown on the screen): group expand button. Pressing button shows group members of a selected route group. [CHAR LIMIT=NONE] -->
<string name="mr_controller_expand_group">Expand</string>
diff --git a/v7/mediarouter/res/values/themes.xml b/v7/mediarouter/res/values/themes.xml
index 1eb4bfd..8c6e97a 100644
--- a/v7/mediarouter/res/values/themes.xml
+++ b/v7/mediarouter/res/values/themes.xml
@@ -23,6 +23,7 @@
<item name="mediaRouteCloseDrawable">@drawable/mr_dialog_close_dark</item>
<item name="mediaRoutePlayDrawable">@drawable/mr_media_play_dark</item>
<item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_dark</item>
+ <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_dark</item>
<item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_dark</item>
<item name="mediaRouteDefaultIconDrawable">@drawable/ic_mr_button_disconnected_dark</item>
<item name="mediaRouteTvIconDrawable">@drawable/ic_vol_type_tv_dark</item>
@@ -43,6 +44,7 @@
<item name="mediaRouteCloseDrawable">@drawable/mr_dialog_close_light</item>
<item name="mediaRoutePlayDrawable">@drawable/mr_media_play_light</item>
<item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_light</item>
+ <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_light</item>
<item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_light</item>
<item name="mediaRouteDefaultIconDrawable">@drawable/ic_mr_button_grey</item>
<item name="mediaRouteTvIconDrawable">@drawable/ic_vol_type_tv_light</item>
@@ -59,12 +61,14 @@
<style name="ThemeOverlay.MediaRouter.Dark" parent="ThemeOverlay.AppCompat.Dark">
<item name="mediaRoutePlayDrawable">@drawable/mr_media_play_dark</item>
<item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_dark</item>
+ <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_dark</item>
<item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_dark</item>
</style>
<style name="ThemeOverlay.MediaRouter.Light" parent="ThemeOverlay.AppCompat.Light">
<item name="mediaRoutePlayDrawable">@drawable/mr_media_play_light</item>
<item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_light</item>
+ <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_light</item>
<item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_light</item>
</style>
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
index 961e37e..4d40610 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
@@ -16,6 +16,11 @@
package android.support.v7.app;
+import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PAUSE;
+import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY;
+import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY_PAUSE;
+import static android.support.v4.media.session.PlaybackStateCompat.ACTION_STOP;
+
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
@@ -67,7 +72,6 @@
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
-
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -119,7 +123,7 @@
private Button mDisconnectButton;
private Button mStopCastingButton;
- private ImageButton mPlayPauseButton;
+ private ImageButton mPlaybackControlButton;
private ImageButton mCloseButton;
private MediaRouteExpandCollapseButton mGroupExpandCollapseButton;
@@ -351,7 +355,7 @@
mDisconnectButton.setOnClickListener(listener);
mStopCastingButton = (Button) findViewById(BUTTON_STOP_RES_ID);
- mStopCastingButton.setText(R.string.mr_controller_stop);
+ mStopCastingButton.setText(R.string.mr_controller_stop_casting);
mStopCastingButton.setTextColor(color);
mStopCastingButton.setOnClickListener(listener);
@@ -388,8 +392,8 @@
mPlaybackControlLayout = (RelativeLayout) findViewById(R.id.mr_playback_control);
mTitleView = (TextView) findViewById(R.id.mr_control_title);
mSubtitleView = (TextView) findViewById(R.id.mr_control_subtitle);
- mPlayPauseButton = (ImageButton) findViewById(R.id.mr_control_play_pause);
- mPlayPauseButton.setOnClickListener(listener);
+ mPlaybackControlButton = (ImageButton) findViewById(R.id.mr_control_playback_ctrl);
+ mPlaybackControlButton.setOnClickListener(listener);
mVolumeControlLayout = (LinearLayout) findViewById(R.id.mr_volume_control);
mVolumeControlLayout.setVisibility(View.GONE);
@@ -1006,30 +1010,47 @@
if (mState != null) {
boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
|| mState.getState() == PlaybackStateCompat.STATE_PLAYING;
- boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY
- | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
- boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE
- | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
- Context playPauseButtonContext = mPlayPauseButton.getContext();
- if (isPlaying && supportsPause) {
- mPlayPauseButton.setVisibility(View.VISIBLE);
- mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
- playPauseButtonContext, R.attr.mediaRoutePauseDrawable));
- mPlayPauseButton.setContentDescription(playPauseButtonContext.getResources()
- .getText(R.string.mr_controller_pause));
- } else if (!isPlaying && supportsPlay) {
- mPlayPauseButton.setVisibility(View.VISIBLE);
- mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
- playPauseButtonContext, R.attr.mediaRoutePlayDrawable));
- mPlayPauseButton.setContentDescription(playPauseButtonContext.getResources()
- .getText(R.string.mr_controller_play));
+ Context playbackControlButtonContext = mPlaybackControlButton.getContext();
+ boolean visible = true;
+ int iconDrawableAttr = 0;
+ int iconDescResId = 0;
+ if (isPlaying && isPauseActionSupported()) {
+ iconDrawableAttr = R.attr.mediaRoutePauseDrawable;
+ iconDescResId = R.string.mr_controller_pause;
+ } else if (isPlaying && isStopActionSupported()) {
+ iconDrawableAttr = R.attr.mediaRouteStopDrawable;
+ iconDescResId = R.string.mr_controller_stop;
+ } else if (!isPlaying && isPlayActionSupported()) {
+ iconDrawableAttr = R.attr.mediaRoutePlayDrawable;
+ iconDescResId = R.string.mr_controller_play;
} else {
- mPlayPauseButton.setVisibility(View.GONE);
+ visible = false;
+ }
+ mPlaybackControlButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+ if (visible) {
+ mPlaybackControlButton.setImageResource(
+ MediaRouterThemeHelper.getThemeResource(
+ playbackControlButtonContext, iconDrawableAttr));
+ mPlaybackControlButton.setContentDescription(
+ playbackControlButtonContext.getResources()
+ .getText(iconDescResId));
}
}
}
}
+ private boolean isPlayActionSupported() {
+ return (mState.getActions() & (ACTION_PLAY | ACTION_PLAY_PAUSE)) != 0;
+ }
+
+ private boolean isPauseActionSupported() {
+ return (mState.getActions() & (ACTION_PAUSE | ACTION_PLAY_PAUSE)) != 0;
+ }
+
+ private boolean isStopActionSupported() {
+ return (mState.getActions() & ACTION_STOP) != 0;
+ }
+
boolean isVolumeControlAvailable(MediaRouter.RouteInfo route) {
return mVolumeControlEnabled && route.getVolumeHandling()
== MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
@@ -1172,23 +1193,28 @@
MediaRouter.UNSELECT_REASON_DISCONNECTED);
}
dismiss();
- } else if (id == R.id.mr_control_play_pause) {
+ } else if (id == R.id.mr_control_playback_ctrl) {
if (mMediaController != null && mState != null) {
boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_PLAYING;
- if (isPlaying) {
+ int actionDescResId = 0;
+ if (isPlaying && isPauseActionSupported()) {
mMediaController.getTransportControls().pause();
- } else {
+ actionDescResId = R.string.mr_controller_pause;
+ } else if (isPlaying && isStopActionSupported()) {
+ mMediaController.getTransportControls().stop();
+ actionDescResId = R.string.mr_controller_stop;
+ } else if (!isPlaying && isPlayActionSupported()){
mMediaController.getTransportControls().play();
+ actionDescResId = R.string.mr_controller_play;
}
// Announce the action for accessibility.
- if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()) {
+ if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()
+ && actionDescResId != 0) {
AccessibilityEvent event = AccessibilityEvent.obtain(
AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
event.setPackageName(mContext.getPackageName());
event.setClassName(getClass().getName());
- int resId = isPlaying ?
- R.string.mr_controller_pause : R.string.mr_controller_play;
- event.getText().add(mContext.getString(resId));
+ event.getText().add(mContext.getString(actionDescResId));
mAccessibilityManager.sendAccessibilityEvent(event);
}
}
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index 3c8e64d..fe16de8 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -18,7 +18,6 @@
import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -2089,11 +2088,6 @@
throw new IllegalStateException("There is no currently selected route. "
+ "The media router has not yet been fully initialized.");
}
- // A workaround for making this method work properly.
- if (android.os.Build.VERSION.SDK_INT >= 16 && android.os.Build.VERSION.SDK_INT < 25
- && RouteInfo.isSystemMediaRouteProvider(mSelectedRoute)) {
- syncSystemRoutes();
- }
return mSelectedRoute;
}
@@ -2110,12 +2104,6 @@
Log.w(TAG, "Ignoring attempt to select disabled route: " + route);
return;
}
-
- // A workaround for making this method work properly.
- if (android.os.Build.VERSION.SDK_INT >= 16 && android.os.Build.VERSION.SDK_INT < 25
- && RouteInfo.isSystemMediaRouteProvider(route)) {
- syncSystemRoutes();
- }
setSelectedRouteInternal(route, unselectReason);
}
@@ -2250,25 +2238,6 @@
}
}
- @TargetApi(16)
- void syncSystemRoutes() {
- Object routerObj = MediaRouterJellybean.getMediaRouter(mApplicationContext);
- boolean routedToBluetooth = MediaRouterJellybean.checkRoutedToBluetooth(
- mApplicationContext);
- Object selectedRouteObj = MediaRouterJellybean.getSelectedRoute(
- routerObj, MediaRouterJellybean.ALL_ROUTE_TYPES);
- Object defaultRouteObj = mSystemProvider.getDefaultRoute();
- Object bluetoothRouteObj = mSystemProvider.getSystemRoute(mBluetoothRoute);
-
- if (routedToBluetooth && selectedRouteObj == defaultRouteObj) {
- MediaRouterJellybean.selectRoute(routerObj,
- MediaRouterJellybean.ALL_ROUTE_TYPES, bluetoothRouteObj);
- } else if (!routedToBluetooth && selectedRouteObj == bluetoothRouteObj) {
- MediaRouterJellybean.selectRoute(routerObj,
- MediaRouterJellybean.ALL_ROUTE_TYPES, defaultRouteObj);
- }
- }
-
void updateProviderDescriptor(MediaRouteProvider providerInstance,
MediaRouteProviderDescriptor descriptor) {
int index = findProviderInfo(providerInstance);
diff --git a/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java b/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
index 60f601c..fad3448 100644
--- a/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
+++ b/v7/recyclerview/src/android/support/v7/widget/GridLayoutManager.java
@@ -1017,98 +1017,47 @@
limit = getChildCount();
}
final boolean preferLastSpan = mOrientation == VERTICAL && isLayoutRTL();
+ View weakCandidate = null; // somewhat matches but not strong
+ int weakCandidateSpanIndex = -1;
+ int weakCandidateOverlap = 0; // how many spans overlap
- // The focusable candidate to be picked if no perfect focusable candidate is found.
- // The best focusable candidate is the one with the highest amount of span overlap with
- // the currently focused view.
- View focusableWeakCandidate = null; // somewhat matches but not strong
- int focusableWeakCandidateSpanIndex = -1;
- int focusableWeakCandidateOverlap = 0; // how many spans overlap
-
- // The unfocusable candidate to become visible on the screen next, if no perfect or
- // weak focusable candidates are found to receive focus next.
- // We are only interested in partially visible unfocusable views. These are views that are
- // not fully visible, that is either partially overlapping, or out-of-bounds and right below
- // or above RV's padded bounded area. The best unfocusable candidate is the one with the
- // highest amount of span overlap with the currently focused view.
- View unfocusableWeakCandidate = null; // somewhat matches but not strong
- int unfocusableWeakCandidateSpanIndex = -1;
- int unfocusableWeakCandidateOverlap = 0; // how many spans overlap
-
- // The span group index of the start child. This indicates the span group index of the
- // next focusable item to receive focus, if a focusable item within the same span group
- // exists. Any focusable item beyond this group index are not relevant since they
- // were already stored in the layout before onFocusSearchFailed call and were not picked
- // by the focusSearch algorithm.
- int focusableSpanGroupIndex = getSpanGroupIndex(recycler, state, start);
for (int i = start; i != limit; i += inc) {
- int spanGroupIndex = getSpanGroupIndex(recycler, state, i);
View candidate = getChildAt(i);
if (candidate == prevFocusedChild) {
break;
}
-
- if (candidate.isFocusable() && spanGroupIndex != focusableSpanGroupIndex) {
- // We are past the allowable span group index for the next focusable item.
- // The search only continues if no focusable weak candidates have been found up
- // until this point, in order to find the best unfocusable candidate to become
- // visible on the screen next.
- if (focusableWeakCandidate != null) {
- break;
- }
+ if (!candidate.isFocusable()) {
continue;
}
-
final LayoutParams candidateLp = (LayoutParams) candidate.getLayoutParams();
final int candidateStart = candidateLp.mSpanIndex;
final int candidateEnd = candidateLp.mSpanIndex + candidateLp.mSpanSize;
- if (candidate.isFocusable() && candidateStart == prevSpanStart
- && candidateEnd == prevSpanEnd) {
+ if (candidateStart == prevSpanStart && candidateEnd == prevSpanEnd) {
return candidate; // perfect match
}
boolean assignAsWeek = false;
- if ((candidate.isFocusable() && focusableWeakCandidate == null)
- || (!candidate.isFocusable() && unfocusableWeakCandidate == null)) {
+ if (weakCandidate == null) {
assignAsWeek = true;
} else {
int maxStart = Math.max(candidateStart, prevSpanStart);
int minEnd = Math.min(candidateEnd, prevSpanEnd);
int overlap = minEnd - maxStart;
- if (candidate.isFocusable()) {
- if (overlap > focusableWeakCandidateOverlap) {
- assignAsWeek = true;
- } else if (overlap == focusableWeakCandidateOverlap
- && preferLastSpan == (candidateStart
- > focusableWeakCandidateSpanIndex)) {
- assignAsWeek = true;
- }
- } else if (focusableWeakCandidate == null
- && isViewPartiallyVisible(candidate, false, true)) {
- if (overlap > unfocusableWeakCandidateOverlap) {
- assignAsWeek = true;
- } else if (overlap == unfocusableWeakCandidateOverlap
- && preferLastSpan == (candidateStart
- > unfocusableWeakCandidateSpanIndex)) {
- assignAsWeek = true;
- }
+ if (overlap > weakCandidateOverlap) {
+ assignAsWeek = true;
+ } else if (overlap == weakCandidateOverlap &&
+ preferLastSpan == (candidateStart > weakCandidateSpanIndex)) {
+ assignAsWeek = true;
}
}
if (assignAsWeek) {
- if (candidate.isFocusable()) {
- focusableWeakCandidate = candidate;
- focusableWeakCandidateSpanIndex = candidateLp.mSpanIndex;
- focusableWeakCandidateOverlap = Math.min(candidateEnd, prevSpanEnd)
- - Math.max(candidateStart, prevSpanStart);
- } else {
- unfocusableWeakCandidate = candidate;
- unfocusableWeakCandidateSpanIndex = candidateLp.mSpanIndex;
- unfocusableWeakCandidateOverlap = Math.min(candidateEnd, prevSpanEnd)
- - Math.max(candidateStart, prevSpanStart);
- }
+ weakCandidate = candidate;
+ weakCandidateSpanIndex = candidateLp.mSpanIndex;
+ weakCandidateOverlap = Math.min(candidateEnd, prevSpanEnd) -
+ Math.max(candidateStart, prevSpanStart);
}
}
- return (focusableWeakCandidate != null) ? focusableWeakCandidate : unfocusableWeakCandidate;
+ return weakCandidate;
}
@Override
diff --git a/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java b/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
index 65a2045..2436a4c 100644
--- a/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
+++ b/v7/recyclerview/src/android/support/v7/widget/LinearLayoutManager.java
@@ -676,8 +676,7 @@
* If necessary, layouts new items for predictive animations
*/
private void layoutForPredictiveAnimations(RecyclerView.Recycler recycler,
- RecyclerView.State state, int startOffset,
- int endOffset) {
+ RecyclerView.State state, int startOffset, int endOffset) {
// If there are scrap children that we did not layout, we need to find where they did go
// and layout them accordingly so that animations can work as expected.
// This case may happen if new views are added or an existing view expands and pushes
@@ -857,7 +856,7 @@
}
anchorInfo.mCoordinate = anchorInfo.mLayoutFromEnd
? (mOrientationHelper.getDecoratedEnd(child) + mOrientationHelper
- .getTotalSpaceChange())
+ .getTotalSpaceChange())
: mOrientationHelper.getDecoratedStart(child);
} else { // item is not visible.
if (getChildCount() > 0) {
@@ -1794,32 +1793,6 @@
return outOfBoundsMatch != null ? outOfBoundsMatch : invalidMatch;
}
- // returns the out-of-bound child view closest to RV's end bounds. An out-of-bound child is
- // defined as a child that's either partially or fully invisible (outside RV's padding area).
- private View findPartiallyOrCompletelyInvisibleChildClosestToEnd(RecyclerView.Recycler recycler,
- RecyclerView.State state) {
- return mShouldReverseLayout ? findFirstPartiallyOrCompletelyInvisibleChild(recycler, state)
- : findLastPartiallyOrCompletelyInvisibleChild(recycler, state);
- }
-
- // returns the out-of-bound child view closest to RV's starting bounds. An out-of-bound child is
- // defined as a child that's either partially or fully invisible (outside RV's padding area).
- private View findPartiallyOrCompletelyInvisibleChildClosestToStart(
- RecyclerView.Recycler recycler, RecyclerView.State state) {
- return mShouldReverseLayout ? findLastPartiallyOrCompletelyInvisibleChild(recycler, state) :
- findFirstPartiallyOrCompletelyInvisibleChild(recycler, state);
- }
-
- private View findFirstPartiallyOrCompletelyInvisibleChild(RecyclerView.Recycler recycler,
- RecyclerView.State state) {
- return findOnePartiallyOrCompletelyInvisibleChild(0, getChildCount());
- }
-
- private View findLastPartiallyOrCompletelyInvisibleChild(RecyclerView.Recycler recycler,
- RecyclerView.State state) {
- return findOnePartiallyOrCompletelyInvisibleChild(getChildCount() - 1, -1);
- }
-
/**
* Returns the adapter position of the first visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
@@ -1903,52 +1876,27 @@
View findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible,
boolean acceptPartiallyVisible) {
ensureLayoutState();
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = 0;
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = 0;
- if (completelyVisible) {
- preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_GT_PVS | ViewBoundsCheck.FLAG_CVS_EQ_PVS
- | ViewBoundsCheck.FLAG_CVE_LT_PVE | ViewBoundsCheck.FLAG_CVE_EQ_PVE);
- } else {
- preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVE | ViewBoundsCheck.FLAG_CVS_EQ_PVE
- | ViewBoundsCheck.FLAG_CVE_GT_PVS | ViewBoundsCheck.FLAG_CVE_EQ_PVS);
+ final int start = mOrientationHelper.getStartAfterPadding();
+ final int end = mOrientationHelper.getEndAfterPadding();
+ final int next = toIndex > fromIndex ? 1 : -1;
+ View partiallyVisible = null;
+ for (int i = fromIndex; i != toIndex; i+=next) {
+ final View child = getChildAt(i);
+ final int childStart = mOrientationHelper.getDecoratedStart(child);
+ final int childEnd = mOrientationHelper.getDecoratedEnd(child);
+ if (childStart < end && childEnd > start) {
+ if (completelyVisible) {
+ if (childStart >= start && childEnd <= end) {
+ return child;
+ } else if (acceptPartiallyVisible && partiallyVisible == null) {
+ partiallyVisible = child;
+ }
+ } else {
+ return child;
+ }
+ }
}
- if (acceptPartiallyVisible) {
- acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVE
- | ViewBoundsCheck.FLAG_CVS_EQ_PVE | ViewBoundsCheck.FLAG_CVE_GT_PVS
- | ViewBoundsCheck.FLAG_CVE_EQ_PVS);
- }
- return (mOrientation == HORIZONTAL) ? mHorizontalBoundCheck
- .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag,
- acceptableBoundsFlag) : mVerticalBoundCheck
- .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag,
- acceptableBoundsFlag);
- }
-
- View findOnePartiallyOrCompletelyInvisibleChild(int fromIndex, int toIndex) {
- ensureLayoutState();
- final int next = toIndex > fromIndex ? 1 : (toIndex < fromIndex ? -1 : 0);
- if (next == 0) {
- return getChildAt(fromIndex);
- }
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = 0;
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = 0;
- if (mOrientationHelper.getDecoratedStart(getChildAt(fromIndex))
- < mOrientationHelper.getStartAfterPadding()) {
- preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS | ViewBoundsCheck.FLAG_CVE_LT_PVE
- | ViewBoundsCheck.FLAG_CVE_GT_PVS);
- acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
- | ViewBoundsCheck.FLAG_CVE_LT_PVE);
- } else {
- preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE | ViewBoundsCheck.FLAG_CVS_GT_PVS
- | ViewBoundsCheck.FLAG_CVS_LT_PVE);
- acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE
- | ViewBoundsCheck.FLAG_CVS_GT_PVS);
- }
- return (mOrientation == HORIZONTAL) ? mHorizontalBoundCheck
- .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag,
- acceptableBoundsFlag) : mVerticalBoundCheck
- .findOneViewWithinBoundFlags(fromIndex, toIndex, preferredBoundsFlag,
- acceptableBoundsFlag);
+ return partiallyVisible;
}
@Override
@@ -1964,38 +1912,35 @@
return null;
}
ensureLayoutState();
+ final View referenceChild;
+ if (layoutDir == LayoutState.LAYOUT_START) {
+ referenceChild = findReferenceChildClosestToStart(recycler, state);
+ } else {
+ referenceChild = findReferenceChildClosestToEnd(recycler, state);
+ }
+ if (referenceChild == null) {
+ if (DEBUG) {
+ Log.d(TAG,
+ "Cannot find a child with a valid position to be used for focus search.");
+ }
+ return null;
+ }
ensureLayoutState();
final int maxScroll = (int) (MAX_SCROLL_FACTOR * mOrientationHelper.getTotalSpace());
updateLayoutState(layoutDir, maxScroll, false, state);
mLayoutState.mScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN;
mLayoutState.mRecycle = false;
fill(recycler, mLayoutState, state, true);
-
- // nextCandidate is the first child view in the layout direction that's partially
- // within RV's bounds, i.e. part of it is visible or it's completely invisible but still
- // touching RV's bounds. This will be the unfocusable candidate view to become visible onto
- // the screen if no focusable views are found in the given layout direction.
- final View nextCandidate;
- if (layoutDir == LayoutState.LAYOUT_START) {
- nextCandidate = findPartiallyOrCompletelyInvisibleChildClosestToStart(recycler, state);
- } else {
- nextCandidate = findPartiallyOrCompletelyInvisibleChildClosestToEnd(recycler, state);
- }
- // nextFocus is meaningful only if it refers to a focusable child, in which case it
- // indicates the next view to gain focus.
final View nextFocus;
if (layoutDir == LayoutState.LAYOUT_START) {
nextFocus = getChildClosestToStart();
} else {
nextFocus = getChildClosestToEnd();
}
- if (nextFocus.isFocusable()) {
- if (nextCandidate == null) {
- return null;
- }
- return nextFocus;
+ if (nextFocus == referenceChild || !nextFocus.isFocusable()) {
+ return null;
}
- return nextCandidate;
+ return nextFocus;
}
/**
@@ -2083,9 +2028,9 @@
if (mShouldReverseLayout) {
if (dropDirection == LayoutState.ITEM_DIRECTION_TAIL) {
scrollToPositionWithOffset(targetPos,
- mOrientationHelper.getEndAfterPadding()
- - (mOrientationHelper.getDecoratedStart(target)
- + mOrientationHelper.getDecoratedMeasurement(view)));
+ mOrientationHelper.getEndAfterPadding() -
+ (mOrientationHelper.getDecoratedStart(target) +
+ mOrientationHelper.getDecoratedMeasurement(view)));
} else {
scrollToPositionWithOffset(targetPos,
mOrientationHelper.getEndAfterPadding()
diff --git a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
index ba01513..2a74928 100644
--- a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
@@ -507,39 +507,38 @@
*/
private final ViewInfoStore.ProcessCallback mViewInfoProcessCallback =
new ViewInfoStore.ProcessCallback() {
- @Override
- public void processDisappeared(ViewHolder viewHolder, @NonNull ItemHolderInfo info,
- @Nullable ItemHolderInfo postInfo) {
- mRecycler.unscrapView(viewHolder);
- animateDisappearance(viewHolder, info, postInfo);
- }
- @Override
- public void processAppeared(ViewHolder viewHolder,
- ItemHolderInfo preInfo, ItemHolderInfo info) {
- animateAppearance(viewHolder, preInfo, info);
- }
+ @Override
+ public void processDisappeared(ViewHolder viewHolder, @NonNull ItemHolderInfo info,
+ @Nullable ItemHolderInfo postInfo) {
+ mRecycler.unscrapView(viewHolder);
+ animateDisappearance(viewHolder, info, postInfo);
+ }
+ @Override
+ public void processAppeared(ViewHolder viewHolder,
+ ItemHolderInfo preInfo, ItemHolderInfo info) {
+ animateAppearance(viewHolder, preInfo, info);
+ }
- @Override
- public void processPersistent(ViewHolder viewHolder,
- @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
- viewHolder.setIsRecyclable(false);
- if (mDataSetHasChangedAfterLayout) {
- // since it was rebound, use change instead as we'll be mapping them from
- // stable ids. If stable ids were false, we would not be running any
- // animations
- if (mItemAnimator.animateChange(viewHolder, viewHolder, preInfo,
- postInfo)) {
- postAnimationRunner();
- }
- } else if (mItemAnimator.animatePersistence(viewHolder, preInfo, postInfo)) {
- postAnimationRunner();
- }
+ @Override
+ public void processPersistent(ViewHolder viewHolder,
+ @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
+ viewHolder.setIsRecyclable(false);
+ if (mDataSetHasChangedAfterLayout) {
+ // since it was rebound, use change instead as we'll be mapping them from
+ // stable ids. If stable ids were false, we would not be running any
+ // animations
+ if (mItemAnimator.animateChange(viewHolder, viewHolder, preInfo, postInfo)) {
+ postAnimationRunner();
}
- @Override
- public void unused(ViewHolder viewHolder) {
- mLayout.removeAndRecycleView(viewHolder.itemView, mRecycler);
- }
- };
+ } else if (mItemAnimator.animatePersistence(viewHolder, preInfo, postInfo)) {
+ postAnimationRunner();
+ }
+ }
+ @Override
+ public void unused(ViewHolder viewHolder) {
+ mLayout.removeAndRecycleView(viewHolder.itemView, mRecycler);
+ }
+ };
public RecyclerView(Context context) {
this(context, null);
@@ -2333,13 +2332,6 @@
resumeRequestLayout(false);
}
}
- if (result != null && !result.hasFocusable()) {
- // If the next view returned by onFocusSearchFailed in layout manager has no focusable
- // views, we still scroll to that view in order to make it visible on the screen.
- // If it's focusable, framework already calls RV's requestChildFocus which handles
- // bringing this newly focused item onto the screen.
- requestChildOnScreen(result, null);
- }
return isPreferredNextFocus(focused, result, direction)
? result : super.focusSearch(focused, direction);
}
@@ -2410,46 +2402,29 @@
@Override
public void requestChildFocus(View child, View focused) {
if (!mLayout.onRequestChildFocus(this, mState, child, focused) && focused != null) {
- requestChildOnScreen(child, focused);
- }
- super.requestChildFocus(child, focused);
- }
+ mTempRect.set(0, 0, focused.getWidth(), focused.getHeight());
- /**
- * Requests that the given child of the RecyclerView be positioned onto the screen. This method
- * can be called for both unfocusable and focusable child views. For unfocusable child views,
- * the {@param focused} parameter passed is null, whereas for a focusable child, this parameter
- * indicates the actual descendant view within this child view that holds the focus.
- * @param child The child view of this RecyclerView that wants to come onto the screen.
- * @param focused The descendant view that actually has the focus if child is focusable, null
- * otherwise.
- */
- private void requestChildOnScreen(@NonNull View child, @Nullable View focused) {
- View rectView = (focused != null) ? focused : child;
- mTempRect.set(0, 0, rectView.getWidth(), rectView.getHeight());
-
- // get item decor offsets w/o refreshing. If they are invalid, there will be another
- // layout pass to fix them, then it is LayoutManager's responsibility to keep focused
- // View in viewport.
- final ViewGroup.LayoutParams focusedLayoutParams = rectView.getLayoutParams();
- if (focusedLayoutParams instanceof LayoutParams) {
- // if focused child has item decors, use them. Otherwise, ignore.
- final LayoutParams lp = (LayoutParams) focusedLayoutParams;
- if (!lp.mInsetsDirty) {
- final Rect insets = lp.mDecorInsets;
- mTempRect.left -= insets.left;
- mTempRect.right += insets.right;
- mTempRect.top -= insets.top;
- mTempRect.bottom += insets.bottom;
+ // get item decor offsets w/o refreshing. If they are invalid, there will be another
+ // layout pass to fix them, then it is LayoutManager's responsibility to keep focused
+ // View in viewport.
+ final ViewGroup.LayoutParams focusedLayoutParams = focused.getLayoutParams();
+ if (focusedLayoutParams instanceof LayoutParams) {
+ // if focused child has item decors, use them. Otherwise, ignore.
+ final LayoutParams lp = (LayoutParams) focusedLayoutParams;
+ if (!lp.mInsetsDirty) {
+ final Rect insets = lp.mDecorInsets;
+ mTempRect.left -= insets.left;
+ mTempRect.right += insets.right;
+ mTempRect.top -= insets.top;
+ mTempRect.bottom += insets.bottom;
+ }
}
- }
- if (focused != null) {
offsetDescendantRectToMyCoords(focused, mTempRect);
offsetRectIntoDescendantCoords(child, mTempRect);
+ requestChildRectangleOnScreen(child, mTempRect, !mFirstLayoutComplete);
}
- mLayout.requestChildRectangleOnScreen(this, child, mTempRect, !mFirstLayoutComplete,
- (focused == null));
+ super.requestChildFocus(child, focused);
}
@Override
@@ -2572,11 +2547,10 @@
throw new IllegalStateException(message);
}
if (mDispatchScrollCounter > 0) {
- Log.w(TAG, "Cannot call this method in a scroll callback. Scroll callbacks might"
- + "be run during a measure & layout pass where you cannot change the"
- + "RecyclerView data. Any method call that might change the structure"
- + "of the RecyclerView or the adapter contents should be postponed to"
- + "the next frame.",
+ Log.w(TAG, "Cannot call this method in a scroll callback. Scroll callbacks might be run"
+ + " during a measure & layout pass where you cannot change the RecyclerView"
+ + " data. Any method call that might change the structure of the RecyclerView"
+ + " or the adapter contents should be postponed to the next frame.",
new IllegalStateException(""));
}
}
@@ -3251,10 +3225,10 @@
mState.mRunSimpleAnimations = mFirstLayoutComplete
&& mItemAnimator != null
&& (mDataSetHasChangedAfterLayout
- || animationTypeSupported
- || mLayout.mRequestedSimpleAnimations)
+ || animationTypeSupported
+ || mLayout.mRequestedSimpleAnimations)
&& (!mDataSetHasChangedAfterLayout
- || mAdapter.hasStableIds());
+ || mAdapter.hasStableIds());
mState.mRunPredictiveAnimations = mState.mRunSimpleAnimations
&& animationTypeSupported
&& !mDataSetHasChangedAfterLayout
@@ -5752,9 +5726,9 @@
if (forceRecycle || holder.isRecyclable()) {
if (mViewCacheMax > 0
&& !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID
- | ViewHolder.FLAG_REMOVED
- | ViewHolder.FLAG_UPDATE
- | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) {
+ | ViewHolder.FLAG_REMOVED
+ | ViewHolder.FLAG_UPDATE
+ | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) {
// Retire oldest cached view
int cachedViewSize = mCachedViews.size();
if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
@@ -6856,109 +6830,6 @@
ChildHelper mChildHelper;
RecyclerView mRecyclerView;
- /**
- * The callback used for retrieving information about a RecyclerView and its children in the
- * horizontal direction.
- */
- private final ViewBoundsCheck.Callback mHorizontalBoundCheckCallback =
- new ViewBoundsCheck.Callback() {
- @Override
- public int getChildCount() {
- return LayoutManager.this.getChildCount();
- }
-
- @Override
- public View getParent() {
- return mRecyclerView;
- }
-
- @Override
- public View getChildAt(int index) {
- return LayoutManager.this.getChildAt(index);
- }
-
- @Override
- public int getParentStart() {
- return LayoutManager.this.getPaddingLeft();
- }
-
- @Override
- public int getParentEnd() {
- return LayoutManager.this.getWidth() - LayoutManager.this.getPaddingRight();
- }
-
- @Override
- public int getChildStart(View view) {
- final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
- view.getLayoutParams();
- return LayoutManager.this.getDecoratedLeft(view) - params.leftMargin;
- }
-
- @Override
- public int getChildEnd(View view) {
- final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
- view.getLayoutParams();
- return LayoutManager.this.getDecoratedRight(view) + params.rightMargin;
- }
- };
-
- /**
- * The callback used for retrieving information about a RecyclerView and its children in the
- * vertical direction.
- */
- private final ViewBoundsCheck.Callback mVerticalBoundCheckCallback =
- new ViewBoundsCheck.Callback() {
- @Override
- public int getChildCount() {
- return LayoutManager.this.getChildCount();
- }
-
- @Override
- public View getParent() {
- return mRecyclerView;
- }
-
- @Override
- public View getChildAt(int index) {
- return LayoutManager.this.getChildAt(index);
- }
-
- @Override
- public int getParentStart() {
- return LayoutManager.this.getPaddingTop();
- }
-
- @Override
- public int getParentEnd() {
- return LayoutManager.this.getHeight()
- - LayoutManager.this.getPaddingBottom();
- }
-
- @Override
- public int getChildStart(View view) {
- final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
- view.getLayoutParams();
- return LayoutManager.this.getDecoratedTop(view) - params.topMargin;
- }
-
- @Override
- public int getChildEnd(View view) {
- final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
- view.getLayoutParams();
- return LayoutManager.this.getDecoratedBottom(view) + params.bottomMargin;
- }
- };
-
- /**
- * Utility objects used to check the boundaries of children against their parent
- * RecyclerView.
- * @see #isViewPartiallyVisible(View, boolean, boolean),
- * {@link LinearLayoutManager#findOneVisibleChild(int, int, boolean, boolean)},
- * and {@link LinearLayoutManager#findOnePartiallyOrCompletelyInvisibleChild(int, int)}.
- */
- ViewBoundsCheck mHorizontalBoundCheck = new ViewBoundsCheck(mHorizontalBoundCheckCallback);
- ViewBoundsCheck mVerticalBoundCheck = new ViewBoundsCheck(mVerticalBoundCheckCallback);
-
@Nullable
SmoothScroller mSmoothScroller;
@@ -9025,11 +8896,7 @@
*
* <p>This is the LayoutManager's opportunity to populate views in the given direction
* to fulfill the request if it can. The LayoutManager should attach and return
- * the view to be focused, if a focusable view in the given direction is found.
- * Otherwise, if all the existing (or the newly populated views) are unfocusable, it returns
- * the next unfocusable view to become visible on the screen. This unfocusable view is
- * typically the first view that's either partially or fully out of RV's padded bounded
- * area in the given direction. The default implementation returns null.</p>
+ * the view to be focused. The default implementation returns null.</p>
*
* @param focused The currently focused view
* @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
@@ -9038,8 +8905,7 @@
* or 0 for not applicable
* @param recycler The recycler to use for obtaining views for currently offscreen items
* @param state Transient state of RecyclerView
- * @return The chosen view to be focused if a focusable view is found, otherwise an
- * unfocusable view to become visible onto the screen, else null.
+ * @return The chosen view to be focused
*/
@Nullable
public View onFocusSearchFailed(View focused, int direction, Recycler recycler,
@@ -9068,20 +8934,22 @@
}
/**
- * Returns the scroll amount that brings the given rect in child's coordinate system within
- * the padded area of RecyclerView.
- * @param parent The parent RecyclerView.
+ * Called when a child of the RecyclerView wants a particular rectangle to be positioned
+ * onto the screen. See {@link ViewParent#requestChildRectangleOnScreen(android.view.View,
+ * android.graphics.Rect, boolean)} for more details.
+ *
+ * <p>The base implementation will attempt to perform a standard programmatic scroll
+ * to bring the given rect into view, within the padded area of the RecyclerView.</p>
+ *
* @param child The direct child making the request.
- * @param rect The rectangle in the child's coordinates the child
- * wishes to be on the screen.
+ * @param rect The rectangle in the child's coordinates the child
+ * wishes to be on the screen.
* @param immediate True to forbid animated or delayed scrolling,
* false otherwise
- * @return The array containing the scroll amount in x and y directions that brings the
- * given rect into RV's padded area.
+ * @return Whether the group scrolled to handle the operation
*/
- private int[] getChildRectangleOnScreenScrollAmount(RecyclerView parent, View child,
- Rect rect, boolean immediate) {
- int[] out = new int[2];
+ public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect,
+ boolean immediate) {
final int parentLeft = getPaddingLeft();
final int parentTop = getPaddingTop();
final int parentRight = getWidth() - getPaddingRight();
@@ -9112,122 +8980,19 @@
// we should scroll to make bottom visible, make sure top does not go out of bounds.
final int dy = offScreenTop != 0 ? offScreenTop
: Math.min(childTop - parentTop, offScreenBottom);
- out[0] = dx;
- out[1] = dy;
- return out;
- }
- /**
- * Called when a child of the RecyclerView wants a particular rectangle to be positioned
- * onto the screen. See {@link ViewParent#requestChildRectangleOnScreen(android.view.View,
- * android.graphics.Rect, boolean)} for more details.
- *
- * <p>The base implementation will attempt to perform a standard programmatic scroll
- * to bring the given rect into view, within the padded area of the RecyclerView.</p>
- *
- * @param child The direct child making the request.
- * @param rect The rectangle in the child's coordinates the child
- * wishes to be on the screen.
- * @param immediate True to forbid animated or delayed scrolling,
- * false otherwise
- * @return Whether the group scrolled to handle the operation
- */
- public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect,
- boolean immediate) {
- return requestChildRectangleOnScreen(parent, child, rect, immediate, false);
- }
- /**
- * Requests that the given child of the RecyclerView be positioned onto the screen. This
- * method can be called for both unfocusable and focusable child views. For unfocusable
- * child views, focusedChildVisible is typically true in which case, layout manager
- * makes the child view visible only if the currently focused child stays in-bounds of RV.
- * @param parent The parent RecyclerView.
- * @param child The direct child making the request.
- * @param rect The rectangle in the child's coordinates the child
- * wishes to be on the screen.
- * @param immediate True to forbid animated or delayed scrolling,
- * false otherwise
- * @param focusedChildVisible Whether the currently focused view must stay visible.
- * @return Whether the group scrolled to handle the operation
- */
- public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect,
- boolean immediate,
- boolean focusedChildVisible) {
- int[] scrollAmount = getChildRectangleOnScreenScrollAmount(parent, child, rect,
- immediate);
- int dx = scrollAmount[0];
- int dy = scrollAmount[1];
- if (!focusedChildVisible || isFocusedChildVisibleAfterScrolling(parent, dx, dy)) {
- if (dx != 0 || dy != 0) {
- if (immediate) {
- parent.scrollBy(dx, dy);
- } else {
- parent.smoothScrollBy(dx, dy);
- }
- return true;
+ if (dx != 0 || dy != 0) {
+ if (immediate) {
+ parent.scrollBy(dx, dy);
+ } else {
+ parent.smoothScrollBy(dx, dy);
}
+ return true;
}
return false;
}
/**
- * Returns whether the given child view is partially or fully visible within the padded
- * bounded area of RecyclerView, depending on the input parameters.
- * A view is partially visible if it has non-zero overlap with RV's padded bounded area.
- * If acceptEndPointInclusion flag is set to true, it's also considered partially
- * visible if it's located outside RV's bounds and it's hitting either RV's start or end
- * bounds.
- *
- * @param child The child view to be examined.
- * @param completelyVisible If true, the method returns true iff the child is completely
- * visible. If false, the method returns true iff the child is only
- * partially visible (that is it will return false if the child is
- * either completely visible or out of RV's bounds).
- * @param acceptEndPointInclusion If the view's endpoint intersection with RV's start of end
- * bounds is enough to consider it partially visible,
- * false otherwise.
- * @return True if the given child is partially or fully visible, false otherwise.
- */
- public boolean isViewPartiallyVisible(@NonNull View child, boolean completelyVisible,
- boolean acceptEndPointInclusion) {
- int boundsFlag = (ViewBoundsCheck.FLAG_CVS_GT_PVS | ViewBoundsCheck.FLAG_CVS_EQ_PVS
- | ViewBoundsCheck.FLAG_CVE_LT_PVE | ViewBoundsCheck.FLAG_CVE_EQ_PVE);
- boolean isViewFullyVisible = mHorizontalBoundCheck.isViewWithinBoundFlags(child,
- boundsFlag)
- && mVerticalBoundCheck.isViewWithinBoundFlags(child, boundsFlag);
- if (completelyVisible) {
- return isViewFullyVisible;
- } else {
- return !isViewFullyVisible;
- }
- }
-
- /**
- * Returns whether the currently focused child stays within RV's bounds with the given
- * amount of scrolling.
- * @param parent The parent RecyclerView.
- * @param dx The scrolling in x-axis direction to be performed.
- * @param dy The scrolling in y-axis direction to be performed.
- * @return Whether after the given scrolling, the currently focused item in still visible
- * (within RV's bounds).
- */
- private boolean isFocusedChildVisibleAfterScrolling(RecyclerView parent, int dx, int dy) {
- final View focusedChild = parent.getFocusedChild();
- final int parentLeft = getPaddingLeft();
- final int parentTop = getPaddingTop();
- final int parentRight = getWidth() - getPaddingRight();
- final int parentBottom = getHeight() - getPaddingBottom();
- final Rect bounds = mRecyclerView.mTempRect;
- getDecoratedBoundsWithMargins(focusedChild, bounds);
-
- if (bounds.left - dx >= parentRight || bounds.right - dx <= parentLeft
- || bounds.top - dy >= parentBottom || bounds.bottom - dy <= parentTop) {
- return false;
- }
- return true;
- }
-
- /**
* @deprecated Use {@link #onRequestChildFocus(RecyclerView, State, View, View)}
*/
@Deprecated
diff --git a/v7/recyclerview/src/android/support/v7/widget/StaggeredGridLayoutManager.java b/v7/recyclerview/src/android/support/v7/widget/StaggeredGridLayoutManager.java
index 6a058af..f6c8fa3 100644
--- a/v7/recyclerview/src/android/support/v7/widget/StaggeredGridLayoutManager.java
+++ b/v7/recyclerview/src/android/support/v7/widget/StaggeredGridLayoutManager.java
@@ -2285,7 +2285,6 @@
return view;
}
}
-
// either could not find from the desired span or prev view is full span.
// traverse all spans
if (preferLastSpan(layoutDir)) {
@@ -2303,44 +2302,6 @@
}
}
}
-
- // Could not find any focusable views from any of the existing spans. Now start the search
- // to find the best unfocusable candidate to become visible on the screen next. The search
- // is done in the same fashion: first, check the views in the desired span and if no
- // candidate is found, traverse the views in all the remaining spans.
- boolean shouldSearchFromStart = !mReverseLayout == (layoutDir == LayoutState.LAYOUT_START);
- View unfocusableCandidate = null;
- if (!prevFocusFullSpan) {
- unfocusableCandidate = findViewByPosition(shouldSearchFromStart
- ? prevFocusSpan.findFirstPartiallyVisibleItemPosition() :
- prevFocusSpan.findLastPartiallyVisibleItemPosition());
- if (unfocusableCandidate != null && unfocusableCandidate != directChild) {
- return unfocusableCandidate;
- }
- }
-
- if (preferLastSpan(layoutDir)) {
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if (i == prevFocusSpan.mIndex) {
- continue;
- }
- unfocusableCandidate = findViewByPosition(shouldSearchFromStart
- ? mSpans[i].findFirstPartiallyVisibleItemPosition() :
- mSpans[i].findLastPartiallyVisibleItemPosition());
- if (unfocusableCandidate != null && unfocusableCandidate != directChild) {
- return unfocusableCandidate;
- }
- }
- } else {
- for (int i = 0; i < mSpanCount; i++) {
- unfocusableCandidate = findViewByPosition(shouldSearchFromStart
- ? mSpans[i].findFirstPartiallyVisibleItemPosition() :
- mSpans[i].findLastPartiallyVisibleItemPosition());
- if (unfocusableCandidate != null && unfocusableCandidate != directChild) {
- return unfocusableCandidate;
- }
- }
- }
return null;
}
@@ -2662,12 +2623,6 @@
: findOneVisibleChild(0, mViews.size(), false);
}
- public int findFirstPartiallyVisibleItemPosition() {
- return mReverseLayout
- ? findOnePartiallyVisibleChild(mViews.size() - 1, -1, true)
- : findOnePartiallyVisibleChild(0, mViews.size(), true);
- }
-
public int findFirstCompletelyVisibleItemPosition() {
return mReverseLayout
? findOneVisibleChild(mViews.size() - 1, -1, true)
@@ -2680,45 +2635,13 @@
: findOneVisibleChild(mViews.size() - 1, -1, false);
}
- public int findLastPartiallyVisibleItemPosition() {
- return mReverseLayout
- ? findOnePartiallyVisibleChild(0, mViews.size(), true)
- : findOnePartiallyVisibleChild(mViews.size() - 1, -1, true);
- }
-
public int findLastCompletelyVisibleItemPosition() {
return mReverseLayout
? findOneVisibleChild(0, mViews.size(), true)
: findOneVisibleChild(mViews.size() - 1, -1, true);
}
- /**
- * Returns the first view within this span that is partially or fully visible. Partially
- * visible refers to a view that overlaps but is not fully contained within RV's padded
- * bounded area. This view returned can be defined to have an area of overlap strictly
- * greater than zero if acceptEndPointInclusion is false. If true, the view's endpoint
- * inclusion is enough to consider it partially visible. The latter case can then refer to
- * an out-of-bounds view positioned right at the top (or bottom) boundaries of RV's padded
- * area. This is used e.g. inside
- * {@link #onFocusSearchFailed(View, int, RecyclerView.Recycler, RecyclerView.State)} for
- * calculating the next unfocusable child to become visible on the screen.
- * @param fromIndex The child position index to start the search from.
- * @param toIndex The child position index to end the search at.
- * @param completelyVisible True if we have to only consider completely visible views,
- * false otherwise.
- * @param acceptCompletelyVisible True if we can consider both partially or fully visible
- * views, false, if only a partially visible child should be
- * returned.
- * @param acceptEndPointInclusion If the view's endpoint intersection with RV's padded
- * bounded area is enough to consider it partially visible,
- * false otherwise
- * @return The adapter position of the first view that's either partially or fully visible.
- * {@link RecyclerView#NO_POSITION} if no such view is found.
- */
- int findOnePartiallyOrCompletelyVisibleChild(int fromIndex, int toIndex,
- boolean completelyVisible,
- boolean acceptCompletelyVisible,
- boolean acceptEndPointInclusion) {
+ int findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible) {
final int start = mPrimaryOrientation.getStartAfterPadding();
final int end = mPrimaryOrientation.getEndAfterPadding();
final int next = toIndex > fromIndex ? 1 : -1;
@@ -2726,22 +2649,12 @@
final View child = mViews.get(i);
final int childStart = mPrimaryOrientation.getDecoratedStart(child);
final int childEnd = mPrimaryOrientation.getDecoratedEnd(child);
- boolean childStartInclusion = acceptEndPointInclusion ? (childStart <= end)
- : (childStart < end);
- boolean childEndInclusion = acceptEndPointInclusion ? (childEnd >= start)
- : (childEnd > start);
- if (childStartInclusion && childEndInclusion) {
- if (completelyVisible && acceptCompletelyVisible) {
- // the child has to be completely visible to be returned.
+ if (childStart < end && childEnd > start) {
+ if (completelyVisible) {
if (childStart >= start && childEnd <= end) {
return getPosition(child);
}
- } else if (acceptCompletelyVisible) {
- // can return either a partially or completely visible child.
- return getPosition(child);
- } else if (childStart < start || childEnd > end) {
- // should return a partially visible child if exists and a completely
- // visible child is not acceptable in this case.
+ } else {
return getPosition(child);
}
}
@@ -2749,17 +2662,6 @@
return NO_POSITION;
}
- int findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible) {
- return findOnePartiallyOrCompletelyVisibleChild(fromIndex, toIndex, completelyVisible,
- true, false);
- }
-
- int findOnePartiallyVisibleChild(int fromIndex, int toIndex,
- boolean acceptEndPointInclusion) {
- return findOnePartiallyOrCompletelyVisibleChild(fromIndex, toIndex, false, false,
- acceptEndPointInclusion);
- }
-
/**
* Depending on the layout direction, returns the View that is after the given position.
*/
@@ -2769,11 +2671,8 @@
final int limit = mViews.size();
for (int i = 0; i < limit; i++) {
final View view = mViews.get(i);
- if ((mReverseLayout && getPosition(view) <= referenceChildPosition)
- || (!mReverseLayout && getPosition(view) >= referenceChildPosition)) {
- break;
- }
- if (view.isFocusable()) {
+ if (view.isFocusable() &&
+ (getPosition(view) > referenceChildPosition == mReverseLayout) ) {
candidate = view;
} else {
break;
@@ -2782,11 +2681,8 @@
} else {
for (int i = mViews.size() - 1; i >= 0; i--) {
final View view = mViews.get(i);
- if ((mReverseLayout && getPosition(view) >= referenceChildPosition)
- || (!mReverseLayout && getPosition(view) <= referenceChildPosition)) {
- break;
- }
- if (view.isFocusable()) {
+ if (view.isFocusable() &&
+ (getPosition(view) > referenceChildPosition == !mReverseLayout)) {
candidate = view;
} else {
break;
diff --git a/v7/recyclerview/src/android/support/v7/widget/ViewBoundsCheck.java b/v7/recyclerview/src/android/support/v7/widget/ViewBoundsCheck.java
deleted file mode 100644
index 8a4f89c..0000000
--- a/v7/recyclerview/src/android/support/v7/widget/ViewBoundsCheck.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v7.widget;
-
-import android.support.annotation.IntDef;
-import android.view.View;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A utility class used to check the boundaries of a given view within its parent view based on
- * a set of boundary flags.
- */
-class ViewBoundsCheck {
-
- static final int GT = 1 << 0;
- static final int EQ = 1 << 1;
- static final int LT = 1 << 2;
-
-
- static final int CVS_PVS_POS = 0;
- /**
- * The child view's start should be strictly greater than parent view's start.
- */
- static final int FLAG_CVS_GT_PVS = GT << CVS_PVS_POS;
-
- /**
- * The child view's start can be equal to its parent view's start. This flag follows with GT
- * or LT indicating greater (less) than or equal relation.
- */
- static final int FLAG_CVS_EQ_PVS = EQ << CVS_PVS_POS;
-
- /**
- * The child view's start should be strictly less than parent view's start.
- */
- static final int FLAG_CVS_LT_PVS = LT << CVS_PVS_POS;
-
-
- static final int CVS_PVE_POS = 4;
- /**
- * The child view's start should be strictly greater than parent view's end.
- */
- static final int FLAG_CVS_GT_PVE = GT << CVS_PVE_POS;
-
- /**
- * The child view's start can be equal to its parent view's end. This flag follows with GT
- * or LT indicating greater (less) than or equal relation.
- */
- static final int FLAG_CVS_EQ_PVE = EQ << CVS_PVE_POS;
-
- /**
- * The child view's start should be strictly less than parent view's end.
- */
- static final int FLAG_CVS_LT_PVE = LT << CVS_PVE_POS;
-
-
- static final int CVE_PVS_POS = 8;
- /**
- * The child view's end should be strictly greater than parent view's start.
- */
- static final int FLAG_CVE_GT_PVS = GT << CVE_PVS_POS;
-
- /**
- * The child view's end can be equal to its parent view's start. This flag follows with GT
- * or LT indicating greater (less) than or equal relation.
- */
- static final int FLAG_CVE_EQ_PVS = EQ << CVE_PVS_POS;
-
- /**
- * The child view's end should be strictly less than parent view's start.
- */
- static final int FLAG_CVE_LT_PVS = LT << CVE_PVS_POS;
-
-
- static final int CVE_PVE_POS = 12;
- /**
- * The child view's end should be strictly greater than parent view's end.
- */
- static final int FLAG_CVE_GT_PVE = GT << CVE_PVE_POS;
-
- /**
- * The child view's end can be equal to its parent view's end. This flag follows with GT
- * or LT indicating greater (less) than or equal relation.
- */
- static final int FLAG_CVE_EQ_PVE = EQ << CVE_PVE_POS;
-
- /**
- * The child view's end should be strictly less than parent view's end.
- */
- static final int FLAG_CVE_LT_PVE = LT << CVE_PVE_POS;
-
- static final int MASK = GT | EQ | LT;
-
- final Callback mCallback;
- BoundFlags mBoundFlags;
- /**
- * The set of flags that can be passed for checking the view boundary conditions.
- * CVS in the flag name indicates the child view, and PV indicates the parent view.\
- * The following S, E indicate a view's start and end points, respectively.
- * GT and LT indicate a strictly greater and less than relationship.
- * Greater than or equal (or less than or equal) can be specified by setting both GT and EQ (or
- * LT and EQ) flags.
- * For instance, setting both {@link #FLAG_CVS_GT_PVS} and {@link #FLAG_CVS_EQ_PVS} indicate the
- * child view's start should be greater than or equal to its parent start.
- */
- @IntDef(flag = true, value = {
- FLAG_CVS_GT_PVS, FLAG_CVS_EQ_PVS, FLAG_CVS_LT_PVS,
- FLAG_CVS_GT_PVE, FLAG_CVS_EQ_PVE, FLAG_CVS_LT_PVE,
- FLAG_CVE_GT_PVS, FLAG_CVE_EQ_PVS, FLAG_CVE_LT_PVS,
- FLAG_CVE_EQ_PVE, FLAG_CVE_EQ_PVE, FLAG_CVE_LT_PVE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ViewBounds {}
-
- ViewBoundsCheck(Callback callback) {
- mCallback = callback;
- mBoundFlags = new BoundFlags();
- }
-
- static class BoundFlags {
- int mBoundFlags = 0;
- int mRvStart, mRvEnd, mChildStart, mChildEnd;
-
- void setBounds(int rvStart, int rvEnd, int childStart, int childEnd) {
- mRvStart = rvStart;
- mRvEnd = rvEnd;
- mChildStart = childStart;
- mChildEnd = childEnd;
- }
-
- void setFlags(@ViewBounds int flags, int mask) {
- mBoundFlags = (mBoundFlags & ~mask) | (flags & mask);
- }
-
- void addFlags(@ViewBounds int flags) {
- mBoundFlags |= flags;
- }
-
- void resetFlags() {
- mBoundFlags = 0;
- }
-
- int compare(int x, int y) {
- if (x > y) {
- return GT;
- }
- if (x == y) {
- return EQ;
- }
- return LT;
- }
-
- boolean boundsMatch() {
- if ((mBoundFlags & (MASK << CVS_PVS_POS)) != 0) {
- if ((mBoundFlags & (compare(mChildStart, mRvStart) << CVS_PVS_POS)) == 0) {
- return false;
- }
- }
-
- if ((mBoundFlags & (MASK << CVS_PVE_POS)) != 0) {
- if ((mBoundFlags & (compare(mChildStart, mRvEnd) << CVS_PVE_POS)) == 0) {
- return false;
- }
- }
-
- if ((mBoundFlags & (MASK << CVE_PVS_POS)) != 0) {
- if ((mBoundFlags & (compare(mChildEnd, mRvStart) << CVE_PVS_POS)) == 0) {
- return false;
- }
- }
-
- if ((mBoundFlags & (MASK << CVE_PVE_POS)) != 0) {
- if ((mBoundFlags & (compare(mChildEnd, mRvEnd) << CVE_PVE_POS)) == 0) {
- return false;
- }
- }
- return true;
- }
- };
-
- /**
- * Returns the first view starting from fromIndex to toIndex in views whose bounds lie within
- * its parent bounds based on the provided preferredBoundFlags. If no match is found based on
- * the preferred flags, and a nonzero acceptableBoundFlags is specified, the last view whose
- * bounds lie within its parent view based on the acceptableBoundFlags is returned. If no such
- * view is found based on either of these two flags, null is returned.
- * @param fromIndex The view position index to start the search from.
- * @param toIndex The view position index to end the search at.
- * @param preferredBoundFlags The flags indicating the preferred match. Once a match is found
- * based on this flag, that view is returned instantly.
- * @param acceptableBoundFlags The flags indicating the acceptable match if no preferred match
- * is found. If so, and if acceptableBoundFlags is non-zero, the
- * last matching acceptable view is returned. Otherwise, null is
- * returned.
- * @return The first view that satisfies acceptableBoundFlags or the last view satisfying
- * acceptableBoundFlags boundary conditions.
- */
- View findOneViewWithinBoundFlags(int fromIndex, int toIndex,
- @ViewBounds int preferredBoundFlags,
- @ViewBounds int acceptableBoundFlags) {
- final int start = mCallback.getParentStart();
- final int end = mCallback.getParentEnd();
- final int next = toIndex > fromIndex ? 1 : -1;
- View acceptableMatch = null;
- for (int i = fromIndex; i != toIndex; i += next) {
- final View child = mCallback.getChildAt(i);
- final int childStart = mCallback.getChildStart(child);
- final int childEnd = mCallback.getChildEnd(child);
- mBoundFlags.setBounds(start, end, childStart, childEnd);
- if (preferredBoundFlags != 0) {
- mBoundFlags.resetFlags();
- mBoundFlags.addFlags(preferredBoundFlags);
- if (mBoundFlags.boundsMatch()) {
- // found a perfect match
- return child;
- }
- }
- if (acceptableBoundFlags != 0) {
- mBoundFlags.resetFlags();
- mBoundFlags.addFlags(acceptableBoundFlags);
- if (mBoundFlags.boundsMatch()) {
- acceptableMatch = child;
- }
- }
- }
- return acceptableMatch;
- }
-
- /**
- * Returns whether the specified view lies within the boundary condition of its parent view.
- * @param child The child view to be checked.
- * @param boundsFlags The flag against which the child view and parent view are matched.
- * @return True if the view meets the boundsFlag, false otherwise.
- */
- boolean isViewWithinBoundFlags(View child, @ViewBounds int boundsFlags) {
- mBoundFlags.setBounds(mCallback.getParentStart(), mCallback.getParentEnd(),
- mCallback.getChildStart(child), mCallback.getChildEnd(child));
- if (boundsFlags != 0) {
- mBoundFlags.resetFlags();
- mBoundFlags.addFlags(boundsFlags);
- return mBoundFlags.boundsMatch();
- }
- return false;
- }
-
- /**
- * Callback provided by the user of this class in order to retrieve information about child and
- * parent boundaries.
- */
- interface Callback {
- int getChildCount();
- View getParent();
- View getChildAt(int index);
- int getParentStart();
- int getParentEnd();
- int getChildStart(View view);
- int getChildEnd(View view);
- }
-}
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
index 5f7bf48..7185cbc 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseRecyclerViewInstrumentationTest.java
@@ -150,11 +150,7 @@
});
}
- public View focusSearch(final View focused, final int direction) throws Throwable {
- return focusSearch(focused, direction, false);
- }
-
- public View focusSearch(final View focused, final int direction, boolean waitForScroll)
+ public View focusSearch(final View focused, final int direction)
throws Throwable {
final View[] result = new View[1];
mActivityRule.runOnUiThread(new Runnable() {
@@ -167,9 +163,6 @@
result[0] = view;
}
});
- if (waitForScroll && (result[0] != null)) {
- waitForIdleScroll(mRecyclerView);
- }
return result[0];
}
@@ -487,7 +480,7 @@
});
getInstrumentation().waitForIdleSync();
assertThat("should be able to scroll in 10 seconds", !assertArrival ||
- viewAdded.await(10, TimeUnit.SECONDS),
+ viewAdded.await(10, TimeUnit.SECONDS),
CoreMatchers.is(true));
waitForIdleScroll(mRecyclerView);
if (mDebug) {
@@ -555,7 +548,6 @@
}
}
}
-
public class TestLayoutManager extends RecyclerView.LayoutManager {
int mScrollVerticallyAmount;
int mScrollHorizontallyAmount;
@@ -1191,60 +1183,4 @@
validateRemaining(recyclerView);
}
}
-
- /**
- * Returns whether a child of RecyclerView is partially in bound. A child is
- * partially in-bounds if it's either fully or partially visible on the screen.
- * @param parent The RecyclerView holding the child.
- * @param child The child view to be checked whether is partially (or fully) within RV's bounds.
- * @return True if the child view is partially (or fully) visible; false otherwise.
- */
- public static boolean isViewPartiallyInBound(RecyclerView parent, View child) {
- if (child == null) {
- return false;
- }
- final int parentLeft = parent.getPaddingLeft();
- final int parentTop = parent.getPaddingTop();
- final int parentRight = parent.getWidth() - parent.getPaddingRight();
- final int parentBottom = parent.getHeight() - parent.getPaddingBottom();
-
- final int childLeft = child.getLeft() - child.getScrollX();
- final int childTop = child.getTop() - child.getScrollY();
- final int childRight = child.getRight() - child.getScrollX();
- final int childBottom = child.getBottom() - child.getScrollY();
-
- if (childLeft >= parentRight || childRight <= parentLeft
- || childTop >= parentBottom || childBottom <= parentTop) {
- return false;
- }
- return true;
- }
-
- /**
- * Returns whether a child of RecyclerView is fully in-bounds, that is it's fully visible
- * on the screen.
- * @param parent The RecyclerView holding the child.
- * @param child The child view to be checked whether is fully within RV's bounds.
- * @return True if the child view is fully visible; false otherwise.
- */
- public boolean isViewFullyInBound(RecyclerView parent, View child) {
- if (child == null) {
- return false;
- }
- final int parentLeft = parent.getPaddingLeft();
- final int parentTop = parent.getPaddingTop();
- final int parentRight = parent.getWidth() - parent.getPaddingRight();
- final int parentBottom = parent.getHeight() - parent.getPaddingBottom();
-
- final int childLeft = child.getLeft() - child.getScrollX();
- final int childTop = child.getTop() - child.getScrollY();
- final int childRight = child.getRight() - child.getScrollX();
- final int childBottom = child.getBottom() - child.getScrollY();
-
- if (childLeft >= parentLeft && childRight <= parentRight
- && childTop >= parentTop && childBottom <= parentBottom) {
- return true;
- }
- return false;
- }
}
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/BaseStaggeredGridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/BaseStaggeredGridLayoutManagerTest.java
index 776b10d..fff64b3 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/BaseStaggeredGridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/BaseStaggeredGridLayoutManagerTest.java
@@ -14,13 +14,9 @@
import static java.util.concurrent.TimeUnit.SECONDS;
-import android.graphics.Color;
import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.StateListDrawable;
import android.support.annotation.Nullable;
import android.util.Log;
-import android.util.StateSet;
import android.view.View;
import android.view.ViewGroup;
@@ -911,13 +907,7 @@
lp.rightMargin = 7;
lp.bottomMargin = 9;
}
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation using this for kitkat tests
- holder.itemView.setBackgroundDrawable(stl);
+
if (mOnBindCallback != null) {
mOnBindCallback.onBoundItem(holder, position);
}
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
index 5ebebfe..5c2692a 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/GridLayoutManagerTest.java
@@ -19,7 +19,6 @@
import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL;
import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
-import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -168,367 +167,6 @@
}
}
-
- @Test
- public void topUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of rows that can be fully in-bounds of RV.
- final int visibleRowCount = 5;
- final int spanCount = 3;
- final int consecutiveFocusableRowsCount = 4;
- final int consecutiveUnFocusableRowsCount = 8;
- final int itemCount = (consecutiveFocusableRowsCount + consecutiveUnFocusableRowsCount)
- * spanCount;
-
- final RecyclerView recyclerView = setupBasic(new Config(spanCount, itemCount)
- .reverseLayout(true),
- new GridTestAdapter(itemCount, 1) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation using this for kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- if (position < spanCount * consecutiveFocusableRowsCount) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / visibleRowCount);
- }
- });
- waitForFirstLayout(recyclerView);
-
- // adapter position of the currently focused item.
- int focusIndex = 1;
- RecyclerView.ViewHolder toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
- View viewToFocus = toFocus.itemView;
- assertTrue(requestFocus(viewToFocus, true));
- assertSame(viewToFocus, recyclerView.getFocusedChild());
-
- // adapter position of the item (whether focusable or not) that just becomes fully
- // visible after focusSearch.
- int visibleIndex = focusIndex;
- // The VH of the above adapter position
- RecyclerView.ViewHolder toVisible = null;
-
- int maxFocusIndex = (consecutiveFocusableRowsCount - 1) * spanCount + focusIndex;
- int maxVisibleIndex = (consecutiveFocusableRowsCount + visibleRowCount - 2)
- * spanCount + visibleIndex;
-
- // Navigate up through the focusable and unfocusable rows. The focusable rows should
- // become focused one by one until hitting the last focusable row, at which point,
- // unfocusable rows should become visible on the screen until the currently focused row
- // stays on the screen.
- int pos = focusIndex + spanCount;
- while (pos < itemCount) {
- focusSearch(recyclerView.getFocusedChild(), View.FOCUS_UP, true);
- waitForIdleScroll(recyclerView);
- focusIndex = Math.min(maxFocusIndex, (focusIndex + spanCount));
- toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
- visibleIndex = Math.min(maxVisibleIndex, (visibleIndex + spanCount));
- toVisible = recyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(recyclerView, toFocus.itemView));
- assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
- isViewFullyInBound(recyclerView, toVisible.itemView));
- pos += spanCount;
- }
- }
-
- @Test
- public void bottomUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of rows that can be fully in-bounds of RV.
- final int visibleRowCount = 5;
- final int spanCount = 3;
- final int consecutiveFocusableRowsCount = 4;
- final int consecutiveUnFocusableRowsCount = 8;
- final int itemCount = (consecutiveFocusableRowsCount + consecutiveUnFocusableRowsCount)
- * spanCount;
-
- final RecyclerView recyclerView = setupBasic(new Config(spanCount, itemCount)
- .reverseLayout(false),
- new GridTestAdapter(itemCount, 1) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation using this for kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- if (position < spanCount * consecutiveFocusableRowsCount) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / visibleRowCount);
- }
- });
- waitForFirstLayout(recyclerView);
-
- // adapter position of the currently focused item.
- int focusIndex = 1;
- RecyclerView.ViewHolder toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
- View viewToFocus = toFocus.itemView;
- assertTrue(requestFocus(viewToFocus, true));
- assertSame(viewToFocus, recyclerView.getFocusedChild());
-
- // adapter position of the item (whether focusable or not) that just becomes fully
- // visible after focusSearch.
- int visibleIndex = focusIndex;
- // The VH of the above adapter position
- RecyclerView.ViewHolder toVisible = null;
-
- int maxFocusIndex = (consecutiveFocusableRowsCount - 1) * spanCount + focusIndex;
- int maxVisibleIndex = (consecutiveFocusableRowsCount + visibleRowCount - 2)
- * spanCount + visibleIndex;
-
- // Navigate down through the focusable and unfocusable rows. The focusable rows should
- // become focused one by one until hitting the last focusable row, at which point,
- // unfocusable rows should become visible on the screen until the currently focused row
- // stays on the screen.
- int pos = focusIndex + spanCount;
- while (pos < itemCount) {
- focusSearch(recyclerView.getFocusedChild(), View.FOCUS_DOWN, true);
- waitForIdleScroll(recyclerView);
- focusIndex = Math.min(maxFocusIndex, (focusIndex + spanCount));
- toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
- visibleIndex = Math.min(maxVisibleIndex, (visibleIndex + spanCount));
- toVisible = recyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(recyclerView, toFocus.itemView));
- assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
- isViewFullyInBound(recyclerView, toVisible.itemView));
- pos += spanCount;
- }
- }
-
- @Test
- public void leftUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of columns that can be fully in-bounds of RV.
- final int visibleColCount = 5;
- final int spanCount = 3;
- final int consecutiveFocusableColsCount = 4;
- final int consecutiveUnFocusableColsCount = 8;
- final int itemCount = (consecutiveFocusableColsCount + consecutiveUnFocusableColsCount)
- * spanCount;
-
- final RecyclerView recyclerView = setupBasic(new Config(spanCount, itemCount)
- .orientation(HORIZONTAL).reverseLayout(true),
- new GridTestAdapter(itemCount, 1) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation using this for kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- if (position < spanCount * consecutiveFocusableColsCount) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- holder.itemView.setMinimumWidth(mAttachedRv.getWidth() / visibleColCount);
- }
- });
- waitForFirstLayout(recyclerView);
-
- // adapter position of the currently focused item.
- int focusIndex = 1;
- RecyclerView.ViewHolder toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
- View viewToFocus = toFocus.itemView;
- assertTrue(requestFocus(viewToFocus, true));
- assertSame(viewToFocus, recyclerView.getFocusedChild());
-
- // adapter position of the item (whether focusable or not) that just becomes fully
- // visible after focusSearch.
- int visibleIndex = focusIndex;
- // The VH of the above adapter position
- RecyclerView.ViewHolder toVisible = null;
-
- int maxFocusIndex = (consecutiveFocusableColsCount - 1) * spanCount + focusIndex;
- int maxVisibleIndex = (consecutiveFocusableColsCount + visibleColCount - 2)
- * spanCount + visibleIndex;
-
- // Navigate left through the focusable and unfocusable columns. The focusable columns should
- // become focused one by one until hitting the last focusable column, at which point,
- // unfocusable columns should become visible on the screen until the currently focused
- // column stays on the screen.
- int pos = focusIndex + spanCount;
- while (pos < itemCount) {
- focusSearch(recyclerView.getFocusedChild(), View.FOCUS_LEFT, true);
- waitForIdleScroll(recyclerView);
- focusIndex = Math.min(maxFocusIndex, (focusIndex + spanCount));
- toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
- visibleIndex = Math.min(maxVisibleIndex, (visibleIndex + spanCount));
- toVisible = recyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(recyclerView, toFocus.itemView));
- assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
- isViewFullyInBound(recyclerView, toVisible.itemView));
- pos += spanCount;
- }
- }
-
- @Test
- public void rightUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of columns that can be fully in-bounds of RV.
- final int visibleColCount = 5;
- final int spanCount = 3;
- final int consecutiveFocusableColsCount = 4;
- final int consecutiveUnFocusableColsCount = 8;
- final int itemCount = (consecutiveFocusableColsCount + consecutiveUnFocusableColsCount)
- * spanCount;
-
- final RecyclerView recyclerView = setupBasic(new Config(spanCount, itemCount)
- .orientation(HORIZONTAL).reverseLayout(false),
- new GridTestAdapter(itemCount, 1) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation using this for kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- if (position < spanCount * consecutiveFocusableColsCount) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- holder.itemView.setMinimumWidth(mAttachedRv.getWidth() / visibleColCount);
- }
- });
- waitForFirstLayout(recyclerView);
-
- // adapter position of the currently focused item.
- int focusIndex = 1;
- RecyclerView.ViewHolder toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
- View viewToFocus = toFocus.itemView;
- assertTrue(requestFocus(viewToFocus, true));
- assertSame(viewToFocus, recyclerView.getFocusedChild());
-
- // adapter position of the item (whether focusable or not) that just becomes fully
- // visible after focusSearch.
- int visibleIndex = focusIndex;
- // The VH of the above adapter position
- RecyclerView.ViewHolder toVisible = null;
-
- int maxFocusIndex = (consecutiveFocusableColsCount - 1) * spanCount + focusIndex;
- int maxVisibleIndex = (consecutiveFocusableColsCount + visibleColCount - 2)
- * spanCount + visibleIndex;
-
- // Navigate right through the focusable and unfocusable columns. The focusable columns
- // should become focused one by one until hitting the last focusable column, at which point,
- // unfocusable columns should become visible on the screen until the currently focused
- // column stays on the screen.
- int pos = focusIndex + spanCount;
- while (pos < itemCount) {
- focusSearch(recyclerView.getFocusedChild(), View.FOCUS_RIGHT, true);
- waitForIdleScroll(recyclerView);
- focusIndex = Math.min(maxFocusIndex, (focusIndex + spanCount));
- toFocus = recyclerView.findViewHolderForAdapterPosition(focusIndex);
- visibleIndex = Math.min(maxVisibleIndex, (visibleIndex + spanCount));
- toVisible = recyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(recyclerView, toFocus.itemView));
- assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
- isViewFullyInBound(recyclerView, toVisible.itemView));
- pos += spanCount;
- }
- }
-
@UiThreadTest
@Test
public void scrollWithoutLayout() throws Throwable {
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
index 067689c..5f61ea7 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/LinearLayoutManagerTest.java
@@ -19,22 +19,16 @@
import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL;
import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
-import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.StateListDrawable;
-import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
import android.support.v4.view.AccessibilityDelegateCompat;
import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
import android.util.Log;
-import android.util.StateSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
@@ -45,7 +39,6 @@
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
-
/**
* Includes tests for {@link LinearLayoutManager}.
* <p>
@@ -53,352 +46,10 @@
* and stability of LinearLayoutManager in response to different events (state change, scrolling
* etc) where it is very hard to do manual testing.
*/
-@LargeTest
+@MediumTest
public class LinearLayoutManagerTest extends BaseLinearLayoutManagerTest {
@Test
- public void topUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of child views that can be visible at any time.
- final int visibleChildCount = 5;
- final int consecutiveFocusablesCount = 2;
- final int consecutiveUnFocusablesCount = 18;
- final TestAdapter adapter = new TestAdapter(
- consecutiveFocusablesCount + consecutiveUnFocusablesCount) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation used to support kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- if (position < consecutiveFocusablesCount) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- // This height ensures that some portion of #visibleChildCount'th child is
- // off-bounds, creating more interesting test scenario.
- holder.itemView.setMinimumHeight((mAttachedRv.getHeight()
- + mAttachedRv.getHeight() / (2 * visibleChildCount)) / visibleChildCount);
- }
- };
- setupByConfig(new Config(VERTICAL, false, false).adapter(adapter).reverseLayout(true),
- false);
- waitForFirstLayout();
-
- // adapter position of the currently focused item.
- int focusIndex = 0;
- View newFocused = mRecyclerView.getChildAt(focusIndex);
- requestFocus(newFocused, true);
- RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
- focusIndex);
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
-
- // adapter position of the item (whether focusable or not) that just becomes fully
- // visible after focusSearch.
- int visibleIndex = 0;
- // The VH of the above adapter position
- RecyclerView.ViewHolder toVisible = null;
-
- // Navigate up through the focusable and unfocusable chunks. The focusable items should
- // become focused one by one until hitting the last focusable item, at which point,
- // unfocusable items should become visible on the screen until the currently focused item
- // stays on the screen.
- for (int i = 0; i < adapter.getItemCount(); i++) {
- focusSearch(mRecyclerView.getFocusedChild(), View.FOCUS_UP, true);
- // adapter position of the currently focused item.
- focusIndex = Math.min(consecutiveFocusablesCount - 1, (focusIndex + 1));
- toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex);
- visibleIndex = Math.min(consecutiveFocusablesCount + visibleChildCount - 2,
- (visibleIndex + 1));
- toVisible = mRecyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(mRecyclerView, toFocus.itemView));
- assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
- isViewFullyInBound(mRecyclerView, toVisible.itemView));
- }
- }
-
- @Test
- public void bottomUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of child views that can be visible at any time.
- final int visibleChildCount = 5;
- final int consecutiveFocusablesCount = 2;
- final int consecutiveUnFocusablesCount = 18;
- final TestAdapter adapter = new TestAdapter(
- consecutiveFocusablesCount + consecutiveUnFocusablesCount) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation used to support kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- if (position < consecutiveFocusablesCount) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- // This height ensures that some portion of #visibleChildCount'th child is
- // off-bounds, creating more interesting test scenario.
- holder.itemView.setMinimumHeight((mAttachedRv.getHeight()
- + mAttachedRv.getHeight() / (2 * visibleChildCount)) / visibleChildCount);
- }
- };
- setupByConfig(new Config(VERTICAL, false, false).adapter(adapter), false);
- waitForFirstLayout();
-
- // adapter position of the currently focused item.
- int focusIndex = 0;
- View newFocused = mRecyclerView.getChildAt(focusIndex);
- requestFocus(newFocused, true);
- RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
- focusIndex);
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
-
- // adapter position of the item (whether focusable or not) that just becomes fully
- // visible after focusSearch.
- int visibleIndex = 0;
- // The VH of the above adapter position
- RecyclerView.ViewHolder toVisible = null;
-
- // Navigate down through the focusable and unfocusable chunks. The focusable items should
- // become focused one by one until hitting the last focusable item, at which point,
- // unfocusable items should become visible on the screen until the currently focused item
- // stays on the screen.
- for (int i = 0; i < adapter.getItemCount(); i++) {
- focusSearch(mRecyclerView.getFocusedChild(), View.FOCUS_DOWN, true);
- // adapter position of the currently focused item.
- focusIndex = Math.min(consecutiveFocusablesCount - 1, (focusIndex + 1));
- toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex);
- visibleIndex = Math.min(consecutiveFocusablesCount + visibleChildCount - 2,
- (visibleIndex + 1));
- toVisible = mRecyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(mRecyclerView, toFocus.itemView));
- assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
- isViewFullyInBound(mRecyclerView, toVisible.itemView));
- }
- }
-
- @Test
- public void leftUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of child views that can be visible at any time.
- final int visibleChildCount = 5;
- final int consecutiveFocusablesCount = 2;
- final int consecutiveUnFocusablesCount = 18;
- final TestAdapter adapter = new TestAdapter(
- consecutiveFocusablesCount + consecutiveUnFocusablesCount) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation used to support kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- if (position < consecutiveFocusablesCount) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- // This width ensures that some portion of #visibleChildCount'th child is
- // off-bounds, creating more interesting test scenario.
- holder.itemView.setMinimumWidth((mAttachedRv.getWidth()
- + mAttachedRv.getWidth() / (2 * visibleChildCount)) / visibleChildCount);
- }
- };
- setupByConfig(new Config(HORIZONTAL, false, false).adapter(adapter).reverseLayout(true),
- false);
- waitForFirstLayout();
-
- // adapter position of the currently focused item.
- int focusIndex = 0;
- View newFocused = mRecyclerView.getChildAt(focusIndex);
- requestFocus(newFocused, true);
- RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
- focusIndex);
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
-
- // adapter position of the item (whether focusable or not) that just becomes fully
- // visible after focusSearch.
- int visibleIndex = 0;
- // The VH of the above adapter position
- RecyclerView.ViewHolder toVisible = null;
-
- // Navigate left through the focusable and unfocusable chunks. The focusable items should
- // become focused one by one until hitting the last focusable item, at which point,
- // unfocusable items should become visible on the screen until the currently focused item
- // stays on the screen.
- for (int i = 0; i < adapter.getItemCount(); i++) {
- focusSearch(mRecyclerView.getFocusedChild(), View.FOCUS_LEFT, true);
- // adapter position of the currently focused item.
- focusIndex = Math.min(consecutiveFocusablesCount - 1, (focusIndex + 1));
- toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex);
- visibleIndex = Math.min(consecutiveFocusablesCount + visibleChildCount - 2,
- (visibleIndex + 1));
- toVisible = mRecyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(mRecyclerView, toFocus.itemView));
- assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
- isViewFullyInBound(mRecyclerView, toVisible.itemView));
- }
- }
-
- @Test
- public void rightUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of child views that can be visible at any time.
- final int visibleChildCount = 5;
- final int consecutiveFocusablesCount = 2;
- final int consecutiveUnFocusablesCount = 18;
- final TestAdapter adapter = new TestAdapter(
- consecutiveFocusablesCount + consecutiveUnFocusablesCount) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation used to support kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- if (position < consecutiveFocusablesCount) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- // This width ensures that some portion of #visibleChildCount'th child is
- // off-bounds, creating more interesting test scenario.
- holder.itemView.setMinimumWidth((mAttachedRv.getWidth()
- + mAttachedRv.getWidth() / (2 * visibleChildCount)) / visibleChildCount);
- }
- };
- setupByConfig(new Config(HORIZONTAL, false, false).adapter(adapter), false);
- waitForFirstLayout();
-
- // adapter position of the currently focused item.
- int focusIndex = 0;
- View newFocused = mRecyclerView.getChildAt(focusIndex);
- requestFocus(newFocused, true);
- RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
- focusIndex);
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
-
- // adapter position of the item (whether focusable or not) that just becomes fully
- // visible after focusSearch.
- int visibleIndex = 0;
- // The VH of the above adapter position
- RecyclerView.ViewHolder toVisible = null;
-
- // Navigate right through the focusable and unfocusable chunks. The focusable items should
- // become focused one by one until hitting the last focusable item, at which point,
- // unfocusable items should become visible on the screen until the currently focused item
- // stays on the screen.
- for (int i = 0; i < adapter.getItemCount(); i++) {
- focusSearch(mRecyclerView.getFocusedChild(), View.FOCUS_RIGHT, true);
- // adapter position of the currently focused item.
- focusIndex = Math.min(consecutiveFocusablesCount - 1, (focusIndex + 1));
- toFocus = mRecyclerView.findViewHolderForAdapterPosition(focusIndex);
- visibleIndex = Math.min(consecutiveFocusablesCount + visibleChildCount - 2,
- (visibleIndex + 1));
- toVisible = mRecyclerView.findViewHolderForAdapterPosition(visibleIndex);
-
- assertThat("Child at position " + focusIndex + " should be focused",
- toFocus.itemView.hasFocus(), is(true));
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(mRecyclerView, toFocus.itemView));
- assertTrue("Child view at adapter pos " + visibleIndex + " should be fully visible.",
- isViewFullyInBound(mRecyclerView, toVisible.itemView));
- }
- }
-
- @Test
public void removeAnchorItem() throws Throwable {
removeAnchorItemTest(
new Config().orientation(VERTICAL).stackFromBottom(false).reverseLayout(
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
index 786df47..79479ef 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewLayoutTest.java
@@ -326,7 +326,7 @@
holder.itemView.setFocusableInTouchMode(true);
holder.itemView.setLayoutParams(
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
+ ViewGroup.LayoutParams.WRAP_CONTENT));
}
});
TestLayoutManager tlm = new TestLayoutManager() {
@@ -355,7 +355,7 @@
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler,
- RecyclerView.State state) {
+ RecyclerView.State state) {
super.scrollHorizontallyBy(dx, recycler, state);
// offset by -dx because the views translate opposite of the scrolling direction
mRecyclerView.offsetChildrenHorizontal(-dx);
@@ -364,7 +364,7 @@
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
- RecyclerView.State state) {
+ RecyclerView.State state) {
super.scrollVerticallyBy(dy, recycler, state);
// offset by -dy because the views translate opposite of the scrolling direction
mRecyclerView.offsetChildrenVertical(-dy);
@@ -604,7 +604,7 @@
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
- RecyclerView.State state) {
+ RecyclerView.State state) {
// Access views in the state (that might have been deleted).
for (int i = 10; i < state.getItemCount(); i++) {
recycler.getViewForPosition(i);
@@ -728,8 +728,8 @@
@Nullable
@Override
public View onFocusSearchFailed(View focused, int direction,
- RecyclerView.Recycler recycler,
- RecyclerView.State state) {
+ RecyclerView.Recycler recycler,
+ RecyclerView.State state) {
try {
recycler.getViewForPosition(state.getItemCount() - 1);
} catch (Throwable t) {
@@ -4246,7 +4246,7 @@
@Override
protected void onTargetFound(View targetView, RecyclerView.State state,
- Action action) {
+ Action action) {
super.onTargetFound(targetView, state, action);
mTargetFound.set(true);
}
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
index 89db393..3528b7c 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
@@ -80,7 +80,7 @@
smoothScrollToPosition(100);
mLayoutManager.expectLayouts(1);
mAdapter.deleteAndNotify(0, 2);
- mLayoutManager.waitForLayout(2000);
+ mLayoutManager.waitForLayout(2);
smoothScrollToPosition(0);
assertFalse("all starts should not be the same", mLayoutManager.areAllStartsEqual());
}
@@ -277,16 +277,6 @@
holder.mBoundItem = item;
((EditText) ((FrameLayout) holder.itemView).getChildAt(0)).setText(
item.mText + " (" + item.mId + ")");
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation using this for kitkat tests
- holder.itemView.setBackgroundDrawable(stl);
- if (mOnBindCallback != null) {
- mOnBindCallback.onBoundItem(holder, position);
- }
}
});
mLayoutManager.expectLayouts(1);
@@ -404,449 +394,6 @@
waitForIdleScroll(mRecyclerView);
}
- @Test
- public void topUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of rows that can be fully in-bounds of RV.
- final int visibleRowCount = 5;
- final int spanCount = 3;
- final int lastFocusableIndex = 6;
-
- setupByConfig(new Config(VERTICAL, true, spanCount, GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS),
- new GridTestAdapter(18, 1) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- testViewHolder.itemView.setFocusable(true);
- testViewHolder.itemView.setFocusableInTouchMode(true);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation used to support kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView
- .getLayoutParams();
- if (position <= lastFocusableIndex) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / visibleRowCount);
- lp.topMargin = 0;
- lp.leftMargin = 0;
- lp.rightMargin = 0;
- lp.bottomMargin = 0;
- if (position == 11) {
- lp.bottomMargin = 9;
- }
- }
- });
-
- /**
- *
- * 15 16 17
- * 12 13 14
- * 11 11 11
- * 9 10
- * 8 8 8
- * 7
- * 6 6 6
- * 3 4 5
- * 0 1 2
- */
- mAdapter.mFullSpanItems.add(6);
- mAdapter.mFullSpanItems.add(8);
- mAdapter.mFullSpanItems.add(11);
- waitFirstLayout();
-
-
- // adapter position of the currently focused item.
- int focusIndex = 1;
- RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
- focusIndex);
- View viewToFocus = toFocus.itemView;
- assertTrue(requestFocus(viewToFocus, true));
- assertSame(viewToFocus, mRecyclerView.getFocusedChild());
-
- // The VH of the unfocusable item that just became fully visible after focusSearch.
- RecyclerView.ViewHolder toVisible = null;
-
- View focusedView = viewToFocus;
- int actualFocusIndex = -1;
- // First, scroll until the last focusable row.
- for (int i : new int[]{4, 6}) {
- focusSearchAndWaitForScroll(focusedView, View.FOCUS_UP);
- focusedView = mRecyclerView.getFocusedChild();
- actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
- assertEquals("Focused view should be at adapter position " + i + " whereas it's at "
- + actualFocusIndex, i, actualFocusIndex);
- }
-
- // Further scroll up in order to make the unfocusable rows visible. This process should
- // continue until the currently focused item is still visible. The focused item should not
- // change in this loop.
- for (int i : new int[]{9, 11, 11, 11}) {
- focusSearchAndWaitForScroll(focusedView, View.FOCUS_UP);
- focusedView = mRecyclerView.getFocusedChild();
- actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
- toVisible = mRecyclerView.findViewHolderForAdapterPosition(i);
-
- assertEquals("Focused view should not be changed, whereas it's now at "
- + actualFocusIndex, 6, actualFocusIndex);
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(mRecyclerView, focusedView));
- assertTrue("Child view at adapter pos " + i + " should be fully visible.",
- isViewFullyInBound(mRecyclerView, toVisible.itemView));
- }
- }
-
- @Test
- public void bottomUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of rows that can be fully in-bounds of RV.
- final int visibleRowCount = 5;
- final int spanCount = 3;
- final int lastFocusableIndex = 6;
-
- setupByConfig(new Config(VERTICAL, false, spanCount, GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS),
- new GridTestAdapter(18, 1) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- testViewHolder.itemView.setFocusable(true);
- testViewHolder.itemView.setFocusableInTouchMode(true);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation used to support kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView
- .getLayoutParams();
- if (position <= lastFocusableIndex) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / visibleRowCount);
- lp.topMargin = 0;
- lp.leftMargin = 0;
- lp.rightMargin = 0;
- lp.bottomMargin = 0;
- if (position == 11) {
- lp.topMargin = 9;
- }
- }
- });
-
- /**
- * 0 1 2
- * 3 4 5
- * 6 6 6
- * 7
- * 8 8 8
- * 9 10
- * 11 11 11
- * 12 13 14
- * 15 16 17
- */
- mAdapter.mFullSpanItems.add(6);
- mAdapter.mFullSpanItems.add(8);
- mAdapter.mFullSpanItems.add(11);
- waitFirstLayout();
-
-
- // adapter position of the currently focused item.
- int focusIndex = 1;
- RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
- focusIndex);
- View viewToFocus = toFocus.itemView;
- assertTrue(requestFocus(viewToFocus, true));
- assertSame(viewToFocus, mRecyclerView.getFocusedChild());
-
- // The VH of the unfocusable item that just became fully visible after focusSearch.
- RecyclerView.ViewHolder toVisible = null;
-
- View focusedView = viewToFocus;
- int actualFocusIndex = -1;
- // First, scroll until the last focusable row.
- for (int i : new int[]{4, 6}) {
- focusSearchAndWaitForScroll(focusedView, View.FOCUS_DOWN);
- focusedView = mRecyclerView.getFocusedChild();
- actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
- assertEquals("Focused view should be at adapter position " + i + " whereas it's at "
- + actualFocusIndex, i, actualFocusIndex);
- }
-
- // Further scroll down in order to make the unfocusable rows visible. This process should
- // continue until the currently focused item is still visible. The focused item should not
- // change in this loop.
- for (int i : new int[]{9, 11, 11, 11}) {
- focusSearchAndWaitForScroll(focusedView, View.FOCUS_DOWN);
- focusedView = mRecyclerView.getFocusedChild();
- actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
- toVisible = mRecyclerView.findViewHolderForAdapterPosition(i);
-
- assertEquals("Focused view should not be changed, whereas it's now at "
- + actualFocusIndex, 6, actualFocusIndex);
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(mRecyclerView, focusedView));
- assertTrue("Child view at adapter pos " + i + " should be fully visible.",
- isViewFullyInBound(mRecyclerView, toVisible.itemView));
- }
- }
-
- @Test
- public void leftUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of columns that can be fully in-bounds of RV.
- final int visibleColCount = 5;
- final int spanCount = 3;
- final int lastFocusableIndex = 6;
-
- // Reverse layout so that views are placed from right to left.
- setupByConfig(new Config(HORIZONTAL, true, spanCount,
- GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS),
- new GridTestAdapter(18, 1) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- testViewHolder.itemView.setFocusable(true);
- testViewHolder.itemView.setFocusableInTouchMode(true);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation used to support kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView
- .getLayoutParams();
- if (position <= lastFocusableIndex) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- holder.itemView.setMinimumWidth(mAttachedRv.getWidth() / visibleColCount);
- lp.topMargin = 0;
- lp.leftMargin = 0;
- lp.rightMargin = 0;
- lp.bottomMargin = 0;
- if (position == 11) {
- lp.rightMargin = 9;
- }
- }
- });
-
- /**
- * 15 12 11 9 8 7 6 3 0
- * 16 13 11 10 8 6 4 1
- * 17 14 11 8 6 5 2
- */
- mAdapter.mFullSpanItems.add(6);
- mAdapter.mFullSpanItems.add(8);
- mAdapter.mFullSpanItems.add(11);
- waitFirstLayout();
-
-
- // adapter position of the currently focused item.
- int focusIndex = 1;
- RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
- focusIndex);
- View viewToFocus = toFocus.itemView;
- assertTrue(requestFocus(viewToFocus, true));
- assertSame(viewToFocus, mRecyclerView.getFocusedChild());
-
- // The VH of the unfocusable item that just became fully visible after focusSearch.
- RecyclerView.ViewHolder toVisible = null;
-
- View focusedView = viewToFocus;
- int actualFocusIndex = -1;
- // First, scroll until the last focusable column.
- for (int i : new int[]{4, 6}) {
- focusSearchAndWaitForScroll(focusedView, View.FOCUS_LEFT);
- focusedView = mRecyclerView.getFocusedChild();
- actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
- assertEquals("Focused view should be at adapter position " + i + " whereas it's at "
- + actualFocusIndex, i, actualFocusIndex);
- }
-
- // Further scroll left in order to make the unfocusable columns visible. This process should
- // continue until the currently focused item is still visible. The focused item should not
- // change in this loop.
- for (int i : new int[]{9, 11, 11, 11}) {
- focusSearchAndWaitForScroll(focusedView, View.FOCUS_LEFT);
- focusedView = mRecyclerView.getFocusedChild();
- actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
- toVisible = mRecyclerView.findViewHolderForAdapterPosition(i);
-
- assertEquals("Focused view should not be changed, whereas it's now at "
- + actualFocusIndex, 6, actualFocusIndex);
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(mRecyclerView, focusedView));
- assertTrue("Child view at adapter pos " + i + " should be fully visible.",
- isViewFullyInBound(mRecyclerView, toVisible.itemView));
- }
- }
-
- @Test
- public void rightUnfocusableViewsVisibility() throws Throwable {
- // The maximum number of columns that can be fully in-bounds of RV.
- final int visibleColCount = 5;
- final int spanCount = 3;
- final int lastFocusableIndex = 6;
-
- setupByConfig(new Config(HORIZONTAL, false, spanCount,
- GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS),
- new GridTestAdapter(18, 1) {
- RecyclerView mAttachedRv;
-
- @Override
- public TestViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType);
- testViewHolder.itemView.setFocusable(true);
- testViewHolder.itemView.setFocusableInTouchMode(true);
- // Good to have colors for debugging
- StateListDrawable stl = new StateListDrawable();
- stl.addState(new int[]{android.R.attr.state_focused},
- new ColorDrawable(Color.RED));
- stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE));
- //noinspection deprecation used to support kitkat tests
- testViewHolder.itemView.setBackgroundDrawable(stl);
- return testViewHolder;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- mAttachedRv = recyclerView;
- }
-
- @Override
- public void onBindViewHolder(TestViewHolder holder,
- int position) {
- super.onBindViewHolder(holder, position);
- RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView
- .getLayoutParams();
- if (position <= lastFocusableIndex) {
- holder.itemView.setFocusable(true);
- holder.itemView.setFocusableInTouchMode(true);
- } else {
- holder.itemView.setFocusable(false);
- holder.itemView.setFocusableInTouchMode(false);
- }
- holder.itemView.setMinimumWidth(mAttachedRv.getWidth() / visibleColCount);
- lp.topMargin = 0;
- lp.leftMargin = 0;
- lp.rightMargin = 0;
- lp.bottomMargin = 0;
- if (position == 11) {
- lp.leftMargin = 9;
- }
- }
- });
-
- /**
- * 0 3 6 7 8 9 11 12 15
- * 1 4 6 8 10 11 13 16
- * 2 5 6 8 11 14 17
- */
- mAdapter.mFullSpanItems.add(6);
- mAdapter.mFullSpanItems.add(8);
- mAdapter.mFullSpanItems.add(11);
- waitFirstLayout();
-
-
- // adapter position of the currently focused item.
- int focusIndex = 1;
- RecyclerView.ViewHolder toFocus = mRecyclerView.findViewHolderForAdapterPosition(
- focusIndex);
- View viewToFocus = toFocus.itemView;
- assertTrue(requestFocus(viewToFocus, true));
- assertSame(viewToFocus, mRecyclerView.getFocusedChild());
-
- // The VH of the unfocusable item that just became fully visible after focusSearch.
- RecyclerView.ViewHolder toVisible = null;
-
- View focusedView = viewToFocus;
- int actualFocusIndex = -1;
- // First, scroll until the last focusable column.
- for (int i : new int[]{4, 6}) {
- focusSearchAndWaitForScroll(focusedView, View.FOCUS_RIGHT);
- focusedView = mRecyclerView.getFocusedChild();
- actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
- assertEquals("Focused view should be at adapter position " + i + " whereas it's at "
- + actualFocusIndex, i, actualFocusIndex);
- }
-
- // Further scroll right in order to make the unfocusable rows visible. This process should
- // continue until the currently focused item is still visible. The focused item should not
- // change in this loop.
- for (int i : new int[]{9, 11, 11, 11}) {
- focusSearchAndWaitForScroll(focusedView, View.FOCUS_RIGHT);
- focusedView = mRecyclerView.getFocusedChild();
- actualFocusIndex = mRecyclerView.getChildViewHolder(focusedView).getAdapterPosition();
- toVisible = mRecyclerView.findViewHolderForAdapterPosition(i);
-
- assertEquals("Focused view should not be changed, whereas it's now at "
- + actualFocusIndex, 6, actualFocusIndex);
- assertTrue("Focused child should be at least partially visible.",
- isViewPartiallyInBound(mRecyclerView, focusedView));
- assertTrue("Child view at adapter pos " + i + " should be fully visible.",
- isViewFullyInBound(mRecyclerView, toVisible.itemView));
- }
- }
@Test
public void scrollToPositionWithPredictive() throws Throwable {
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/ViewBoundsCheckTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/ViewBoundsCheckTest.java
deleted file mode 100644
index c950a78..0000000
--- a/v7/recyclerview/tests/src/android/support/v7/widget/ViewBoundsCheckTest.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v7.widget;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.view.View;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-
-@SmallTest
-@RunWith(JUnit4.class)
-public class ViewBoundsCheckTest {
-
-
- private static final String TAG = "ViewBoundsCheckTest";
- private Context mContext;
-
- /** Case #1:
- * Parent: [2.......................8]
- Views: [-3...-1] [-1...1] [1...3] [3...5] [5...7] [7...9] [9...11] [11...13]
- */
- int[] mParentBound1 = {2, 8};
- int[][] mChildrenBound1 = {{-3, -1}, {-1, 1}, {1, 3}, {3, 5}, {5, 7}, {7, 9}, {9, 11},
- {11, 13}};
-
- /** Case #2:
- * Parent: [1...................7]
- Views: [-3...-1] [-1...1][1...3] [3...5] [5...7] [7...9] [9...11]
- */
- int[] mParentBound2 = {1, 7};
- int[][] mChildrenBound2 = {{-3, -1}, {-1, 1}, {1, 3}, {3, 5}, {5, 7}, {7, 9}, {9, 11}};
-
- View mParent;
- View[] mChildren;
-
- private final ViewBoundsCheck.Callback mBoundCheckCallback =
- new ViewBoundsCheck.Callback() {
- @Override
- public int getChildCount() {
- return mChildren.length;
- }
-
- @Override
- public View getParent() {
- return mParent;
- }
-
- @Override
- public View getChildAt(int index) {
- return mChildren[index];
- }
-
- @Override
- public int getParentStart() {
- return mParent.getLeft();
- }
-
- @Override
- public int getParentEnd() {
- return mParent.getRight();
- }
-
- @Override
- public int getChildStart(View view) {
- return view.getLeft();
- }
-
- @Override
- public int getChildEnd(View view) {
- return view.getRight();
- }
- };
-
- ViewBoundsCheck mBoundCheck = new ViewBoundsCheck(mBoundCheckCallback);
-
- @Before
- public void setUp() throws Exception {
- mContext = InstrumentationRegistry.getContext();
- }
-
- private void setUpViews(int[] parentBound, int[][] childrenBound) {
- mParent = new View(mContext);
- mParent.setLeft(parentBound[0]);
- mParent.setRight(parentBound[1]);
- mChildren = new View[childrenBound.length];
- for (int i = 0; i < childrenBound.length; i++) {
- mChildren[i] = new View(mContext);
- mChildren[i].setLeft(childrenBound[i][0]);
- mChildren[i].setRight(childrenBound[i][1]);
- }
- }
-
- @Test
- public void preferredFromStart() {
- setUpViews(mParentBound1, mChildrenBound1);
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = ViewBoundsCheck.FLAG_CVS_GT_PVS
- | ViewBoundsCheck.FLAG_CVS_EQ_PVS | ViewBoundsCheck.FLAG_CVE_LT_PVE
- | ViewBoundsCheck.FLAG_CVE_EQ_PVE;
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = 0;
- View view = mBoundCheck.findOneViewWithinBoundFlags(0, mChildren.length,
- preferredBoundsFlag, acceptableBoundsFlag);
- assertEquals("The first fully visible child from start should be returned", 3,
- view.getLeft());
- assertEquals("The first fully visible child from start should be returned", 5,
- view.getRight());
- }
-
- @Test
- public void preferredFromEnd() {
- setUpViews(mParentBound1, mChildrenBound1);
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = ViewBoundsCheck.FLAG_CVS_GT_PVS
- | ViewBoundsCheck.FLAG_CVS_EQ_PVS | ViewBoundsCheck.FLAG_CVE_LT_PVE
- | ViewBoundsCheck.FLAG_CVE_EQ_PVE;
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = 0;
- View view = mBoundCheck.findOneViewWithinBoundFlags(mChildren.length - 1, -1,
- preferredBoundsFlag, acceptableBoundsFlag);
- assertEquals("The first fully visible child from end should be returned", 5,
- view.getLeft());
- assertEquals("The first fully visible child from end should be returned", 7,
- view.getRight());
- }
-
- @Test
- public void acceptableFromStart() {
- setUpViews(mParentBound1, mChildrenBound1);
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = 0;
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
- | ViewBoundsCheck.FLAG_CVE_LT_PVE | ViewBoundsCheck.FLAG_CVE_GT_PVS);
- View view = mBoundCheck.findOneViewWithinBoundFlags(0, mChildren.length,
- preferredBoundsFlag, acceptableBoundsFlag);
- assertEquals("The first partially visible child from start should be returned", 1,
- view.getLeft());
- assertEquals("The first partially visible child from start should be returned", 3,
- view.getRight());
- }
-
- @Test
- public void acceptableFromEnd() {
- setUpViews(mParentBound1, mChildrenBound1);
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = 0;
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE
- | ViewBoundsCheck.FLAG_CVS_GT_PVS | ViewBoundsCheck.FLAG_CVS_LT_PVE);
- View view = mBoundCheck.findOneViewWithinBoundFlags(mChildren.length - 1, -1,
- preferredBoundsFlag, acceptableBoundsFlag);
- assertEquals("The first partially visible child from end should be returned", 7,
- view.getLeft());
- assertEquals("The first partially visible child from end should be returned", 9,
- view.getRight());
- }
-
- @Test
- public void noPreferredFoundAcceptableReturnedFromStart() {
- setUpViews(mParentBound2, mChildrenBound2);
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
- | ViewBoundsCheck.FLAG_CVE_LT_PVE | ViewBoundsCheck.FLAG_CVE_GT_PVS);
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
- | ViewBoundsCheck.FLAG_CVE_LT_PVE);
- View view = mBoundCheck.findOneViewWithinBoundFlags(0, mChildren.length,
- preferredBoundsFlag, acceptableBoundsFlag);
- assertEquals("The last fully invisible child from start should be returned", -1,
- view.getLeft());
- assertEquals("TThe last fully invisible child from start should be returned", 1,
- view.getRight());
- }
-
- @Test
- public void noPreferredFoundAcceptableReturnedFromEnd() {
- setUpViews(mParentBound2, mChildrenBound2);
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE
- | ViewBoundsCheck.FLAG_CVS_GT_PVS | ViewBoundsCheck.FLAG_CVS_LT_PVE);
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = (ViewBoundsCheck.FLAG_CVE_GT_PVE
- | ViewBoundsCheck.FLAG_CVS_GT_PVS);
- View view = mBoundCheck.findOneViewWithinBoundFlags(mChildren.length - 1, -1,
- preferredBoundsFlag, acceptableBoundsFlag);
- assertEquals("The last fully invisible child from end should be returned", 7,
- view.getLeft());
- assertEquals("TThe last fully invisible child from end should be returned", 9,
- view.getRight());
- }
-
- @Test
- public void noViewsFoundWithinGivenBounds() {
- setUpViews(mParentBound1, mChildrenBound1);
- // create a view whose bounds cover its parent. Since no such view exist in the example
- // layout, null should be returned.
- @ViewBoundsCheck.ViewBounds int preferredBoundsFlag = (ViewBoundsCheck.FLAG_CVS_LT_PVS
- | ViewBoundsCheck.FLAG_CVE_GT_PVE);
- @ViewBoundsCheck.ViewBounds int acceptableBoundsFlag = preferredBoundsFlag;
- View view = mBoundCheck.findOneViewWithinBoundFlags(0, mChildren.length,
- preferredBoundsFlag, acceptableBoundsFlag);
- assertNull("Null should be returned since no views are within the given bounds",
- view);
- }
-
-}