Merge "PlaybackControlGlue: remove dependency on PlaybackControlsRowPresenter" into nyc-support-25.4-dev
diff --git a/api/current.txt b/api/current.txt
index eed38ed..62853ba 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1859,6 +1859,7 @@
public class DetailsFragmentBackgroundController {
ctor public DetailsFragmentBackgroundController(android.support.v17.leanback.app.DetailsFragment);
+ method public boolean canNavigateToVideoFragment();
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();
@@ -1866,6 +1867,7 @@
method public final android.graphics.Bitmap getCoverBitmap();
method public final android.graphics.drawable.Drawable getCoverDrawable();
method public final int getParallaxDrawableMaxOffset();
+ method public final android.support.v17.leanback.media.PlaybackGlue getPlaybackGlue();
method public final int getSolidColor();
method public android.support.v17.leanback.media.PlaybackGlueHost onCreateGlueHost();
method public android.app.Fragment onCreateVideoFragment();
@@ -1873,6 +1875,8 @@
method public final void setParallaxDrawableMaxOffset(int);
method public final void setSolidColor(int);
method public void setupVideoPlayback(android.support.v17.leanback.media.PlaybackGlue);
+ method public final void switchToRows();
+ method public final void switchToVideo();
}
public class DetailsSupportFragment extends android.support.v17.leanback.app.BrandedSupportFragment {
@@ -1900,6 +1904,7 @@
public class DetailsSupportFragmentBackgroundController {
ctor public DetailsSupportFragmentBackgroundController(android.support.v17.leanback.app.DetailsSupportFragment);
+ method public boolean canNavigateToVideoSupportFragment();
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();
@@ -1907,6 +1912,7 @@
method public final android.graphics.Bitmap getCoverBitmap();
method public final android.graphics.drawable.Drawable getCoverDrawable();
method public final int getParallaxDrawableMaxOffset();
+ method public final android.support.v17.leanback.media.PlaybackGlue getPlaybackGlue();
method public final int getSolidColor();
method public android.support.v17.leanback.media.PlaybackGlueHost onCreateGlueHost();
method public android.support.v4.app.Fragment onCreateVideoSupportFragment();
@@ -1914,6 +1920,8 @@
method public final void setParallaxDrawableMaxOffset(int);
method public final void setSolidColor(int);
method public void setupVideoPlayback(android.support.v17.leanback.media.PlaybackGlue);
+ method public final void switchToRows();
+ method public final void switchToVideo();
}
public class ErrorFragment extends android.support.v17.leanback.app.BrandedFragment {
diff --git a/fragment/java/android/support/v4/app/Fragment.java b/fragment/java/android/support/v4/app/Fragment.java
index 8741ff6..698db20 100644
--- a/fragment/java/android/support/v4/app/Fragment.java
+++ b/fragment/java/android/support/v4/app/Fragment.java
@@ -1398,8 +1398,7 @@
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
- }
- if (mLoaderManager != null) {
+ } else if (mLoaderManager != null) {
mLoaderManager.doStart();
}
}
diff --git a/v17/leanback/generatev4.py b/v17/leanback/generatev4.py
index ae695e50..4bd9550 100755
--- a/v17/leanback/generatev4.py
+++ b/v17/leanback/generatev4.py
@@ -100,6 +100,7 @@
line = re.sub(r'FragmentUtil.getContext\(mFragment\)', 'mFragment.getContext()', line);
line = line.replace('VideoFragment', 'VideoSupportFragment')
line = line.replace('DetailsFragment', 'DetailsSupportFragment')
+ line = line.replace('RowsFragment', 'RowsSupportFragment')
line = line.replace('VideoSupportFragmentGlueHost'.format(w), 'VideoSupportFragmentGlueHost'.format(w))
line = line.replace('android.app.Fragment', 'android.support.v4.app.Fragment')
outfile.write(line)
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 5e2980d..c372888 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsBackgroundVideoHelper.java
@@ -56,6 +56,7 @@
private ValueAnimator mBackgroundAnimator;
private Drawable mBackgroundDrawable;
private PlaybackGlue mPlaybackGlue;
+ private boolean mBackgroundDrawableVisible;
/**
* Constructor to setup a Helper for controlling video playback in DetailsFragment.
@@ -75,6 +76,7 @@
this.mPlaybackGlue = playbackGlue;
this.mDetailsParallax = detailsParallax;
this.mBackgroundDrawable = backgroundDrawable;
+ mBackgroundDrawableVisible = true;
startParallax();
}
@@ -97,6 +99,9 @@
}
}
});
+ // In case the VideoHelper is created after RecyclerView is created: perform initial
+ // parallax effect.
+ mDetailsParallax.updateValues();
}
void stopParallax() {
@@ -112,24 +117,44 @@
return;
}
mCurrentState = state;
- switch (state) {
+ applyState();
+ }
+
+ private void applyState() {
+ switch (mCurrentState) {
case PLAY_VIDEO:
- if (mPlaybackGlue.isReadyForPlayback()) {
- internalStartPlayback();
+ if (mPlaybackGlue != null) {
+ if (mPlaybackGlue.isReadyForPlayback()) {
+ internalStartPlayback();
+ } else {
+ mPlaybackGlue.setPlayerCallback(mControlStateCallback);
+ }
} else {
- mPlaybackGlue.setPlayerCallback(new PlaybackControlStateCallback());
+ crossFadeBackgroundToVideo(false);
}
break;
case NO_VIDEO:
crossFadeBackgroundToVideo(false);
- mPlaybackGlue.setPlayerCallback(null);
- mPlaybackGlue.pause();
+ if (mPlaybackGlue != null) {
+ mPlaybackGlue.setPlayerCallback(null);
+ mPlaybackGlue.pause();
+ }
break;
}
}
+ void setPlaybackGlue(PlaybackGlue playbackGlue) {
+ if (mPlaybackGlue != null) {
+ mPlaybackGlue.setPlayerCallback(null);
+ }
+ mPlaybackGlue = playbackGlue;
+ applyState();
+ }
+
private void internalStartPlayback() {
- mPlaybackGlue.play();
+ if (mPlaybackGlue != null) {
+ mPlaybackGlue.play();
+ }
mDetailsParallax.getRecyclerView().postDelayed(new Runnable() {
@Override
public void run() {
@@ -139,6 +164,11 @@
}
private void crossFadeBackgroundToVideo(final boolean crossFadeToVideo) {
+ final boolean newVisible = !crossFadeToVideo;
+ if (mBackgroundDrawableVisible == newVisible) {
+ return;
+ }
+ mBackgroundDrawableVisible = newVisible;
if (mBackgroundAnimator != null) {
mBackgroundAnimator.cancel();
mBackgroundAnimator = null;
@@ -189,4 +219,6 @@
internalStartPlayback();
}
}
+
+ PlaybackControlStateCallback mControlStateCallback = new PlaybackControlStateCallback();
}
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 694384c..7e54146 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragment.java
@@ -77,6 +77,11 @@
* {@link FullWidthDetailsOverviewRowPresenter}.
* </li>
* </p>
+ *
+ * <p>
+ * DetailsFragment can use {@link DetailsFragmentBackgroundController} to add a parallax drawable
+ * background and embedded video playing fragment.
+ * </p>
*/
public class DetailsFragment extends BaseFragment {
static final String TAG = "DetailsFragment";
@@ -723,7 +728,9 @@
if (mRowsFragment.getVerticalGridView() != null
&& mRowsFragment.getVerticalGridView().hasFocus()) {
if (direction == View.FOCUS_UP) {
- if (mVideoFragment != null && mVideoFragment.getView() != null) {
+ if (mDetailsBackgroundController != null
+ && mDetailsBackgroundController.canNavigateToVideoFragment()
+ && mVideoFragment != null && mVideoFragment.getView() != null) {
return mVideoFragment.getView();
} else if (getTitleView() != null && getTitleView().hasFocusable()) {
return getTitleView();
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 ef09ae6..625a196 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsFragmentBackgroundController.java
@@ -107,14 +107,14 @@
*/
public class DetailsFragmentBackgroundController {
- private final DetailsFragment mFragment;
- private DetailsParallaxDrawable mParallaxDrawable;
- private int mParallaxDrawableMaxOffset;
- private PlaybackGlue mPlaybackGlue;
- private DetailsBackgroundVideoHelper mVideoHelper;
- private Bitmap mCoverBitmap;
- private int mSolidColor;
- private boolean mCanUseHost = false;
+ final DetailsFragment mFragment;
+ DetailsParallaxDrawable mParallaxDrawable;
+ int mParallaxDrawableMaxOffset;
+ PlaybackGlue mPlaybackGlue;
+ DetailsBackgroundVideoHelper mVideoHelper;
+ Bitmap mCoverBitmap;
+ int mSolidColor;
+ boolean mCanUseHost = false;
/**
* Creates a DetailsFragmentBackgroundController for a DetailsFragment. Note that
@@ -209,9 +209,13 @@
/**
* 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 details Fragment super.onCreate().
+ * This method must be called after calling details Fragment super.onCreate(). This method
+ * can be called multiple times to replace existing PlaybackGlue or calling
+ * setupVideoPlayback(null) to clear. Note a typical {@link PlaybackGlue} subclass releases
+ * resources in {@link PlaybackGlue#onDetachedFromHost()}, when the {@link PlaybackGlue}
+ * subclass is not doing that, it's app's responsibility to release the resources.
*
- * @param playbackGlue
+ * @param playbackGlue The new PlaybackGlue to set as background or null to clear existing one.
* @see #onCreateVideoFragment()
* @see #onCreateGlueHost().
*/
@@ -219,15 +223,62 @@
if (mPlaybackGlue == playbackGlue) {
return;
}
+ if (mPlaybackGlue != null) {
+ mPlaybackGlue.setHost(null);
+ }
mPlaybackGlue = playbackGlue;
- mVideoHelper = new DetailsBackgroundVideoHelper(mPlaybackGlue,
- mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
- if (mCanUseHost) {
+ if (mVideoHelper == null && mPlaybackGlue != null) {
+ mVideoHelper = new DetailsBackgroundVideoHelper(mPlaybackGlue,
+ mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
+ } else if (mVideoHelper != null) {
+ mVideoHelper.setPlaybackGlue(mPlaybackGlue);
+ }
+ if (mCanUseHost && mPlaybackGlue != null) {
mPlaybackGlue.setHost(onCreateGlueHost());
}
}
/**
+ * Returns current PlaybackGlue or null if not set or cleared.
+ *
+ * @return Current PlaybackGlue or null
+ */
+ public final PlaybackGlue getPlaybackGlue() {
+ return mPlaybackGlue;
+ }
+
+ /**
+ * Precondition allows user navigate to video fragment using DPAD. Default implementation
+ * returns true if PlaybackGlue is not null. Subclass may override, e.g. only allow navigation
+ * when {@link PlaybackGlue#isReadyForPlayback()} is true. Note this method does not block
+ * app calls {@link #switchToVideo}.
+ *
+ * @return True allow to navigate to video fragment.
+ */
+ public boolean canNavigateToVideoFragment() {
+ return mPlaybackGlue != null;
+ }
+
+ /**
+ * Switch to video fragment, note that this method is not affected by result of
+ * {@link #canNavigateToVideoFragment()}.
+ */
+ public final void switchToVideo() {
+ if (mFragment.mVideoFragment != null && mFragment.mVideoFragment.getView() != null) {
+ mFragment.mVideoFragment.getView().requestFocus();
+ }
+ }
+
+ /**
+ * Switch to rows fragment.
+ */
+ public final void switchToRows() {
+ if (mFragment.mRowsFragment != null && mFragment.mRowsFragment.getView() != null) {
+ mFragment.mRowsFragment.getView().requestFocus();
+ }
+ }
+
+ /**
* When fragment is started and no running transition. First set host if not yet set, second
* start playing if it was paused before.
*/
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 033ad0b..511a90b 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragment.java
@@ -80,6 +80,11 @@
* {@link FullWidthDetailsOverviewRowPresenter}.
* </li>
* </p>
+ *
+ * <p>
+ * DetailsSupportFragment can use {@link DetailsSupportFragmentBackgroundController} to add a parallax drawable
+ * background and embedded video playing fragment.
+ * </p>
*/
public class DetailsSupportFragment extends BaseSupportFragment {
static final String TAG = "DetailsSupportFragment";
@@ -726,7 +731,9 @@
if (mRowsSupportFragment.getVerticalGridView() != null
&& mRowsSupportFragment.getVerticalGridView().hasFocus()) {
if (direction == View.FOCUS_UP) {
- if (mVideoSupportFragment != null && mVideoSupportFragment.getView() != null) {
+ if (mDetailsBackgroundController != null
+ && mDetailsBackgroundController.canNavigateToVideoSupportFragment()
+ && mVideoSupportFragment != null && mVideoSupportFragment.getView() != null) {
return mVideoSupportFragment.getView();
} else if (getTitleView() != null && getTitleView().hasFocusable()) {
return getTitleView();
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 071a04a..6149625 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/DetailsSupportFragmentBackgroundController.java
@@ -110,14 +110,14 @@
*/
public class DetailsSupportFragmentBackgroundController {
- private final DetailsSupportFragment mFragment;
- private DetailsParallaxDrawable mParallaxDrawable;
- private int mParallaxDrawableMaxOffset;
- private PlaybackGlue mPlaybackGlue;
- private DetailsBackgroundVideoHelper mVideoHelper;
- private Bitmap mCoverBitmap;
- private int mSolidColor;
- private boolean mCanUseHost = false;
+ final DetailsSupportFragment mFragment;
+ DetailsParallaxDrawable mParallaxDrawable;
+ int mParallaxDrawableMaxOffset;
+ PlaybackGlue mPlaybackGlue;
+ DetailsBackgroundVideoHelper mVideoHelper;
+ Bitmap mCoverBitmap;
+ int mSolidColor;
+ boolean mCanUseHost = false;
/**
* Creates a DetailsSupportFragmentBackgroundController for a DetailsSupportFragment. Note that
@@ -212,9 +212,13 @@
/**
* 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 details Fragment super.onCreate().
+ * This method must be called after calling details Fragment super.onCreate(). This method
+ * can be called multiple times to replace existing PlaybackGlue or calling
+ * setupVideoPlayback(null) to clear. Note a typical {@link PlaybackGlue} subclass releases
+ * resources in {@link PlaybackGlue#onDetachedFromHost()}, when the {@link PlaybackGlue}
+ * subclass is not doing that, it's app's responsibility to release the resources.
*
- * @param playbackGlue
+ * @param playbackGlue The new PlaybackGlue to set as background or null to clear existing one.
* @see #onCreateVideoSupportFragment()
* @see #onCreateGlueHost().
*/
@@ -222,15 +226,62 @@
if (mPlaybackGlue == playbackGlue) {
return;
}
+ if (mPlaybackGlue != null) {
+ mPlaybackGlue.setHost(null);
+ }
mPlaybackGlue = playbackGlue;
- mVideoHelper = new DetailsBackgroundVideoHelper(mPlaybackGlue,
- mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
- if (mCanUseHost) {
+ if (mVideoHelper == null && mPlaybackGlue != null) {
+ mVideoHelper = new DetailsBackgroundVideoHelper(mPlaybackGlue,
+ mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
+ } else if (mVideoHelper != null) {
+ mVideoHelper.setPlaybackGlue(mPlaybackGlue);
+ }
+ if (mCanUseHost && mPlaybackGlue != null) {
mPlaybackGlue.setHost(onCreateGlueHost());
}
}
/**
+ * Returns current PlaybackGlue or null if not set or cleared.
+ *
+ * @return Current PlaybackGlue or null
+ */
+ public final PlaybackGlue getPlaybackGlue() {
+ return mPlaybackGlue;
+ }
+
+ /**
+ * Precondition allows user navigate to video fragment using DPAD. Default implementation
+ * returns true if PlaybackGlue is not null. Subclass may override, e.g. only allow navigation
+ * when {@link PlaybackGlue#isReadyForPlayback()} is true. Note this method does not block
+ * app calls {@link #switchToVideo}.
+ *
+ * @return True allow to navigate to video fragment.
+ */
+ public boolean canNavigateToVideoSupportFragment() {
+ return mPlaybackGlue != null;
+ }
+
+ /**
+ * Switch to video fragment, note that this method is not affected by result of
+ * {@link #canNavigateToVideoSupportFragment()}.
+ */
+ public final void switchToVideo() {
+ if (mFragment.mVideoSupportFragment != null && mFragment.mVideoSupportFragment.getView() != null) {
+ mFragment.mVideoSupportFragment.getView().requestFocus();
+ }
+ }
+
+ /**
+ * Switch to rows fragment.
+ */
+ public final void switchToRows() {
+ if (mFragment.mRowsSupportFragment != null && mFragment.mRowsSupportFragment.getView() != null) {
+ mFragment.mRowsSupportFragment.getView().requestFocus();
+ }
+ }
+
+ /**
* When fragment is started and no running transition. First set host if not yet set, second
* start playing if it was paused before.
*/
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/RecyclerViewParallax.java b/v17/leanback/src/android/support/v17/leanback/widget/RecyclerViewParallax.java
index bdcf044..7253d01 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/RecyclerViewParallax.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/RecyclerViewParallax.java
@@ -41,6 +41,14 @@
}
};
+ View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View view, int l, int t, int r, int b,
+ int oldL, int oldT, int oldR, int oldB) {
+ updateValues();
+ }
+ };
+
/**
* Subclass of {@link Parallax.IntProperty}. Using this Property, users can track a
* RecylerView child's position inside recyclerview. i.e.
@@ -211,6 +219,7 @@
}
if (mRecylerView != null) {
mRecylerView.removeOnScrollListener(mOnScrollListener);
+ mRecylerView.removeOnLayoutChangeListener(mOnLayoutChangeListener);
}
mRecylerView = recyclerView;
if (mRecylerView != null) {
@@ -218,6 +227,7 @@
.getProperties(mRecylerView.getContext(), null, 0, 0);
mIsVertical = properties.orientation == RecyclerView.VERTICAL;
mRecylerView.addOnScrollListener(mOnScrollListener);
+ mRecylerView.addOnLayoutChangeListener(mOnLayoutChangeListener);
}
}
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsFragmentTest.java
index 4356459..c8db4bd 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsFragmentTest.java
@@ -30,6 +30,7 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
+import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.v17.leanback.R;
@@ -57,6 +58,11 @@
static final int PARALLAX_VERTICAL_OFFSET = -300;
+ static int getCoverDrawableAlpha(DetailsFragmentBackgroundController controller) {
+ return ((FitWidthBitmapDrawable) controller.mParallaxDrawable.getCoverDrawable())
+ .getAlpha();
+ }
+
public static class DetailsFragmentParallax extends DetailsTestFragment {
private DetailsParallaxDrawable mParallaxDrawable;
@@ -386,6 +392,14 @@
navigateBetweenRowsAndVideoUsingDPADInternal(DetailsFragmentWithVideo2.class);
}
+ public static class EmptyFragmentClass extends Fragment {
+ @Override
+ public void onStart() {
+ super.onStart();
+ getActivity().finish();
+ }
+ }
+
private void fragmentOnStartWithVideoInternal(Class cls) throws Throwable {
launchAndWaitActivity(cls,
new Options().uiVisibility(
@@ -427,7 +441,7 @@
public void run() {
Intent intent = new Intent(mActivity, SingleFragmentTestActivity.class);
intent.putExtra(SingleFragmentTestActivity.EXTRA_FRAGMENT_NAME,
- Fragment.class.getName());
+ EmptyFragmentClass.class.getName());
mActivity.startActivity(intent);
}
}
@@ -435,17 +449,6 @@
PollingCheck.waitFor(2000, new PollingCheck.PollingCheckCondition() {
@Override
public boolean canProceed() {
- return !detailsFragment.isResumed();
- }
- });
- // pop empty activity, have to wait 1000 before sending BACK key or the key will lose
- // nowhere.
- Thread.sleep(1000);
- sendKeys(KeyEvent.KEYCODE_BACK);
-
- PollingCheck.waitFor(2000, new PollingCheck.PollingCheckCondition() {
- @Override
- public boolean canProceed() {
return detailsFragment.isResumed();
}
});
@@ -509,4 +512,272 @@
assertTrue(firstRow.hasFocus());
assertEquals(originalFirstRowTop, firstRow.getTop());
}
+
+ public static class DetailsFragmentWithNoVideo extends DetailsTestFragment {
+
+ final DetailsFragmentBackgroundController mDetailsBackground =
+ new DetailsFragmentBackgroundController(this);
+
+ public DetailsFragmentWithNoVideo() {
+ mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mDetailsBackground.enableParallax();
+
+ setItem(new PhotoItem("Hello world", "Fake content goes here",
+ android.support.v17.leanback.test.R.drawable.spiderman));
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(),
+ android.support.v17.leanback.test.R.drawable.spiderman);
+ mDetailsBackground.setCoverBitmap(bitmap);
+ }
+
+ @Override
+ public void onStop() {
+ mDetailsBackground.setCoverBitmap(null);
+ super.onStop();
+ }
+ }
+
+ @Test
+ public void lateSetupVideo() {
+ launchAndWaitActivity(DetailsFragmentWithNoVideo.class, new Options().uiVisibility(
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0);
+ final DetailsFragmentWithNoVideo detailsFragment =
+ (DetailsFragmentWithNoVideo) mActivity.getTestFragment();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.setItem(new PhotoItem("Hello world", "Fake content goes here",
+ android.support.v17.leanback.test.R.drawable.spiderman));
+ }
+ });
+
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return detailsFragment.getRowsFragment().getVerticalGridView().getChildCount() > 0;
+ }
+ });
+ final View firstRow = detailsFragment.getRowsFragment().getVerticalGridView().getChildAt(0);
+ final int screenHeight = detailsFragment.getRowsFragment().getVerticalGridView()
+ .getHeight();
+
+ assertTrue(firstRow.hasFocus());
+ assertTrue(detailsFragment.isShowingTitle());
+ assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight);
+
+ sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+ assertTrue(firstRow.hasFocus());
+
+ SystemClock.sleep(1000);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ final MediaPlayerGlue glue = new MediaPlayerGlue(mActivity);
+ detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue);
+ glue.setMode(MediaPlayerGlue.REPEAT_ALL);
+ glue.setArtist("A Googleer");
+ glue.setTitle("Diving with Sharks");
+ glue.setMediaSource(Uri.parse(
+ "android.resource://android.support.v17.leanback.test/raw/video"));
+ }
+ }
+ );
+
+ // after setup Video Playback the DPAD up will navigate to Video Fragment.
+ sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+ assertTrue(detailsFragment.mVideoFragment.getView().hasFocus());
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return ((MediaPlayerGlue) detailsFragment.mDetailsBackgroundController
+ .getPlaybackGlue()).isMediaPlaying();
+ }
+ });
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return 0 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController);
+ }
+ });
+
+ // wait a little bit to replace with new Glue
+ SystemClock.sleep(1000);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ final MediaPlayerGlue glue2 = new MediaPlayerGlue(mActivity);
+ detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue2);
+ glue2.setMode(MediaPlayerGlue.REPEAT_ALL);
+ glue2.setArtist("A Googleer");
+ glue2.setTitle("Diving with Sharks");
+ glue2.setMediaSource(Uri.parse(
+ "android.resource://android.support.v17.leanback.test/raw/video"));
+ }
+ }
+ );
+
+ // test switchToRows() and switchToVideo()
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.mDetailsBackgroundController.switchToRows();
+ }
+ }
+ );
+ assertTrue(detailsFragment.mRowsFragment.getView().hasFocus());
+ PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(firstRow));
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.mDetailsBackgroundController.switchToVideo();
+ }
+ }
+ );
+ assertTrue(detailsFragment.mVideoFragment.getView().hasFocus());
+ PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(firstRow));
+ }
+
+ @Test
+ public void clearVideo() {
+ launchAndWaitActivity(DetailsFragmentWithNoVideo.class, new Options().uiVisibility(
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0);
+ final DetailsFragmentWithNoVideo detailsFragment =
+ (DetailsFragmentWithNoVideo) mActivity.getTestFragment();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.setItem(new PhotoItem("Hello world", "Fake content goes here",
+ android.support.v17.leanback.test.R.drawable.spiderman));
+ }
+ });
+
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return detailsFragment.getRowsFragment().getVerticalGridView().getChildCount() > 0;
+ }
+ });
+ final View firstRow = detailsFragment.getRowsFragment().getVerticalGridView().getChildAt(0);
+ final int screenHeight = detailsFragment.getRowsFragment().getVerticalGridView()
+ .getHeight();
+
+ assertTrue(firstRow.hasFocus());
+ assertTrue(detailsFragment.isShowingTitle());
+ assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight);
+
+ SystemClock.sleep(1000);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ final MediaPlayerGlue glue = new MediaPlayerGlue(mActivity);
+ detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue);
+ glue.setMode(MediaPlayerGlue.REPEAT_ALL);
+ glue.setArtist("A Googleer");
+ glue.setTitle("Diving with Sharks");
+ glue.setMediaSource(Uri.parse(
+ "android.resource://android.support.v17.leanback.test/raw/video"));
+ }
+ }
+ );
+
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return ((MediaPlayerGlue) detailsFragment.mDetailsBackgroundController
+ .getPlaybackGlue()).isMediaPlaying();
+ }
+ });
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return 0 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController);
+ }
+ });
+
+ // wait a little bit then clear glue
+ SystemClock.sleep(1000);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.mDetailsBackgroundController.setupVideoPlayback(null);
+ }
+ }
+ );
+ // background should fade in upon clear playback
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return 255 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController);
+ }
+ });
+ }
+
+ public static class DetailsFragmentWithNoItem extends DetailsTestFragment {
+
+ final DetailsFragmentBackgroundController mDetailsBackground =
+ new DetailsFragmentBackgroundController(this);
+
+ public DetailsFragmentWithNoItem() {
+ mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mDetailsBackground.enableParallax();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(),
+ android.support.v17.leanback.test.R.drawable.spiderman);
+ mDetailsBackground.setCoverBitmap(bitmap);
+ }
+
+ @Override
+ public void onStop() {
+ mDetailsBackground.setCoverBitmap(null);
+ super.onStop();
+ }
+ }
+
+ @Test
+ public void noInitialItem() {
+ launchAndWaitActivity(DetailsFragmentWithNoItem.class, new Options().uiVisibility(
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0);
+ final DetailsFragmentWithNoItem detailsFragment =
+ (DetailsFragmentWithNoItem) mActivity.getTestFragment();
+
+ final int recyclerViewHeight = detailsFragment.getRowsFragment().getVerticalGridView()
+ .getHeight();
+ assertTrue(recyclerViewHeight > 0);
+
+ assertEquals(255, getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController));
+ assertEquals(255, detailsFragment.mDetailsBackgroundController.mParallaxDrawable
+ .getAlpha());
+ Drawable coverDrawable = detailsFragment.mDetailsBackgroundController.getCoverDrawable();
+ assertEquals(0, coverDrawable.getBounds().top);
+ assertEquals(recyclerViewHeight, coverDrawable.getBounds().bottom);
+ Drawable bottomDrawable = detailsFragment.mDetailsBackgroundController.getBottomDrawable();
+ assertEquals(recyclerViewHeight, bottomDrawable.getBounds().top);
+ assertEquals(recyclerViewHeight, bottomDrawable.getBounds().bottom);
+ }
}
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsSupportFragmentTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsSupportFragmentTest.java
index f90eb1b..03277bd 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsSupportFragmentTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/DetailsSupportFragmentTest.java
@@ -33,6 +33,7 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
+import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.v17.leanback.R;
@@ -60,6 +61,11 @@
static final int PARALLAX_VERTICAL_OFFSET = -300;
+ static int getCoverDrawableAlpha(DetailsSupportFragmentBackgroundController controller) {
+ return ((FitWidthBitmapDrawable) controller.mParallaxDrawable.getCoverDrawable())
+ .getAlpha();
+ }
+
public static class DetailsSupportFragmentParallax extends DetailsTestSupportFragment {
private DetailsParallaxDrawable mParallaxDrawable;
@@ -389,6 +395,14 @@
navigateBetweenRowsAndVideoUsingDPADInternal(DetailsSupportFragmentWithVideo2.class);
}
+ public static class EmptyFragmentClass extends Fragment {
+ @Override
+ public void onStart() {
+ super.onStart();
+ getActivity().finish();
+ }
+ }
+
private void fragmentOnStartWithVideoInternal(Class cls) throws Throwable {
launchAndWaitActivity(cls,
new Options().uiVisibility(
@@ -430,7 +444,7 @@
public void run() {
Intent intent = new Intent(mActivity, SingleSupportFragmentTestActivity.class);
intent.putExtra(SingleSupportFragmentTestActivity.EXTRA_FRAGMENT_NAME,
- Fragment.class.getName());
+ EmptyFragmentClass.class.getName());
mActivity.startActivity(intent);
}
}
@@ -438,17 +452,6 @@
PollingCheck.waitFor(2000, new PollingCheck.PollingCheckCondition() {
@Override
public boolean canProceed() {
- return !detailsFragment.isResumed();
- }
- });
- // pop empty activity, have to wait 1000 before sending BACK key or the key will lose
- // nowhere.
- Thread.sleep(1000);
- sendKeys(KeyEvent.KEYCODE_BACK);
-
- PollingCheck.waitFor(2000, new PollingCheck.PollingCheckCondition() {
- @Override
- public boolean canProceed() {
return detailsFragment.isResumed();
}
});
@@ -512,4 +515,272 @@
assertTrue(firstRow.hasFocus());
assertEquals(originalFirstRowTop, firstRow.getTop());
}
+
+ public static class DetailsSupportFragmentWithNoVideo extends DetailsTestSupportFragment {
+
+ final DetailsSupportFragmentBackgroundController mDetailsBackground =
+ new DetailsSupportFragmentBackgroundController(this);
+
+ public DetailsSupportFragmentWithNoVideo() {
+ mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mDetailsBackground.enableParallax();
+
+ setItem(new PhotoItem("Hello world", "Fake content goes here",
+ android.support.v17.leanback.test.R.drawable.spiderman));
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(),
+ android.support.v17.leanback.test.R.drawable.spiderman);
+ mDetailsBackground.setCoverBitmap(bitmap);
+ }
+
+ @Override
+ public void onStop() {
+ mDetailsBackground.setCoverBitmap(null);
+ super.onStop();
+ }
+ }
+
+ @Test
+ public void lateSetupVideo() {
+ launchAndWaitActivity(DetailsSupportFragmentWithNoVideo.class, new Options().uiVisibility(
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0);
+ final DetailsSupportFragmentWithNoVideo detailsFragment =
+ (DetailsSupportFragmentWithNoVideo) mActivity.getTestFragment();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.setItem(new PhotoItem("Hello world", "Fake content goes here",
+ android.support.v17.leanback.test.R.drawable.spiderman));
+ }
+ });
+
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildCount() > 0;
+ }
+ });
+ final View firstRow = detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildAt(0);
+ final int screenHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView()
+ .getHeight();
+
+ assertTrue(firstRow.hasFocus());
+ assertTrue(detailsFragment.isShowingTitle());
+ assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight);
+
+ sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+ assertTrue(firstRow.hasFocus());
+
+ SystemClock.sleep(1000);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ final MediaPlayerGlue glue = new MediaPlayerGlue(mActivity);
+ detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue);
+ glue.setMode(MediaPlayerGlue.REPEAT_ALL);
+ glue.setArtist("A Googleer");
+ glue.setTitle("Diving with Sharks");
+ glue.setMediaSource(Uri.parse(
+ "android.resource://android.support.v17.leanback.test/raw/video"));
+ }
+ }
+ );
+
+ // after setup Video Playback the DPAD up will navigate to Video Fragment.
+ sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+ assertTrue(detailsFragment.mVideoSupportFragment.getView().hasFocus());
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return ((MediaPlayerGlue) detailsFragment.mDetailsBackgroundController
+ .getPlaybackGlue()).isMediaPlaying();
+ }
+ });
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return 0 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController);
+ }
+ });
+
+ // wait a little bit to replace with new Glue
+ SystemClock.sleep(1000);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ final MediaPlayerGlue glue2 = new MediaPlayerGlue(mActivity);
+ detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue2);
+ glue2.setMode(MediaPlayerGlue.REPEAT_ALL);
+ glue2.setArtist("A Googleer");
+ glue2.setTitle("Diving with Sharks");
+ glue2.setMediaSource(Uri.parse(
+ "android.resource://android.support.v17.leanback.test/raw/video"));
+ }
+ }
+ );
+
+ // test switchToRows() and switchToVideo()
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.mDetailsBackgroundController.switchToRows();
+ }
+ }
+ );
+ assertTrue(detailsFragment.mRowsSupportFragment.getView().hasFocus());
+ PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(firstRow));
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.mDetailsBackgroundController.switchToVideo();
+ }
+ }
+ );
+ assertTrue(detailsFragment.mVideoSupportFragment.getView().hasFocus());
+ PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(firstRow));
+ }
+
+ @Test
+ public void clearVideo() {
+ launchAndWaitActivity(DetailsSupportFragmentWithNoVideo.class, new Options().uiVisibility(
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0);
+ final DetailsSupportFragmentWithNoVideo detailsFragment =
+ (DetailsSupportFragmentWithNoVideo) mActivity.getTestFragment();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.setItem(new PhotoItem("Hello world", "Fake content goes here",
+ android.support.v17.leanback.test.R.drawable.spiderman));
+ }
+ });
+
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildCount() > 0;
+ }
+ });
+ final View firstRow = detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildAt(0);
+ final int screenHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView()
+ .getHeight();
+
+ assertTrue(firstRow.hasFocus());
+ assertTrue(detailsFragment.isShowingTitle());
+ assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight);
+
+ SystemClock.sleep(1000);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ final MediaPlayerGlue glue = new MediaPlayerGlue(mActivity);
+ detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue);
+ glue.setMode(MediaPlayerGlue.REPEAT_ALL);
+ glue.setArtist("A Googleer");
+ glue.setTitle("Diving with Sharks");
+ glue.setMediaSource(Uri.parse(
+ "android.resource://android.support.v17.leanback.test/raw/video"));
+ }
+ }
+ );
+
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return ((MediaPlayerGlue) detailsFragment.mDetailsBackgroundController
+ .getPlaybackGlue()).isMediaPlaying();
+ }
+ });
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return 0 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController);
+ }
+ });
+
+ // wait a little bit then clear glue
+ SystemClock.sleep(1000);
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ new Runnable() {
+ @Override
+ public void run() {
+ detailsFragment.mDetailsBackgroundController.setupVideoPlayback(null);
+ }
+ }
+ );
+ // background should fade in upon clear playback
+ PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() {
+ @Override
+ public boolean canProceed() {
+ return 255 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController);
+ }
+ });
+ }
+
+ public static class DetailsSupportFragmentWithNoItem extends DetailsTestSupportFragment {
+
+ final DetailsSupportFragmentBackgroundController mDetailsBackground =
+ new DetailsSupportFragmentBackgroundController(this);
+
+ public DetailsSupportFragmentWithNoItem() {
+ mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mDetailsBackground.enableParallax();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(),
+ android.support.v17.leanback.test.R.drawable.spiderman);
+ mDetailsBackground.setCoverBitmap(bitmap);
+ }
+
+ @Override
+ public void onStop() {
+ mDetailsBackground.setCoverBitmap(null);
+ super.onStop();
+ }
+ }
+
+ @Test
+ public void noInitialItem() {
+ launchAndWaitActivity(DetailsSupportFragmentWithNoItem.class, new Options().uiVisibility(
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0);
+ final DetailsSupportFragmentWithNoItem detailsFragment =
+ (DetailsSupportFragmentWithNoItem) mActivity.getTestFragment();
+
+ final int recyclerViewHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView()
+ .getHeight();
+ assertTrue(recyclerViewHeight > 0);
+
+ assertEquals(255, getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController));
+ assertEquals(255, detailsFragment.mDetailsBackgroundController.mParallaxDrawable
+ .getAlpha());
+ Drawable coverDrawable = detailsFragment.mDetailsBackgroundController.getCoverDrawable();
+ assertEquals(0, coverDrawable.getBounds().top);
+ assertEquals(recyclerViewHeight, coverDrawable.getBounds().bottom);
+ Drawable bottomDrawable = detailsFragment.mDetailsBackgroundController.getBottomDrawable();
+ assertEquals(recyclerViewHeight, bottomDrawable.getBounds().top);
+ assertEquals(recyclerViewHeight, bottomDrawable.getBounds().bottom);
+ }
}