mirror of
https://github.com/yuliskov/SmartTube.git
synced 2026-01-08 06:50:28 -06:00
animated previews
This commit is contained in:
Submodule MediaServiceCore updated: 68de8120e8...49caabc237
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<br/>
|
||||
* See: androidx.leanback.widget.BaseCardView#findChildrenViews()
|
||||
*/
|
||||
@Override
|
||||
public void setVisibility(int visibility) {
|
||||
super.setVisibility(visibility);
|
||||
if (mMainImage != null) {
|
||||
mMainImage.setVisibility(visibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<br/>
|
||||
* 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<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> 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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main_image"
|
||||
style="?attr/imageCardViewImageStyle"/>
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:visibility="gone"
|
||||
android:id="@+id/extra_text_badge"
|
||||
android:layout_alignBottom="@+id/main_image"
|
||||
android:layout_alignEnd="@+id/main_image"
|
||||
android:layout_marginEnd="@dimen/lb_basic_card_info_badge_margin"
|
||||
android:layout_marginBottom="@dimen/lb_basic_card_info_badge_margin"
|
||||
android:background="@color/black"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
android:paddingStart="@dimen/lb_details_description_title_padding_adjust_bottom"
|
||||
android:paddingEnd="@dimen/lb_details_description_title_padding_adjust_bottom"
|
||||
style="@style/TextAppearance.Leanback.ImageCardView.Content" />
|
||||
@@ -4,11 +4,11 @@
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:lb="http://schemas.android.com/apk/res-auto" >
|
||||
|
||||
<com.liskovsoft.smartyoutubetv2.tv.ui.widgets.textbadgecard.TextBadgeImageLayout
|
||||
<com.liskovsoft.smartyoutubetv2.tv.ui.widgets.textbadgecard.TextBadgeImageView
|
||||
android:id="@+id/main_image_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
</com.liskovsoft.smartyoutubetv2.tv.ui.widgets.textbadgecard.TextBadgeImageLayout>
|
||||
</com.liskovsoft.smartyoutubetv2.tv.ui.widgets.textbadgecard.TextBadgeImageView>
|
||||
|
||||
<androidx.leanback.widget.NonOverlappingRelativeLayout
|
||||
android:id="@+id/info_field"
|
||||
|
||||
71
smartyoutubetv2/src/main/res/layout/lb_video_card_view.xml
Normal file
71
smartyoutubetv2/src/main/res/layout/lb_video_card_view.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:lb="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.liskovsoft.smartyoutubetv2.tv.ui.widgets.videocard.PreviewCardView
|
||||
android:id="@+id/layout_preview_card"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
lb:layout_viewType="main" />
|
||||
|
||||
<androidx.leanback.widget.NonOverlappingFrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
lb:layout_viewType="info">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/info_field"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/lb_basic_card_info_height"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:padding="@dimen/lb_basic_card_info_padding">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginLeft="@dimen/lb_basic_card_info_text_margin"
|
||||
android:layout_marginTop="@dimen/lb_basic_card_info_text_margin"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/lb_basic_card_title_text_color"
|
||||
android:textSize="@dimen/lb_basic_card_title_text_size" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/content_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginBottom="@dimen/lb_basic_card_info_text_margin"
|
||||
android:layout_marginLeft="@dimen/lb_basic_card_info_text_margin"
|
||||
android:ellipsize="none"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/lb_basic_card_content_text_color"
|
||||
android:textSize="@dimen/lb_basic_card_content_text_size" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/extra_badge"
|
||||
android:layout_width="@dimen/lb_basic_card_info_badge_size"
|
||||
android:layout_height="@dimen/lb_basic_card_info_badge_size"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fade_mask"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/lb_basic_card_info_badge_size"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toStartOf="@id/extra_badge"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
</androidx.leanback.widget.NonOverlappingFrameLayout>
|
||||
</merge>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ImageView
|
||||
android:id="@+id/main_image"
|
||||
style="?attr/imageCardViewImageStyle"/>
|
||||
<ImageView
|
||||
android:visibility="gone"
|
||||
android:id="@+id/preview_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitXY"
|
||||
android:adjustViewBounds="true"
|
||||
android:layout_alignTop="@+id/main_image"
|
||||
android:layout_alignStart="@+id/main_image"
|
||||
/>
|
||||
<TextView android:visibility="gone"
|
||||
android:id="@+id/extra_text_badge"
|
||||
android:layout_alignBottom="@+id/main_image"
|
||||
android:layout_alignEnd="@+id/main_image"
|
||||
android:layout_marginEnd="@dimen/lb_basic_card_info_badge_margin"
|
||||
android:layout_marginBottom="@dimen/lb_basic_card_info_badge_margin"
|
||||
android:background="@color/black"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
android:paddingStart="@dimen/lb_details_description_title_padding_adjust_bottom"
|
||||
android:paddingEnd="@dimen/lb_details_description_title_padding_adjust_bottom"
|
||||
style="@style/TextAppearance.Leanback.ImageCardView.Content" />
|
||||
</merge>
|
||||
35
smartyoutubetv2/src/main/res/layout/widget_preview_card.xml
Normal file
35
smartyoutubetv2/src/main/res/layout/widget_preview_card.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.liskovsoft.smartyoutubetv2.tv.ui.widgets.videocard.LoopingVideoView
|
||||
android:id="@+id/main_video"
|
||||
android:layout_width="175dp"
|
||||
android:layout_height="175dp"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/main_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@null"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black_87pc"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_card"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="invisible" />
|
||||
|
||||
</FrameLayout>
|
||||
@@ -19,4 +19,5 @@
|
||||
<color name="icon_background">#4A4F51</color>
|
||||
<color name="icon_alt_background">#2A2F51</color>
|
||||
<color name="player_background">#FF000000</color>
|
||||
<color name="black_87pc">#77000000</color>
|
||||
</resources>
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
<dimen name="card_width">205dp</dimen>
|
||||
<dimen name="card_height">115dp</dimen>
|
||||
|
||||
<dimen name="lb_basic_card_main_width">140dp</dimen>
|
||||
<dimen name="lb_basic_card_main_height">188dp</dimen>
|
||||
<dimen name="lb_basic_card_info_height">52dp</dimen>
|
||||
<dimen name="lb_basic_card_info_padding">6dp</dimen>
|
||||
<dimen name="lb_basic_card_info_text_margin">2dp</dimen>
|
||||
<dimen name="lb_basic_card_title_text_size">16sp</dimen>
|
||||
<dimen name="lb_basic_card_content_text_size">12sp</dimen>
|
||||
<dimen name="lb_basic_card_info_badge_size">16dp</dimen>
|
||||
|
||||
<!-- Elements below aren't used in the app -->
|
||||
|
||||
<dimen name="grid_item_width">100dp</dimen>
|
||||
|
||||
Reference in New Issue
Block a user