From 9e0b99381db43e4e6c0171217502b018300a6ac1 Mon Sep 17 00:00:00 2001 From: Yuriy Liskov Date: Wed, 14 Oct 2020 08:22:54 +0300 Subject: [PATCH] animated previews --- MediaServiceCore | 2 +- .../common/app/models/data/Video.java | 2 + .../playback/managers/StateUpdater.java | 1 + smartyoutubetv2/build.gradle | 2 + .../tv/presenter/CardPresenter.java | 1 + .../textbadgecard/TextBadgeImageCardView.java | 46 ++-- .../textbadgecard/TextBadgeImageLayout.java | 43 ---- .../textbadgecard/TextBadgeImageView.java | 117 ++++++++++ .../widgets/videocard/LoopingVideoView.java | 58 +++++ .../ui/widgets/videocard/PreviewCardView.java | 79 +++++++ .../ui/widgets/videocard/VideoCardView.java | 217 ++++++++++++++++++ .../smartyoutubetv2/tv/util/NetworkUtil.java | 16 ++ .../src/main/res/layout/image_card_view.xml | 5 - .../main/res/layout/image_card_view_badge.xml | 17 -- .../main/res/layout/lb_image_card_view.xml | 4 +- .../main/res/layout/lb_video_card_view.xml | 71 ++++++ .../main/res/layout/text_badge_image_view.xml | 31 +++ .../main/res/layout/widget_preview_card.xml | 35 +++ .../src/main/res/values/colors.xml | 1 + .../src/main/res/values/dimens.xml | 9 + 20 files changed, 663 insertions(+), 94 deletions(-) delete mode 100644 smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageLayout.java create mode 100644 smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageView.java create mode 100644 smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/LoopingVideoView.java create mode 100644 smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/PreviewCardView.java create mode 100644 smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/VideoCardView.java create mode 100644 smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/util/NetworkUtil.java delete mode 100644 smartyoutubetv2/src/main/res/layout/image_card_view.xml delete mode 100644 smartyoutubetv2/src/main/res/layout/image_card_view_badge.xml create mode 100644 smartyoutubetv2/src/main/res/layout/lb_video_card_view.xml create mode 100644 smartyoutubetv2/src/main/res/layout/text_badge_image_view.xml create mode 100644 smartyoutubetv2/src/main/res/layout/widget_preview_card.xml diff --git a/MediaServiceCore b/MediaServiceCore index 68de8120e..49caabc23 160000 --- a/MediaServiceCore +++ b/MediaServiceCore @@ -1 +1 @@ -Subproject commit 68de8120e841ebd72a2699a869e5b8d615a4b7f2 +Subproject commit 49caabc23701bb154ec72a783107782d594b6fb9 diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/Video.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/Video.java index 27b5f0d92..498587c4e 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/Video.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/data/Video.java @@ -22,6 +22,7 @@ public final class Video implements Parcelable { public String cardImageUrl; public String studio; public String badge; + public String previewUrl; public int percentWatched; public MediaItem mediaItem; @@ -77,6 +78,7 @@ public final class Video implements Parcelable { video.studio = item.getAuthor(); video.percentWatched = item.getPercentWatched(); video.badge = item.getBadgeText(); + video.previewUrl = item.getVideoPreviewUrl(); video.mediaItem = item; return video; diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/managers/StateUpdater.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/managers/StateUpdater.java index d3ac22089..09218271a 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/managers/StateUpdater.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/managers/StateUpdater.java @@ -152,6 +152,7 @@ public class StateUpdater extends PlayerEventListenerHelper { public void onPlayEnd() { Video video = mController.getVideo(); + // In case we start to watch the video again if (video != null) { mStates.remove(video.videoId); } diff --git a/smartyoutubetv2/build.gradle b/smartyoutubetv2/build.gradle index d83434248..dc8031e68 100644 --- a/smartyoutubetv2/build.gradle +++ b/smartyoutubetv2/build.gradle @@ -103,6 +103,8 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:' + appCompatXLibraryVersion implementation 'com.github.bumptech.glide:glide:' + glideVersion + annotationProcessor 'com.github.bumptech.glide:compiler:' + glideVersion + implementation 'com.zlc.glide:webpdecoder:2.0.' + glideVersion implementation 'com.google.android.exoplayer:exoplayer:' + amazonExoplayerVersion implementation 'com.google.android.exoplayer:extension-leanback:' + amazonExoplayerVersion diff --git a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/presenter/CardPresenter.java b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/presenter/CardPresenter.java index 3b8aee32a..5b18428fa 100644 --- a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/presenter/CardPresenter.java +++ b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/presenter/CardPresenter.java @@ -88,6 +88,7 @@ public class CardPresenter extends Presenter { cardView.setTitleText(video.title); cardView.setContentText(video.description); cardView.setBadgeText(video.badge); + cardView.setPreviewUrl(video.previewUrl); if (video.cardImageUrl != null) { // Set card size from dimension resources. diff --git a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageCardView.java b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageCardView.java index b09fd3bbe..8b2e81945 100644 --- a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageCardView.java +++ b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageCardView.java @@ -3,32 +3,29 @@ package com.liskovsoft.smartyoutubetv2.tv.ui.widgets.textbadgecard; import android.content.Context; import android.text.TextUtils.TruncateAt; import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; import android.widget.TextView; import androidx.leanback.widget.ImageCardView; import com.liskovsoft.smartyoutubetv2.tv.R; public class TextBadgeImageCardView extends ImageCardView { - private TextView mBadgeText; + private TextBadgeImageView mTextBadgeImageLayout; public TextBadgeImageCardView(Context context) { super(context); - createTextBadge(); + init(); } public TextBadgeImageCardView(Context context, AttributeSet attrs) { super(context, attrs); - createTextBadge(); + init(); } public TextBadgeImageCardView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - createTextBadge(); + init(); } private void enableTextAnimation(boolean enable) { @@ -53,31 +50,15 @@ public class TextBadgeImageCardView extends ImageCardView { } } - private void createTextBadge() { - ViewGroup wrapper = findViewById(R.id.main_image_wrapper); - - if (wrapper != null) { - LayoutInflater inflater = LayoutInflater.from(getContext()); - - int layoutId = R.layout.image_card_view_badge; - mBadgeText = (TextView) inflater.inflate(layoutId, wrapper, false); - wrapper.addView(mBadgeText); - } + private void init() { + mTextBadgeImageLayout = findViewById(R.id.main_image_wrapper); } /** * Sets the badge text. */ public void setBadgeText(String text) { - if (mBadgeText == null) { - return; - } - mBadgeText.setText(text); - if (text != null) { - mBadgeText.setVisibility(View.VISIBLE); - } else { - mBadgeText.setVisibility(View.GONE); - } + mTextBadgeImageLayout.setBadgeText(text); } @Override @@ -85,5 +66,18 @@ public class TextBadgeImageCardView extends ImageCardView { super.setSelected(selected); enableTextAnimation(selected); + enableVideoPreview(selected); + } + + private void enableVideoPreview(boolean selected) { + if (selected) { + mTextBadgeImageLayout.setLoading(); + } else { + mTextBadgeImageLayout.setFinished(); + } + } + + public void setPreviewUrl(String previewUrl) { + mTextBadgeImageLayout.setPreviewUrl(previewUrl); } } diff --git a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageLayout.java b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageLayout.java deleted file mode 100644 index b890e89bf..000000000 --- a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageLayout.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.liskovsoft.smartyoutubetv2.tv.ui.widgets.textbadgecard; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import com.liskovsoft.smartyoutubetv2.tv.R; - -public class TextBadgeImageLayout extends RelativeLayout { - private ImageView mMainImage; - - public TextBadgeImageLayout(Context context) { - super(context); - init(); - } - - public TextBadgeImageLayout(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public TextBadgeImageLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - inflate(getContext(), R.layout.image_card_view, this); - mMainImage = findViewById(R.id.main_image); - } - - /** - * Main trick is to apply visibility to child image views
- * See: androidx.leanback.widget.BaseCardView#findChildrenViews() - */ - @Override - public void setVisibility(int visibility) { - super.setVisibility(visibility); - if (mMainImage != null) { - mMainImage.setVisibility(visibility); - } - } -} diff --git a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageView.java b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageView.java new file mode 100644 index 000000000..3f30bd1c6 --- /dev/null +++ b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/textbadgecard/TextBadgeImageView.java @@ -0,0 +1,117 @@ +package com.liskovsoft.smartyoutubetv2.tv.ui.widgets.textbadgecard; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import androidx.annotation.Nullable; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.liskovsoft.smartyoutubetv2.tv.R; + +public class TextBadgeImageView extends RelativeLayout { + private ImageView mMainImage; + private ImageView mPreviewImage; + private TextView mBadgeText; + private String mPreviewUrl; + + public TextBadgeImageView(Context context) { + super(context); + init(); + } + + public TextBadgeImageView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public TextBadgeImageView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + inflate(getContext(), R.layout.text_badge_image_view, this); + mMainImage = findViewById(R.id.main_image); + mPreviewImage = findViewById(R.id.preview_image); + mBadgeText = findViewById(R.id.extra_text_badge); + } + + /** + * Main trick is to apply visibility to child image views
+ * See: androidx.leanback.widget.BaseCardView#findChildrenViews() + */ + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + if (mMainImage != null) { + mMainImage.setVisibility(visibility); + } + } + + /** + * Sets the badge text. + */ + public void setBadgeText(String text) { + if (mBadgeText == null) { + return; + } + mBadgeText.setText(text); + if (text != null) { + mBadgeText.setVisibility(View.VISIBLE); + } else { + mBadgeText.setVisibility(View.GONE); + } + } + + public void setPreviewUrl(String videoUrl) { + mPreviewUrl = videoUrl; + } + + //public ImageView getImageView() { + // return mImageView; + //} + + public void setLoading() { + if (mPreviewUrl == null) { + return; + } + + mPreviewImage.setVisibility(View.VISIBLE); + mMainImage.setVisibility(View.GONE); + + Glide.with(getContext()) + .load(mPreviewUrl) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, + boolean isFirstResource) { + //mMainImage.setVisibility(View.GONE); + //mPreviewImage.setVisibility(View.VISIBLE); + return false; + } + }) + .into(mPreviewImage); + } + + public void setFinished() { + if (mPreviewUrl == null) { + return; + } + + mPreviewImage.setVisibility(View.GONE); + mPreviewImage.setImageDrawable(null); + mMainImage.setVisibility(View.VISIBLE); + } +} diff --git a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/LoopingVideoView.java b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/LoopingVideoView.java new file mode 100644 index 000000000..69c79e930 --- /dev/null +++ b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/LoopingVideoView.java @@ -0,0 +1,58 @@ +package com.liskovsoft.smartyoutubetv2.tv.ui.widgets.videocard; + +import android.content.Context; +import android.media.MediaPlayer; +import android.net.Uri; +import android.util.AttributeSet; +import android.widget.VideoView; + +public class LoopingVideoView extends VideoView { + + private MediaPlayer mMediaPlayer; + + public LoopingVideoView(Context context) { + super(context); + } + + public LoopingVideoView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public LoopingVideoView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public LoopingVideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public void setupMediaPlayer(String url, final OnVideoReadyListener onVideoReadyListener) { + setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mp) { + mMediaPlayer = mp; + mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { + @Override + public void onBufferingUpdate(MediaPlayer mp, int percent) { + if (percent > 20) onVideoReadyListener.onVideoReady(); + } + }); + mMediaPlayer.setLooping(true); + mMediaPlayer.setVolume(0, 0); + mMediaPlayer.start(); + } + }); + setVideoURI(Uri.parse(url)); + } + + public void stopMediaPlayer() { + if (mMediaPlayer != null) { + mMediaPlayer.release(); + } + } + + public interface OnVideoReadyListener { + void onVideoReady(); + } + +} diff --git a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/PreviewCardView.java b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/PreviewCardView.java new file mode 100644 index 000000000..c4f574381 --- /dev/null +++ b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/PreviewCardView.java @@ -0,0 +1,79 @@ +package com.liskovsoft.smartyoutubetv2.tv.ui.widgets.videocard; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.ProgressBar; +import com.liskovsoft.smartyoutubetv2.tv.R; + +public class PreviewCardView extends FrameLayout { + FrameLayout mMainContainer; + + LoopingVideoView mVideoView; + + ImageView mImageView; + + View mOverlayView; + + ProgressBar mProgressCard; + + private String mVideoUrl; + + public PreviewCardView(Context context) { + super(context); + init(); + } + + public PreviewCardView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public PreviewCardView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + View view = inflate(getContext(), R.layout.widget_preview_card, this); + + mMainContainer = view.findViewById(R.id.main_container); + mVideoView = view.findViewById(R.id.main_video); + mImageView = view.findViewById(R.id.main_image); + mOverlayView = view.findViewById(R.id.view_overlay); + mProgressCard = view.findViewById(R.id.progress_card); + } + + public void setVideoUrl(String videoUrl) { + mVideoUrl = videoUrl; + } + + public ImageView getImageView() { + return mImageView; + } + + public void setLoading() { + mOverlayView.setVisibility(View.VISIBLE); + mProgressCard.setVisibility(View.VISIBLE); + mVideoView.setVisibility(View.VISIBLE); + mVideoView.setupMediaPlayer(mVideoUrl, new LoopingVideoView.OnVideoReadyListener() { + @Override + public void onVideoReady() { + mOverlayView.setVisibility(View.INVISIBLE); + mProgressCard.setVisibility(View.INVISIBLE); + mImageView.setVisibility(View.INVISIBLE); + } + }); + } + + public void setFinished() { + mVideoView.setVisibility(View.INVISIBLE); + mVideoView.stopMediaPlayer(); + mImageView.setVisibility(View.VISIBLE); + mOverlayView.setVisibility(View.INVISIBLE); + mProgressCard.setVisibility(View.INVISIBLE); + } + +} diff --git a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/VideoCardView.java b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/VideoCardView.java new file mode 100644 index 000000000..0a52259a5 --- /dev/null +++ b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/widgets/videocard/VideoCardView.java @@ -0,0 +1,217 @@ +package com.liskovsoft.smartyoutubetv2.tv.ui.widgets.videocard; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import androidx.leanback.widget.BaseCardView; +import com.liskovsoft.smartyoutubetv2.tv.R; +import com.liskovsoft.smartyoutubetv2.tv.util.NetworkUtil; + +public class VideoCardView extends BaseCardView { + public static final int CARD_TYPE_FLAG_IMAGE_ONLY = 0; + public static final int CARD_TYPE_FLAG_TITLE = 1; + public static final int CARD_TYPE_FLAG_CONTENT = 2; + + PreviewCardView mPreviewCard; + + ViewGroup mInfoArea; + + private TextView mTitleView; + private TextView mContentView; + private boolean mAttachedToWindow; + + public VideoCardView(Context context, int styleResId) { + super(new ContextThemeWrapper(context, styleResId), null, 0); + buildImageCardView(styleResId); + } + + public VideoCardView(Context context, AttributeSet attrs, int defStyleAttr) { + super(getStyledContext(context, attrs, defStyleAttr), attrs, defStyleAttr); + buildImageCardView(getImageCardViewStyle(context, attrs, defStyleAttr)); + } + + @Override + public boolean hasOverlappingRendering() { + return false; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mAttachedToWindow = true; + ImageView mImageView = mPreviewCard.getImageView(); + if (mImageView.getAlpha() == 0) fadeIn(); + } + + @Override + protected void onDetachedFromWindow() { + ImageView mImageView = mPreviewCard.getImageView(); + mAttachedToWindow = false; + mImageView.animate().cancel(); + mImageView.setAlpha(1f); + super.onDetachedFromWindow(); + } + + private void buildImageCardView(int styleResId) { + // Make sure the ImageCardView is focusable. + setFocusable(true); + setFocusableInTouchMode(true); + + LayoutInflater inflater = LayoutInflater.from(getContext()); + View view = inflater.inflate(R.layout.lb_video_card_view, this); + mPreviewCard = view.findViewById(R.id.layout_preview_card); + mInfoArea = view.findViewById(R.id.info_field); + + TypedArray cardAttrs = + getContext().obtainStyledAttributes(styleResId, R.styleable.lbImageCardView); + int cardType = + cardAttrs.getInt( + R.styleable.lbImageCardView_lbImageCardViewType, CARD_TYPE_FLAG_IMAGE_ONLY); + boolean hasImageOnly = cardType == CARD_TYPE_FLAG_IMAGE_ONLY; + boolean hasTitle = (cardType & CARD_TYPE_FLAG_TITLE) == CARD_TYPE_FLAG_TITLE; + boolean hasContent = (cardType & CARD_TYPE_FLAG_CONTENT) == CARD_TYPE_FLAG_CONTENT; + + if (hasImageOnly) { + removeView(mInfoArea); + cardAttrs.recycle(); + return; + } + + // Create children + if (hasTitle) { + mTitleView = (TextView) inflater.inflate(R.layout.lb_image_card_view_themed_title, mInfoArea, false); + mInfoArea.addView(mTitleView); + } + + if (hasContent) { + mContentView = (TextView) inflater.inflate(R.layout.lb_image_card_view_themed_content, mInfoArea, false); + mInfoArea.addView(mContentView); + } + + // Backward compatibility: Newly created ImageCardViews should change + // the InfoArea's background color in XML using the corresponding style. + // However, since older implementations might make use of the + // 'infoAreaBackground' attribute, we have to make sure to support it. + // If the user has set a specific value here, it will differ from null. + // In this case, we do want to override the value set in the style. + Drawable background = cardAttrs.getDrawable(R.styleable.lbImageCardView_infoAreaBackground); + if (null != background) { + setInfoAreaBackground(background); + } + + cardAttrs.recycle(); + } + + private static Context getStyledContext(Context context, AttributeSet attrs, int defStyleAttr) { + int style = getImageCardViewStyle(context, attrs, defStyleAttr); + return new ContextThemeWrapper(context, style); + } + + private static int getImageCardViewStyle(Context context, AttributeSet attrs, int defStyleAttr) { + // Read style attribute defined in XML layout. + int style = null == attrs ? 0 : attrs.getStyleAttribute(); + if (0 == style) { + // Not found? Read global ImageCardView style from Theme attribute. + TypedArray styledAttrs = context.obtainStyledAttributes(R.styleable.LeanbackTheme); + style = styledAttrs.getResourceId(R.styleable.LeanbackTheme_imageCardViewStyle, 0); + styledAttrs.recycle(); + } + return style; + } + + public VideoCardView(Context context) { + this(context, null); + } + + public VideoCardView(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.imageCardViewStyle); + } + + /** + * Returns the main image view. + */ + public final ImageView getMainImageView() { + return mPreviewCard.getImageView(); + } + + /** + * Sets the layout dimensions of the ImageView. + */ + public void setMainContainerDimensions(int width, int height) { + ViewGroup.LayoutParams lp = mPreviewCard.getLayoutParams(); + lp.width = width; + lp.height = height; + mPreviewCard.setLayoutParams(lp); + } + + /** + * Sets the info area background drawable. + */ + public void setInfoAreaBackground(Drawable drawable) { + if (mInfoArea != null) { + mInfoArea.setBackground(drawable); + } + } + + public void setVideoUrl(String url) { + mPreviewCard.setVideoUrl(url); + } + + public void startVideo() { + if (NetworkUtil.isNetworkConnected(getContext())) { + mPreviewCard.setLoading(); + } + } + + public void stopVideo() { + mPreviewCard.setFinished(); + } + + /** + * Sets the title text. + */ + public void setTitleText(CharSequence text) { + if (mTitleView == null) { + return; + } + mTitleView.setText(text); + } + + /** + * Sets the content text. + */ + public void setContentText(CharSequence text) { + if (mContentView == null) { + return; + } + mContentView.setText(text); + } + + private void fadeIn() { + ImageView mImageView = mPreviewCard.getImageView(); + mImageView.setAlpha(0f); + if (mAttachedToWindow) { + int duration = + mImageView.getResources().getInteger(android.R.integer.config_shortAnimTime); + mImageView.animate().alpha(1f).setDuration(duration); + } + } + + @Override + public void setSelected(boolean selected) { + super.setSelected(selected); + + if (selected) { + startVideo(); + } else { + stopVideo(); + } + } +} diff --git a/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/util/NetworkUtil.java b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/util/NetworkUtil.java new file mode 100644 index 000000000..45e990db5 --- /dev/null +++ b/smartyoutubetv2/src/main/java/com/liskovsoft/smartyoutubetv2/tv/util/NetworkUtil.java @@ -0,0 +1,16 @@ +package com.liskovsoft.smartyoutubetv2.tv.util; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +public class NetworkUtil { + public static boolean isNetworkConnected(Context context) { + ConnectivityManager cm = + (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); + + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + return activeNetwork != null && + activeNetwork.isConnectedOrConnecting(); + } +} \ No newline at end of file diff --git a/smartyoutubetv2/src/main/res/layout/image_card_view.xml b/smartyoutubetv2/src/main/res/layout/image_card_view.xml deleted file mode 100644 index 5c86675b7..000000000 --- a/smartyoutubetv2/src/main/res/layout/image_card_view.xml +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/smartyoutubetv2/src/main/res/layout/image_card_view_badge.xml b/smartyoutubetv2/src/main/res/layout/image_card_view_badge.xml deleted file mode 100644 index 337684e2b..000000000 --- a/smartyoutubetv2/src/main/res/layout/image_card_view_badge.xml +++ /dev/null @@ -1,17 +0,0 @@ - - \ No newline at end of file diff --git a/smartyoutubetv2/src/main/res/layout/lb_image_card_view.xml b/smartyoutubetv2/src/main/res/layout/lb_image_card_view.xml index 1d0e82b3b..0c251843a 100644 --- a/smartyoutubetv2/src/main/res/layout/lb_image_card_view.xml +++ b/smartyoutubetv2/src/main/res/layout/lb_image_card_view.xml @@ -4,11 +4,11 @@ - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smartyoutubetv2/src/main/res/layout/text_badge_image_view.xml b/smartyoutubetv2/src/main/res/layout/text_badge_image_view.xml new file mode 100644 index 000000000..cd8b71ec3 --- /dev/null +++ b/smartyoutubetv2/src/main/res/layout/text_badge_image_view.xml @@ -0,0 +1,31 @@ + + + + + + \ No newline at end of file diff --git a/smartyoutubetv2/src/main/res/layout/widget_preview_card.xml b/smartyoutubetv2/src/main/res/layout/widget_preview_card.xml new file mode 100644 index 000000000..b37d0d4d8 --- /dev/null +++ b/smartyoutubetv2/src/main/res/layout/widget_preview_card.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/smartyoutubetv2/src/main/res/values/colors.xml b/smartyoutubetv2/src/main/res/values/colors.xml index 972a3a174..b33d99541 100644 --- a/smartyoutubetv2/src/main/res/values/colors.xml +++ b/smartyoutubetv2/src/main/res/values/colors.xml @@ -19,4 +19,5 @@ #4A4F51 #2A2F51 #FF000000 + #77000000 diff --git a/smartyoutubetv2/src/main/res/values/dimens.xml b/smartyoutubetv2/src/main/res/values/dimens.xml index db480fab0..6052e0946 100644 --- a/smartyoutubetv2/src/main/res/values/dimens.xml +++ b/smartyoutubetv2/src/main/res/values/dimens.xml @@ -5,6 +5,15 @@ 205dp 115dp + 140dp + 188dp + 52dp + 6dp + 2dp + 16sp + 12sp + 16dp + 100dp