Mini player, ExpandableSurfaceView with ZOOM support, popup
- mini player's title, image and author information will be updated in many situations but the main idea is that the info will be the same as currently playing stream. If nothing played then you'll see the info about currently opened stream in fragment. When MainPlayer service stops the info updates too - made ExpandableSurfaceView to replace AspectRatioFrameLayout. The reason for that is to make possible to use aspect ratio mode ZOOM. It's impossible to show a stream inside AspectRatioFrameLayout with ZOOM mode and to fit the video view to a screen space at the same time. Now the new view able to do that and to show vertical videos in a slightly wide space for them - refactored some methods to make the code more understandable - made fixes for player view for landscape-to-landscape orientation change - added Java docs - adapted swipe tracking inside bottom sheet - fixed PlayQueue crashes on clearing - paddings for popup player now as small as possible
This commit is contained in:
parent
26e487c01a
commit
f334a2740f
14 changed files with 405 additions and 225 deletions
|
@ -30,7 +30,7 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
|
||||||
ViewGroup playQueue = child.findViewById(R.id.playQueue);
|
ViewGroup playQueue = child.findViewById(R.id.playQueue);
|
||||||
if (playQueue != null) {
|
if (playQueue != null) {
|
||||||
playQueue.getGlobalVisibleRect(playQueueRect);
|
playQueue.getGlobalVisibleRect(playQueueRect);
|
||||||
if (playQueueRect.contains((int) ev.getX(), (int) ev.getY())) {
|
if (playQueueRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
|
||||||
allowScroll = false;
|
allowScroll = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import android.app.Activity;
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -108,6 +107,7 @@ public class VideoDetailFragment
|
||||||
private static final int TOOLBAR_ITEMS_UPDATE_FLAG = 0x4;
|
private static final int TOOLBAR_ITEMS_UPDATE_FLAG = 0x4;
|
||||||
private static final int COMMENTS_UPDATE_FLAG = 0x8;
|
private static final int COMMENTS_UPDATE_FLAG = 0x8;
|
||||||
private static final float MAX_OVERLAY_ALPHA = 0.9f;
|
private static final float MAX_OVERLAY_ALPHA = 0.9f;
|
||||||
|
private static final float MAX_PLAYER_HEIGHT = 0.7f;
|
||||||
|
|
||||||
public static final String ACTION_SHOW_MAIN_PLAYER = "org.schabi.newpipe.fragments.VideoDetailFragment.ACTION_SHOW_MAIN_PLAYER";
|
public static final String ACTION_SHOW_MAIN_PLAYER = "org.schabi.newpipe.fragments.VideoDetailFragment.ACTION_SHOW_MAIN_PLAYER";
|
||||||
public static final String ACTION_HIDE_MAIN_PLAYER = "org.schabi.newpipe.fragments.VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER";
|
public static final String ACTION_HIDE_MAIN_PLAYER = "org.schabi.newpipe.fragments.VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER";
|
||||||
|
@ -235,7 +235,7 @@ public class VideoDetailFragment
|
||||||
// It will do nothing if the player is not in fullscreen mode
|
// It will do nothing if the player is not in fullscreen mode
|
||||||
hideSystemUIIfNeeded();
|
hideSystemUIIfNeeded();
|
||||||
|
|
||||||
if (!player.videoPlayerSelected()) return;
|
if (!player.videoPlayerSelected() && !playAfterConnect) return;
|
||||||
|
|
||||||
// STATE_IDLE means the player is stopped
|
// STATE_IDLE means the player is stopped
|
||||||
if (player.getPlayer() != null && player.getPlayer().getPlaybackState() != Player.STATE_IDLE) addVideoPlayerView();
|
if (player.getPlayer() != null && player.getPlayer().getPlaybackState() != Player.STATE_IDLE) addVideoPlayerView();
|
||||||
|
@ -282,6 +282,9 @@ public class VideoDetailFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startService(boolean playAfterConnect) {
|
private void startService(boolean playAfterConnect) {
|
||||||
|
// startService() can be called concurrently and it will give a random crashes and NullPointerExceptions
|
||||||
|
// inside the service because the service will be bound twice. Prevent it with unbinding first
|
||||||
|
unbind();
|
||||||
getContext().startService(new Intent(getContext(), MainPlayer.class));
|
getContext().startService(new Intent(getContext(), MainPlayer.class));
|
||||||
serviceConnection = getServiceConnection(playAfterConnect);
|
serviceConnection = getServiceConnection(playAfterConnect);
|
||||||
bind();
|
bind();
|
||||||
|
@ -708,7 +711,6 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
private void initThumbnailViews(@NonNull StreamInfo info) {
|
private void initThumbnailViews(@NonNull StreamInfo info) {
|
||||||
thumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
|
thumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
|
||||||
overlayThumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(info.getThumbnailUrl())) {
|
if (!TextUtils.isEmpty(info.getThumbnailUrl())) {
|
||||||
final String infoServiceName = NewPipe.getNameOfService(info.getServiceId());
|
final String infoServiceName = NewPipe.getNameOfService(info.getServiceId());
|
||||||
|
@ -718,11 +720,6 @@ public class VideoDetailFragment
|
||||||
showSnackBarError(failReason.getCause(), UserAction.LOAD_IMAGE,
|
showSnackBarError(failReason.getCause(), UserAction.LOAD_IMAGE,
|
||||||
infoServiceName, imageUri, R.string.could_not_load_thumbnails);
|
infoServiceName, imageUri, R.string.could_not_load_thumbnails);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
|
||||||
overlayThumbnailImageView.setImageBitmap(loadedImage);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
imageLoader.displayImage(info.getThumbnailUrl(), thumbnailImageView,
|
imageLoader.displayImage(info.getThumbnailUrl(), thumbnailImageView,
|
||||||
|
@ -855,7 +852,7 @@ public class VideoDetailFragment
|
||||||
*/
|
*/
|
||||||
protected final LinkedList<StackItem> stack = new LinkedList<>();
|
protected final LinkedList<StackItem> stack = new LinkedList<>();
|
||||||
|
|
||||||
public void setTitleToUrl(int serviceId, String videoUrl, String name) {
|
/*public void setTitleToUrl(int serviceId, String videoUrl, String name) {
|
||||||
if (name != null && !name.isEmpty()) {
|
if (name != null && !name.isEmpty()) {
|
||||||
for (StackItem stackItem : stack) {
|
for (StackItem stackItem : stack) {
|
||||||
if (stack.peek().getServiceId() == serviceId
|
if (stack.peek().getServiceId() == serviceId
|
||||||
|
@ -864,7 +861,7 @@ public class VideoDetailFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onBackPressed() {
|
public boolean onBackPressed() {
|
||||||
|
@ -887,7 +884,9 @@ public class VideoDetailFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have something in history of played items we replay it here
|
// If we have something in history of played items we replay it here
|
||||||
if (player != null && player.getPlayQueue() != null && player.getPlayQueue().previous()) {
|
boolean isPreviousCanBePlayed = player != null && player.getPlayQueue() != null && player.videoPlayerSelected()
|
||||||
|
&& player.getPlayQueue().previous();
|
||||||
|
if (isPreviousCanBePlayed) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// That means that we are on the start of the stack,
|
// That means that we are on the start of the stack,
|
||||||
|
@ -914,6 +913,12 @@ public class VideoDetailFragment
|
||||||
item.getUrl(),
|
item.getUrl(),
|
||||||
!TextUtils.isEmpty(item.getTitle()) ? item.getTitle() : "",
|
!TextUtils.isEmpty(item.getTitle()) ? item.getTitle() : "",
|
||||||
item.getPlayQueue());
|
item.getPlayQueue());
|
||||||
|
|
||||||
|
PlayQueueItem playQueueItem = item.getPlayQueue().getItem();
|
||||||
|
// Update title, url, uploader from the last item in the stack (it's current now)
|
||||||
|
boolean isPlayerStopped = player == null || player.isPlayerStopped();
|
||||||
|
if (playQueueItem != null && isPlayerStopped)
|
||||||
|
updateOverlayData(playQueueItem.getTitle(), playQueueItem.getUploader(), playQueueItem.getThumbnailUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1199,7 +1204,7 @@ public class VideoDetailFragment
|
||||||
FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder);
|
FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder);
|
||||||
|
|
||||||
// Check if viewHolder already contains a child
|
// Check if viewHolder already contains a child
|
||||||
if (player.getRootView() != viewHolder) removeVideoPlayerView();
|
if (player.getRootView().getParent() != viewHolder) removeVideoPlayerView();
|
||||||
setHeightThumbnail();
|
setHeightThumbnail();
|
||||||
|
|
||||||
// Prevent from re-adding a view multiple times
|
// Prevent from re-adding a view multiple times
|
||||||
|
@ -1250,6 +1255,11 @@ public class VideoDetailFragment
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method which controls the size of thumbnail and the size of main player inside a layout with thumbnail.
|
||||||
|
* It decides what height the player should have in both screen orientations. It knows about multiWindow feature
|
||||||
|
* and about videos with aspectRatio ZOOM (the height for them will be a bit higher, {@link #MAX_PLAYER_HEIGHT})
|
||||||
|
*/
|
||||||
private void setHeightThumbnail() {
|
private void setHeightThumbnail() {
|
||||||
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||||
boolean isPortrait = metrics.heightPixels > metrics.widthPixels;
|
boolean isPortrait = metrics.heightPixels > metrics.widthPixels;
|
||||||
|
@ -1260,11 +1270,14 @@ public class VideoDetailFragment
|
||||||
else
|
else
|
||||||
height = isPortrait
|
height = isPortrait
|
||||||
? (int) (metrics.widthPixels / (16.0f / 9.0f))
|
? (int) (metrics.widthPixels / (16.0f / 9.0f))
|
||||||
: (int) (metrics.heightPixels / 2f);;
|
: (int) (metrics.heightPixels / 2f);
|
||||||
|
|
||||||
thumbnailImageView.setLayoutParams(
|
thumbnailImageView.setLayoutParams(new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
||||||
new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
|
||||||
thumbnailImageView.setMinimumHeight(height);
|
thumbnailImageView.setMinimumHeight(height);
|
||||||
|
if (player != null) {
|
||||||
|
int maxHeight = (int) (metrics.heightPixels * MAX_PLAYER_HEIGHT);
|
||||||
|
player.getSurfaceView().setHeights(height, player.isInFullscreen() ? height : maxHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showContent() {
|
private void showContent() {
|
||||||
|
@ -1393,13 +1406,11 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
animateView(thumbnailPlayButton, true, 200);
|
animateView(thumbnailPlayButton, true, 200);
|
||||||
videoTitleTextView.setText(name);
|
videoTitleTextView.setText(name);
|
||||||
overlayTitleTextView.setText(name);
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(info.getUploaderName())) {
|
if (!TextUtils.isEmpty(info.getUploaderName())) {
|
||||||
uploaderTextView.setText(info.getUploaderName());
|
uploaderTextView.setText(info.getUploaderName());
|
||||||
uploaderTextView.setVisibility(View.VISIBLE);
|
uploaderTextView.setVisibility(View.VISIBLE);
|
||||||
uploaderTextView.setSelected(true);
|
uploaderTextView.setSelected(true);
|
||||||
overlayChannelTextView.setText(info.getUploaderName());
|
|
||||||
} else {
|
} else {
|
||||||
uploaderTextView.setVisibility(View.GONE);
|
uploaderTextView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
@ -1481,8 +1492,9 @@ public class VideoDetailFragment
|
||||||
setupActionBar(info);
|
setupActionBar(info);
|
||||||
initThumbnailViews(info);
|
initThumbnailViews(info);
|
||||||
|
|
||||||
setTitleToUrl(info.getServiceId(), info.getUrl(), info.getName());
|
if (player == null || player.isPlayerStopped())
|
||||||
setTitleToUrl(info.getServiceId(), info.getOriginalUrl(), info.getName());
|
updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
|
||||||
|
|
||||||
|
|
||||||
if (!info.getErrors().isEmpty()) {
|
if (!info.getErrors().isEmpty()) {
|
||||||
showSnackBarError(info.getErrors(),
|
showSnackBarError(info.getErrors(),
|
||||||
|
@ -1682,7 +1694,8 @@ public class VideoDetailFragment
|
||||||
peek.setUrl(info.getUrl());
|
peek.setUrl(info.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentInfo == info) return;
|
updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
|
||||||
|
if (currentInfo != null && info.getUrl().equals(currentInfo.getUrl())) return;
|
||||||
|
|
||||||
currentInfo = info;
|
currentInfo = info;
|
||||||
setAutoplay(false);
|
setAutoplay(false);
|
||||||
|
@ -1702,6 +1715,8 @@ public class VideoDetailFragment
|
||||||
public void onServiceStopped() {
|
public void onServiceStopped() {
|
||||||
unbind();
|
unbind();
|
||||||
setOverlayPlayPauseImage();
|
setOverlayPlayPauseImage();
|
||||||
|
if (currentInfo != null)
|
||||||
|
updateOverlayData(currentInfo.getName(), currentInfo.getUploaderName(), currentInfo.getThumbnailUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1858,9 +1873,11 @@ public class VideoDetailFragment
|
||||||
private void cleanUp() {
|
private void cleanUp() {
|
||||||
// New beginning
|
// New beginning
|
||||||
stack.clear();
|
stack.clear();
|
||||||
|
if (currentWorker != null) currentWorker.dispose();
|
||||||
stopService();
|
stopService();
|
||||||
setInitialData(0,null,"", null);
|
setInitialData(0,null,"", null);
|
||||||
currentInfo = null;
|
currentInfo = null;
|
||||||
|
updateOverlayData(null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1899,16 +1916,20 @@ public class VideoDetailFragment
|
||||||
// Disable click because overlay buttons located on top of buttons from the player
|
// Disable click because overlay buttons located on top of buttons from the player
|
||||||
setOverlayElementsClickable(false);
|
setOverlayElementsClickable(false);
|
||||||
hideSystemUIIfNeeded();
|
hideSystemUIIfNeeded();
|
||||||
if (isLandscape() && player != null && player.isPlaying() && !player.isInFullscreen())
|
boolean needToExpand = isLandscape()
|
||||||
player.toggleFullscreen();
|
&& player != null
|
||||||
|
&& player.isPlaying()
|
||||||
|
&& !player.isInFullscreen()
|
||||||
|
&& player.videoPlayerSelected();
|
||||||
|
if (needToExpand) player.toggleFullscreen();
|
||||||
break;
|
break;
|
||||||
case BottomSheetBehavior.STATE_COLLAPSED:
|
case BottomSheetBehavior.STATE_COLLAPSED:
|
||||||
// Re-enable clicks
|
// Re-enable clicks
|
||||||
setOverlayElementsClickable(true);
|
setOverlayElementsClickable(true);
|
||||||
if (player != null && player.isInFullscreen()) showSystemUi();
|
|
||||||
break;
|
break;
|
||||||
case BottomSheetBehavior.STATE_DRAGGING:
|
case BottomSheetBehavior.STATE_DRAGGING:
|
||||||
case BottomSheetBehavior.STATE_SETTLING:
|
case BottomSheetBehavior.STATE_SETTLING:
|
||||||
|
if (player != null && player.isInFullscreen()) showSystemUi();
|
||||||
if (player != null && player.isControlsVisible()) player.hideControls(0, 0);
|
if (player != null && player.isControlsVisible()) player.hideControls(0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1925,6 +1946,15 @@ public class VideoDetailFragment
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateOverlayData(@Nullable String title, @Nullable String uploader, @Nullable String thumbnailUrl) {
|
||||||
|
overlayTitleTextView.setText(!TextUtils.isEmpty(title) ? title : "");
|
||||||
|
overlayChannelTextView.setText(!TextUtils.isEmpty(uploader) ? uploader : "");
|
||||||
|
overlayThumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
|
||||||
|
if (!TextUtils.isEmpty(thumbnailUrl))
|
||||||
|
imageLoader.displayImage(thumbnailUrl, overlayThumbnailImageView,
|
||||||
|
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, null);
|
||||||
|
}
|
||||||
|
|
||||||
private void setOverlayPlayPauseImage() {
|
private void setOverlayPlayPauseImage() {
|
||||||
boolean playing = player != null && player.getPlayer().getPlayWhenReady();
|
boolean playing = player != null && player.getPlayer().getPlayWhenReady();
|
||||||
int attr = playing ? R.attr.pause : R.attr.play;
|
int attr = playing ? R.attr.pause : R.attr.play;
|
||||||
|
@ -1935,7 +1965,8 @@ public class VideoDetailFragment
|
||||||
if (behavior != null) {
|
if (behavior != null) {
|
||||||
overlay.setAlpha(Math.min(MAX_OVERLAY_ALPHA, 1 - slideOffset));
|
overlay.setAlpha(Math.min(MAX_OVERLAY_ALPHA, 1 - slideOffset));
|
||||||
|
|
||||||
behavior.setTopAndBottomOffset((int)(-appBarLayout.getTotalScrollRange() * (1 - slideOffset) / 3));
|
// These numbers are not special. They just do a cool transition
|
||||||
|
behavior.setTopAndBottomOffset((int)(-thumbnailImageView.getHeight() * 2 * (1 - slideOffset) / 3));
|
||||||
appBarLayout.requestLayout();
|
appBarLayout.requestLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,14 +276,6 @@ public abstract class BasePlayer implements
|
||||||
|
|
||||||
boolean same = playQueue != null && playQueue.equals(queue);
|
boolean same = playQueue != null && playQueue.equals(queue);
|
||||||
|
|
||||||
// Do not re-init the same PlayQueue. Save time
|
|
||||||
if (same && !playQueue.isDisposed()) {
|
|
||||||
// Player can have state = IDLE when playback is stopped or failed and we should retry() in this case
|
|
||||||
if (simpleExoPlayer != null && simpleExoPlayer.getPlaybackState() == Player.STATE_IDLE)
|
|
||||||
simpleExoPlayer.retry();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode());
|
final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode());
|
||||||
final float playbackSpeed = intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed());
|
final float playbackSpeed = intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed());
|
||||||
final float playbackPitch = intent.getFloatExtra(PLAYBACK_PITCH, getPlaybackPitch());
|
final float playbackPitch = intent.getFloatExtra(PLAYBACK_PITCH, getPlaybackPitch());
|
||||||
|
@ -298,10 +290,17 @@ public abstract class BasePlayer implements
|
||||||
&& playQueue.getItem() != null
|
&& playQueue.getItem() != null
|
||||||
&& queue.getItem().getUrl().equals(playQueue.getItem().getUrl())
|
&& queue.getItem().getUrl().equals(playQueue.getItem().getUrl())
|
||||||
&& queue.getItem().getRecoveryPosition() != PlayQueueItem.RECOVERY_UNSET
|
&& queue.getItem().getRecoveryPosition() != PlayQueueItem.RECOVERY_UNSET
|
||||||
&& !same) {
|
&& simpleExoPlayer.getPlaybackState() != Player.STATE_IDLE) {
|
||||||
|
// Player can have state = IDLE when playback is stopped or failed and we should retry() in this case
|
||||||
|
if (simpleExoPlayer.getPlaybackState() == Player.STATE_IDLE) simpleExoPlayer.retry();
|
||||||
simpleExoPlayer.seekTo(playQueue.getIndex(), queue.getItem().getRecoveryPosition());
|
simpleExoPlayer.seekTo(playQueue.getIndex(), queue.getItem().getRecoveryPosition());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
} else if (same && !playQueue.isDisposed() && simpleExoPlayer != null) {
|
||||||
|
// Do not re-init the same PlayQueue. Save time
|
||||||
|
// Player can have state = IDLE when playback is stopped or failed and we should retry() in this case
|
||||||
|
if (simpleExoPlayer.getPlaybackState() == Player.STATE_IDLE) simpleExoPlayer.retry();
|
||||||
|
return;
|
||||||
} else if (intent.getBooleanExtra(RESUME_PLAYBACK, false)
|
} else if (intent.getBooleanExtra(RESUME_PLAYBACK, false)
|
||||||
&& isPlaybackResumeEnabled()
|
&& isPlaybackResumeEnabled()
|
||||||
&& !same) {
|
&& !same) {
|
||||||
|
|
|
@ -179,6 +179,7 @@ public final class MainPlayer extends Service {
|
||||||
|
|
||||||
playerImpl.savePlaybackState();
|
playerImpl.savePlaybackState();
|
||||||
playerImpl.stopActivityBinding();
|
playerImpl.stopActivityBinding();
|
||||||
|
playerImpl.removePopupFromView();
|
||||||
playerImpl.destroy();
|
playerImpl.destroy();
|
||||||
}
|
}
|
||||||
if (notificationManager != null) notificationManager.cancel(NOTIFICATION_ID);
|
if (notificationManager != null) notificationManager.cancel(NOTIFICATION_ID);
|
||||||
|
|
|
@ -34,10 +34,7 @@ import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.*;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.SurfaceView;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -65,6 +62,7 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
||||||
import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
||||||
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
|
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
import org.schabi.newpipe.util.AnimationUtils;
|
||||||
|
import org.schabi.newpipe.views.ExpandableSurfaceView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -109,8 +107,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
|
|
||||||
private View rootView;
|
private View rootView;
|
||||||
|
|
||||||
private AspectRatioFrameLayout aspectRatioFrameLayout;
|
private ExpandableSurfaceView surfaceView;
|
||||||
private SurfaceView surfaceView;
|
|
||||||
private View surfaceForeground;
|
private View surfaceForeground;
|
||||||
|
|
||||||
private View loadingPanel;
|
private View loadingPanel;
|
||||||
|
@ -163,7 +160,6 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
|
|
||||||
public void initViews(View rootView) {
|
public void initViews(View rootView) {
|
||||||
this.rootView = rootView;
|
this.rootView = rootView;
|
||||||
this.aspectRatioFrameLayout = rootView.findViewById(R.id.aspectRatioLayout);
|
|
||||||
this.surfaceView = rootView.findViewById(R.id.surfaceView);
|
this.surfaceView = rootView.findViewById(R.id.surfaceView);
|
||||||
this.surfaceForeground = rootView.findViewById(R.id.surfaceForeground);
|
this.surfaceForeground = rootView.findViewById(R.id.surfaceForeground);
|
||||||
this.loadingPanel = rootView.findViewById(R.id.loading_panel);
|
this.loadingPanel = rootView.findViewById(R.id.loading_panel);
|
||||||
|
@ -187,12 +183,10 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
setupSubtitleView(subtitleView, captionScale, captionStyle);
|
setupSubtitleView(subtitleView, captionScale, captionStyle);
|
||||||
|
|
||||||
this.resizeView = rootView.findViewById(R.id.resizeTextView);
|
this.resizeView = rootView.findViewById(R.id.resizeTextView);
|
||||||
resizeView.setText(PlayerHelper.resizeTypeOf(context, aspectRatioFrameLayout.getResizeMode()));
|
resizeView.setText(PlayerHelper.resizeTypeOf(context, getSurfaceView().getResizeMode()));
|
||||||
|
|
||||||
this.captionTextView = rootView.findViewById(R.id.captionTextView);
|
this.captionTextView = rootView.findViewById(R.id.captionTextView);
|
||||||
|
|
||||||
//this.aspectRatioFrameLayout.setAspectRatio(16.0f / 9.0f);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
|
||||||
playbackSeekBar.getThumb().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
|
playbackSeekBar.getThumb().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
|
||||||
this.playbackSeekBar.getProgressDrawable().setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY);
|
this.playbackSeekBar.getProgressDrawable().setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY);
|
||||||
|
@ -501,7 +495,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "onVideoSizeChanged() called with: width / height = [" + width + " / " + height + " = " + (((float) width) / height) + "], unappliedRotationDegrees = [" + unappliedRotationDegrees + "], pixelWidthHeightRatio = [" + pixelWidthHeightRatio + "]");
|
Log.d(TAG, "onVideoSizeChanged() called with: width / height = [" + width + " / " + height + " = " + (((float) width) / height) + "], unappliedRotationDegrees = [" + unappliedRotationDegrees + "], pixelWidthHeightRatio = [" + pixelWidthHeightRatio + "]");
|
||||||
}
|
}
|
||||||
aspectRatioFrameLayout.setAspectRatio(((float) width) / height);
|
getSurfaceView().setAspectRatio(((float) width) / height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -715,15 +709,15 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
void onResizeClicked() {
|
void onResizeClicked() {
|
||||||
if (getAspectRatioFrameLayout() != null) {
|
if (getSurfaceView() != null) {
|
||||||
final int currentResizeMode = getAspectRatioFrameLayout().getResizeMode();
|
final int currentResizeMode = getSurfaceView().getResizeMode();
|
||||||
final int newResizeMode = nextResizeMode(currentResizeMode);
|
final int newResizeMode = nextResizeMode(currentResizeMode);
|
||||||
setResizeMode(newResizeMode);
|
setResizeMode(newResizeMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setResizeMode(@AspectRatioFrameLayout.ResizeMode final int resizeMode) {
|
protected void setResizeMode(@AspectRatioFrameLayout.ResizeMode final int resizeMode) {
|
||||||
getAspectRatioFrameLayout().setResizeMode(resizeMode);
|
getSurfaceView().setResizeMode(resizeMode);
|
||||||
getResizeView().setText(PlayerHelper.resizeTypeOf(context, resizeMode));
|
getResizeView().setText(PlayerHelper.resizeTypeOf(context, resizeMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,11 +888,7 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
return resolver.getPlaybackQuality();
|
return resolver.getPlaybackQuality();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AspectRatioFrameLayout getAspectRatioFrameLayout() {
|
public ExpandableSurfaceView getSurfaceView() {
|
||||||
return aspectRatioFrameLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SurfaceView getSurfaceView() {
|
|
||||||
return surfaceView;
|
return surfaceView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,6 +959,10 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
return qualityPopupMenu;
|
return qualityPopupMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TextView getPlaybackSpeedTextView() {
|
||||||
|
return playbackSpeedTextView;
|
||||||
|
}
|
||||||
|
|
||||||
public PopupMenu getPlaybackSpeedPopupMenu() {
|
public PopupMenu getPlaybackSpeedPopupMenu() {
|
||||||
return playbackSpeedPopupMenu;
|
return playbackSpeedPopupMenu;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.text.CaptionStyleCompat;
|
import com.google.android.exoplayer2.text.CaptionStyleCompat;
|
||||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||||
|
@ -195,6 +196,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
setupElementsVisibility();
|
setupElementsVisibility();
|
||||||
|
setupElementsSize();
|
||||||
|
|
||||||
if (audioPlayerSelected()) {
|
if (audioPlayerSelected()) {
|
||||||
service.removeViewFromParent();
|
service.removeViewFromParent();
|
||||||
|
@ -280,11 +282,16 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method ensures that popup and main players have different look. We use one layout for both players and
|
||||||
|
* need to decide what to show and what to hide. Additional measuring should be done inside {@link #setupElementsSize}.
|
||||||
|
* {@link #setControlsSize} is used to adapt the UI to fullscreen mode, multiWindow, navBar, etc
|
||||||
|
*/
|
||||||
private void setupElementsVisibility() {
|
private void setupElementsVisibility() {
|
||||||
if (popupPlayerSelected()) {
|
if (popupPlayerSelected()) {
|
||||||
fullscreenButton.setVisibility(View.VISIBLE);
|
fullscreenButton.setVisibility(View.VISIBLE);
|
||||||
screenRotationButton.setVisibility(View.GONE);
|
screenRotationButton.setVisibility(View.GONE);
|
||||||
getRootView().findViewById(R.id.spaceBeforeControls).setVisibility(View.GONE);
|
getResizeView().setVisibility(View.GONE);
|
||||||
getRootView().findViewById(R.id.metadataView).setVisibility(View.GONE);
|
getRootView().findViewById(R.id.metadataView).setVisibility(View.GONE);
|
||||||
queueButton.setVisibility(View.GONE);
|
queueButton.setVisibility(View.GONE);
|
||||||
moreOptionsButton.setVisibility(View.GONE);
|
moreOptionsButton.setVisibility(View.GONE);
|
||||||
|
@ -297,14 +304,16 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
playWithKodi.setVisibility(View.GONE);
|
playWithKodi.setVisibility(View.GONE);
|
||||||
openInBrowser.setVisibility(View.GONE);
|
openInBrowser.setVisibility(View.GONE);
|
||||||
playerCloseButton.setVisibility(View.GONE);
|
playerCloseButton.setVisibility(View.GONE);
|
||||||
|
getTopControlsRoot().bringToFront();
|
||||||
|
getBottomControlsRoot().bringToFront();
|
||||||
} else {
|
} else {
|
||||||
fullscreenButton.setVisibility(View.GONE);
|
fullscreenButton.setVisibility(View.GONE);
|
||||||
setupScreenRotationButton(service.isLandscape());
|
setupScreenRotationButton(service.isLandscape());
|
||||||
getRootView().findViewById(R.id.spaceBeforeControls).setVisibility(View.VISIBLE);
|
getResizeView().setVisibility(View.VISIBLE);
|
||||||
getRootView().findViewById(R.id.metadataView).setVisibility(View.VISIBLE);
|
getRootView().findViewById(R.id.metadataView).setVisibility(View.VISIBLE);
|
||||||
moreOptionsButton.setVisibility(View.VISIBLE);
|
moreOptionsButton.setVisibility(View.VISIBLE);
|
||||||
getTopControlsRoot().setOrientation(LinearLayout.VERTICAL);
|
getTopControlsRoot().setOrientation(LinearLayout.VERTICAL);
|
||||||
primaryControls.getLayoutParams().width = secondaryControls.getLayoutParams().width;
|
primaryControls.getLayoutParams().width = LinearLayout.LayoutParams.MATCH_PARENT;
|
||||||
secondaryControls.setVisibility(View.GONE);
|
secondaryControls.setVisibility(View.GONE);
|
||||||
moreOptionsButton.setImageDrawable(service.getResources().getDrawable(
|
moreOptionsButton.setImageDrawable(service.getResources().getDrawable(
|
||||||
R.drawable.ic_expand_more_white_24dp));
|
R.drawable.ic_expand_more_white_24dp));
|
||||||
|
@ -325,6 +334,37 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
animateRotation(moreOptionsButton, DEFAULT_CONTROLS_DURATION, 0);
|
animateRotation(moreOptionsButton, DEFAULT_CONTROLS_DURATION, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes padding, size of elements based on player selected right now. Popup player has small padding in comparison with the
|
||||||
|
* main player
|
||||||
|
*/
|
||||||
|
private void setupElementsSize() {
|
||||||
|
if (popupPlayerSelected()) {
|
||||||
|
int controlsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_popup_controls_padding);
|
||||||
|
int buttonsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_popup_buttons_padding);
|
||||||
|
getTopControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0);
|
||||||
|
getBottomControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0);
|
||||||
|
getQualityTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
|
||||||
|
getPlaybackSpeedTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
|
||||||
|
getQualityTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
|
||||||
|
getCaptionTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
|
||||||
|
getQualityTextView().setMinimumWidth(0);
|
||||||
|
getPlaybackSpeedTextView().setMinimumWidth(0);
|
||||||
|
} else if (videoPlayerSelected()) {
|
||||||
|
int buttonsMinWidth = service.getResources().getDimensionPixelSize(R.dimen.player_main_buttons_min_width);
|
||||||
|
int playerTopPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_top_padding);
|
||||||
|
int controlsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_controls_padding);
|
||||||
|
int buttonsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_buttons_padding);
|
||||||
|
getTopControlsRoot().setPaddingRelative(controlsPadding, playerTopPadding, controlsPadding, 0);
|
||||||
|
getBottomControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0);
|
||||||
|
getQualityTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
|
||||||
|
getPlaybackSpeedTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
|
||||||
|
getQualityTextView().setMinimumWidth(buttonsMinWidth);
|
||||||
|
getPlaybackSpeedTextView().setMinimumWidth(buttonsMinWidth);
|
||||||
|
getCaptionTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initListeners() {
|
public void initListeners() {
|
||||||
super.initListeners();
|
super.initListeners();
|
||||||
|
@ -357,24 +397,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
service.getContentResolver().registerContentObserver(
|
service.getContentResolver().registerContentObserver(
|
||||||
Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), false,
|
Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), false,
|
||||||
settingsContentObserver);
|
settingsContentObserver);
|
||||||
|
getRootView().addOnLayoutChangeListener(this);
|
||||||
getRootView().addOnLayoutChangeListener((view, l, t, r, b, ol, ot, or, ob) -> {
|
|
||||||
if (l != ol || t != ot || r != or || b != ob) {
|
|
||||||
// Use smaller value to be consistent between screen orientations
|
|
||||||
// (and to make usage easier)
|
|
||||||
int width = r - l, height = b - t;
|
|
||||||
int min = Math.min(width, height);
|
|
||||||
maxGestureLength = (int) (min * MAX_GESTURE_LENGTH);
|
|
||||||
|
|
||||||
if (DEBUG) Log.d(TAG, "maxGestureLength = " + maxGestureLength);
|
|
||||||
|
|
||||||
volumeProgressBar.setMax(maxGestureLength);
|
|
||||||
brightnessProgressBar.setMax(maxGestureLength);
|
|
||||||
|
|
||||||
setInitialGestureValues();
|
|
||||||
queueLayout.getLayoutParams().height = min - queueLayout.getTop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AppCompatActivity getParentActivity() {
|
public AppCompatActivity getParentActivity() {
|
||||||
|
@ -553,19 +576,15 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
intent.putExtra(Constants.KEY_URL, getVideoUrl());
|
intent.putExtra(Constants.KEY_URL, getVideoUrl());
|
||||||
intent.putExtra(Constants.KEY_TITLE, getVideoTitle());
|
intent.putExtra(Constants.KEY_TITLE, getVideoTitle());
|
||||||
intent.putExtra(VideoDetailFragment.AUTO_PLAY, true);
|
intent.putExtra(VideoDetailFragment.AUTO_PLAY, true);
|
||||||
|
service.onDestroy();
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (fragmentListener == null) return;
|
if (fragmentListener == null) return;
|
||||||
|
|
||||||
isFullscreen = !isFullscreen;
|
isFullscreen = !isFullscreen;
|
||||||
setControlsSize();
|
setControlsSize();
|
||||||
fragmentListener.onFullscreenStateChanged(isInFullscreen());
|
fragmentListener.onFullscreenStateChanged(isInFullscreen());
|
||||||
// When user presses back button in landscape mode and in fullscreen and uses ZOOM mode
|
|
||||||
// a video can be larger than screen. Prevent it like this
|
|
||||||
if (getAspectRatioFrameLayout().getResizeMode() == AspectRatioFrameLayout.RESIZE_MODE_ZOOM
|
|
||||||
&& !isInFullscreen()
|
|
||||||
&& service.isLandscape())
|
|
||||||
onResizeClicked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isInFullscreen()) {
|
if (!isInFullscreen()) {
|
||||||
|
@ -741,18 +760,28 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLayoutChange(final View view, int left, int top, int right, int bottom,
|
public void onLayoutChange(final View view, int l, int t, int r, int b,
|
||||||
int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
int ol, int ot, int or, int ob) {
|
||||||
|
if (l != ol || t != ot || r != or || b != ob) {
|
||||||
|
// Use smaller value to be consistent between screen orientations
|
||||||
|
// (and to make usage easier)
|
||||||
|
int width = r - l, height = b - t;
|
||||||
|
int min = Math.min(width, height);
|
||||||
|
maxGestureLength = (int) (min * MAX_GESTURE_LENGTH);
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "maxGestureLength = " + maxGestureLength);
|
||||||
|
|
||||||
|
volumeProgressBar.setMax(maxGestureLength);
|
||||||
|
brightnessProgressBar.setMax(maxGestureLength);
|
||||||
|
|
||||||
|
setInitialGestureValues();
|
||||||
|
queueLayout.getLayoutParams().height = min - queueLayout.getTop();
|
||||||
|
|
||||||
if (popupPlayerSelected()) {
|
if (popupPlayerSelected()) {
|
||||||
float widthDp = Math.abs(right - left) / service.getResources().getDisplayMetrics().density;
|
float widthDp = Math.abs(r - l) / service.getResources().getDisplayMetrics().density;
|
||||||
final int visibility = widthDp > MINIMUM_SHOW_EXTRA_WIDTH_DP ? View.VISIBLE : View.GONE;
|
final int visibility = widthDp > MINIMUM_SHOW_EXTRA_WIDTH_DP ? View.VISIBLE : View.GONE;
|
||||||
secondaryControls.setVisibility(visibility);
|
secondaryControls.setVisibility(visibility);
|
||||||
} else if (videoPlayerSelected()
|
}
|
||||||
&& !isInFullscreen()
|
|
||||||
&& getAspectRatioFrameLayout().getMeasuredHeight() > service.getResources().getDisplayMetrics().heightPixels * 0.8) {
|
|
||||||
// Resize mode is ZOOM probably. In this mode video will grow down and it will be weird.
|
|
||||||
// So let's open it in fullscreen
|
|
||||||
toggleFullscreen();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,6 +810,11 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void restoreResizeMode() {
|
||||||
|
setResizeMode(defaultPreferences.getInt(
|
||||||
|
service.getString(R.string.last_resize_mode), AspectRatioFrameLayout.RESIZE_MODE_FIT));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected VideoPlaybackResolver.QualityResolver getQualityResolver() {
|
protected VideoPlaybackResolver.QualityResolver getQualityResolver() {
|
||||||
return new VideoPlaybackResolver.QualityResolver() {
|
return new VideoPlaybackResolver.QualityResolver() {
|
||||||
|
@ -933,6 +967,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
intentFilter.addAction(ACTION_FAST_REWIND);
|
intentFilter.addAction(ACTION_FAST_REWIND);
|
||||||
intentFilter.addAction(ACTION_FAST_FORWARD);
|
intentFilter.addAction(ACTION_FAST_FORWARD);
|
||||||
|
|
||||||
|
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
|
||||||
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
|
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
|
||||||
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||||
|
|
||||||
|
@ -969,6 +1004,9 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
case ACTION_REPEAT:
|
case ACTION_REPEAT:
|
||||||
onRepeatClicked();
|
onRepeatClicked();
|
||||||
break;
|
break;
|
||||||
|
case Intent.ACTION_CONFIGURATION_CHANGED:
|
||||||
|
setControlsSize();
|
||||||
|
break;
|
||||||
case Intent.ACTION_SCREEN_ON:
|
case Intent.ACTION_SCREEN_ON:
|
||||||
shouldUpdateOnProgress = true;
|
shouldUpdateOnProgress = true;
|
||||||
// Interrupt playback only when screen turns on and user is watching video in fragment
|
// Interrupt playback only when screen turns on and user is watching video in fragment
|
||||||
|
@ -1054,6 +1092,10 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
return playerType == MainPlayer.PlayerType.POPUP;
|
return playerType == MainPlayer.PlayerType.POPUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPlayerStopped() {
|
||||||
|
return getPlayer() == null || getPlayer().getPlaybackState() == SimpleExoPlayer.STATE_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
private int distanceFromCloseButton(MotionEvent popupMotionEvent) {
|
private int distanceFromCloseButton(MotionEvent popupMotionEvent) {
|
||||||
final int closeOverlayButtonX = closeOverlayButton.getLeft() + closeOverlayButton.getWidth() / 2;
|
final int closeOverlayButtonX = closeOverlayButton.getLeft() + closeOverlayButton.getWidth() / 2;
|
||||||
final int closeOverlayButtonY = closeOverlayButton.getTop() + closeOverlayButton.getHeight() / 2;
|
final int closeOverlayButtonY = closeOverlayButton.getTop() + closeOverlayButton.getHeight() / 2;
|
||||||
|
@ -1143,32 +1185,29 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
fragmentListener.hideSystemUIIfNeeded();
|
fragmentListener.hideSystemUIIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* This method measures width and height of controls visible on screen. It ensures that controls will be side-by-side with
|
* Measures width and height of controls visible on screen. It ensures that controls will be side-by-side with
|
||||||
* NavigationBar and notches but not under them. Tablets have only bottom NavigationBar
|
* NavigationBar and notches but not under them. Tablets have only bottom NavigationBar
|
||||||
* */
|
*/
|
||||||
private void setControlsSize() {
|
public void setControlsSize() {
|
||||||
Point size = new Point();
|
Point size = new Point();
|
||||||
Display display = getRootView().getDisplay();
|
Display display = getRootView().getDisplay();
|
||||||
if (display == null) return;
|
if (display == null || !videoPlayerSelected()) return;
|
||||||
// This method will give a correct size of a usable area of a window.
|
// This method will give a correct size of a usable area of a window.
|
||||||
// It doesn't include NavigationBar, notches, etc.
|
// It doesn't include NavigationBar, notches, etc.
|
||||||
display.getSize(size);
|
display.getSize(size);
|
||||||
|
|
||||||
int spaceBeforeTopControls = getRootView().findViewById(R.id.spaceBeforeControls).getWidth();
|
int width = isFullscreen ? size.x : ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
int widthForTopControls = isFullscreen ? size.x - spaceBeforeTopControls : ViewGroup.LayoutParams.MATCH_PARENT;
|
|
||||||
int widthForBottomControls = isFullscreen ? size.x : ViewGroup.LayoutParams.MATCH_PARENT;
|
|
||||||
int gravity = isFullscreen ? (display.getRotation() == Surface.ROTATION_90 ? Gravity.START : Gravity.END) : Gravity.TOP;
|
int gravity = isFullscreen ? (display.getRotation() == Surface.ROTATION_90 ? Gravity.START : Gravity.END) : Gravity.TOP;
|
||||||
|
|
||||||
primaryControls.getLayoutParams().width = widthForTopControls;
|
getTopControlsRoot().getLayoutParams().width = width;
|
||||||
((LinearLayout.LayoutParams) primaryControls.getLayoutParams()).gravity = gravity;
|
RelativeLayout.LayoutParams topParams = ((RelativeLayout.LayoutParams) getTopControlsRoot().getLayoutParams());
|
||||||
primaryControls.requestLayout();
|
topParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
|
||||||
|
topParams.removeRule(RelativeLayout.ALIGN_PARENT_END);
|
||||||
|
topParams.addRule(gravity == Gravity.END ? RelativeLayout.ALIGN_PARENT_END : RelativeLayout.ALIGN_PARENT_START);
|
||||||
|
getTopControlsRoot().requestLayout();
|
||||||
|
|
||||||
secondaryControls.getLayoutParams().width = widthForTopControls;
|
getBottomControlsRoot().getLayoutParams().width = width;
|
||||||
((LinearLayout.LayoutParams) secondaryControls.getLayoutParams()).gravity = gravity;
|
|
||||||
secondaryControls.requestLayout();
|
|
||||||
|
|
||||||
getBottomControlsRoot().getLayoutParams().width = widthForBottomControls;
|
|
||||||
RelativeLayout.LayoutParams bottomParams = ((RelativeLayout.LayoutParams) getBottomControlsRoot().getLayoutParams());
|
RelativeLayout.LayoutParams bottomParams = ((RelativeLayout.LayoutParams) getBottomControlsRoot().getLayoutParams());
|
||||||
bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
|
bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
|
||||||
bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_END);
|
bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_END);
|
||||||
|
@ -1188,6 +1227,9 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
getRootView().findViewById(R.id.playbackWindowRoot).requestLayout();
|
getRootView().findViewById(R.id.playbackWindowRoot).requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return statusBar height that was found inside system resources or default value if no value was provided inside resources
|
||||||
|
*/
|
||||||
private int getStatusBarHeight() {
|
private int getStatusBarHeight() {
|
||||||
int statusBarHeight = 0;
|
int statusBarHeight = 0;
|
||||||
int resourceId = service.getResources().getIdentifier("status_bar_height_landscape", "dimen", "android");
|
int resourceId = service.getResources().getIdentifier("status_bar_height_landscape", "dimen", "android");
|
||||||
|
@ -1200,6 +1242,9 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
return statusBarHeight;
|
return statusBarHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if main player is attached to activity and activity inside multiWindow mode
|
||||||
|
*/
|
||||||
private boolean isInMultiWindow() {
|
private boolean isInMultiWindow() {
|
||||||
AppCompatActivity parent = getParentActivity();
|
AppCompatActivity parent = getParentActivity();
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && parent != null && parent.isInMultiWindowMode();
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && parent != null && parent.isInMultiWindowMode();
|
||||||
|
@ -1308,7 +1353,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
if (DEBUG) Log.d(TAG, "initPopup() called");
|
if (DEBUG) Log.d(TAG, "initPopup() called");
|
||||||
|
|
||||||
// Popup is already added to windowManager
|
// Popup is already added to windowManager
|
||||||
if (getRootView().getLayoutParams() instanceof WindowManager.LayoutParams) return;
|
if (isPopupHasParent()) return;
|
||||||
|
|
||||||
updateScreenSize();
|
updateScreenSize();
|
||||||
|
|
||||||
|
@ -1316,18 +1361,19 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
final float defaultSize = service.getResources().getDimension(R.dimen.popup_default_width);
|
final float defaultSize = service.getResources().getDimension(R.dimen.popup_default_width);
|
||||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(service);
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(service);
|
||||||
popupWidth = popupRememberSizeAndPos ? sharedPreferences.getFloat(POPUP_SAVED_WIDTH, defaultSize) : defaultSize;
|
popupWidth = popupRememberSizeAndPos ? sharedPreferences.getFloat(POPUP_SAVED_WIDTH, defaultSize) : defaultSize;
|
||||||
|
popupHeight = getMinimumVideoHeight(popupWidth);
|
||||||
final int layoutParamType = Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O ?
|
final int layoutParamType = Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O ?
|
||||||
WindowManager.LayoutParams.TYPE_PHONE :
|
WindowManager.LayoutParams.TYPE_PHONE :
|
||||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||||
|
|
||||||
popupLayoutParams = new WindowManager.LayoutParams(
|
popupLayoutParams = new WindowManager.LayoutParams(
|
||||||
(int) popupWidth, (int) getMinimumVideoHeight(popupWidth),
|
(int) popupWidth, (int) popupHeight,
|
||||||
layoutParamType,
|
layoutParamType,
|
||||||
IDLE_WINDOW_FLAGS,
|
IDLE_WINDOW_FLAGS,
|
||||||
PixelFormat.TRANSLUCENT);
|
PixelFormat.TRANSLUCENT);
|
||||||
popupLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
|
popupLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
|
||||||
popupLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
popupLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||||
|
getSurfaceView().setHeights((int) popupHeight, (int) popupHeight);
|
||||||
|
|
||||||
int centerX = (int) (screenWidth / 2f - popupWidth / 2f);
|
int centerX = (int) (screenWidth / 2f - popupWidth / 2f);
|
||||||
int centerY = (int) (screenHeight / 2f - popupHeight / 2f);
|
int centerY = (int) (screenHeight / 2f - popupHeight / 2f);
|
||||||
|
@ -1342,8 +1388,8 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
service.removeViewFromParent();
|
service.removeViewFromParent();
|
||||||
windowManager.addView(getRootView(), popupLayoutParams);
|
windowManager.addView(getRootView(), popupLayoutParams);
|
||||||
|
|
||||||
if (getAspectRatioFrameLayout().getResizeMode() == AspectRatioFrameLayout.RESIZE_MODE_ZOOM)
|
// Popup doesn't have aspectRatio selector, using FIT automatically
|
||||||
onResizeClicked();
|
setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("RtlHardcoded")
|
@SuppressLint("RtlHardcoded")
|
||||||
|
@ -1375,6 +1421,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initVideoPlayer() {
|
private void initVideoPlayer() {
|
||||||
|
restoreResizeMode();
|
||||||
getRootView().setLayoutParams(new FrameLayout.LayoutParams(
|
getRootView().setLayoutParams(new FrameLayout.LayoutParams(
|
||||||
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
|
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
|
||||||
}
|
}
|
||||||
|
@ -1471,6 +1518,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
popupLayoutParams.height = height;
|
popupLayoutParams.height = height;
|
||||||
popupWidth = width;
|
popupWidth = width;
|
||||||
popupHeight = height;
|
popupHeight = height;
|
||||||
|
getSurfaceView().setHeights((int) popupHeight, (int) popupHeight);
|
||||||
|
|
||||||
if (DEBUG) Log.d(TAG, "updatePopupSize() updated values: width = [" + width + "], height = [" + height + "]");
|
if (DEBUG) Log.d(TAG, "updatePopupSize() updated values: width = [" + width + "], height = [" + height + "]");
|
||||||
windowManager.updateViewLayout(getRootView(), popupLayoutParams);
|
windowManager.updateViewLayout(getRootView(), popupLayoutParams);
|
||||||
|
@ -1499,6 +1547,14 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
animateOverlayAndFinishService();
|
animateOverlayAndFinishService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removePopupFromView() {
|
||||||
|
boolean isCloseOverlayHasParent = closeOverlayView != null && closeOverlayView.getParent() != null;
|
||||||
|
if (isPopupHasParent())
|
||||||
|
windowManager.removeView(getRootView());
|
||||||
|
if (isCloseOverlayHasParent)
|
||||||
|
windowManager.removeView(closeOverlayView);
|
||||||
|
}
|
||||||
|
|
||||||
private void animateOverlayAndFinishService() {
|
private void animateOverlayAndFinishService() {
|
||||||
final int targetTranslationY = (int) (closeOverlayButton.getRootView().getHeight() - closeOverlayButton.getY());
|
final int targetTranslationY = (int) (closeOverlayButton.getRootView().getHeight() - closeOverlayButton.getY());
|
||||||
|
|
||||||
|
@ -1527,12 +1583,18 @@ public class VideoPlayerImpl extends VideoPlayer
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPopupHasParent() {
|
||||||
|
View root = getRootView();
|
||||||
|
return root != null && root.getLayoutParams() instanceof WindowManager.LayoutParams && root.getParent() != null;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Manipulations with listener
|
// Manipulations with listener
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void setFragmentListener(PlayerServiceEventListener listener) {
|
public void setFragmentListener(PlayerServiceEventListener listener) {
|
||||||
fragmentListener = listener;
|
fragmentListener = listener;
|
||||||
|
updateMetadata();
|
||||||
updatePlayback();
|
updatePlayback();
|
||||||
triggerProgressUpdate();
|
triggerProgressUpdate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ public class CustomBottomSheetBehavior extends BottomSheetBehavior {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean skippingInterception = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent event) {
|
public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent event) {
|
||||||
// Behavior of globalVisibleRect is different on different APIs.
|
// Behavior of globalVisibleRect is different on different APIs.
|
||||||
|
@ -24,24 +26,40 @@ public class CustomBottomSheetBehavior extends BottomSheetBehavior {
|
||||||
boolean visible;
|
boolean visible;
|
||||||
Rect rect = new Rect();
|
Rect rect = new Rect();
|
||||||
|
|
||||||
|
// Drop folowing when actions ends
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP)
|
||||||
|
skippingInterception = false;
|
||||||
|
|
||||||
|
// Found that user still swipping, continue folowing
|
||||||
|
if (skippingInterception) return false;
|
||||||
|
|
||||||
// Without overriding scrolling will not work in detail_content_root_layout
|
// Without overriding scrolling will not work in detail_content_root_layout
|
||||||
ViewGroup controls = child.findViewById(R.id.detail_content_root_layout);
|
ViewGroup controls = child.findViewById(R.id.detail_content_root_layout);
|
||||||
if (controls != null) {
|
if (controls != null) {
|
||||||
visible = controls.getGlobalVisibleRect(rect);
|
visible = controls.getGlobalVisibleRect(rect);
|
||||||
if (rect.contains((int) event.getX(), (int) event.getY()) && visible) return false;
|
if (rect.contains((int) event.getRawX(), (int) event.getRawY()) && visible) {
|
||||||
|
skippingInterception = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Without overriding scrolling will not work on relatedStreamsLayout
|
// Without overriding scrolling will not work on relatedStreamsLayout
|
||||||
ViewGroup relatedStreamsLayout = child.findViewById(R.id.relatedStreamsLayout);
|
ViewGroup relatedStreamsLayout = child.findViewById(R.id.relatedStreamsLayout);
|
||||||
if (relatedStreamsLayout != null) {
|
if (relatedStreamsLayout != null) {
|
||||||
visible = relatedStreamsLayout.getGlobalVisibleRect(rect);
|
visible = relatedStreamsLayout.getGlobalVisibleRect(rect);
|
||||||
if (rect.contains((int) event.getX(), (int) event.getY()) && visible) return false;
|
if (rect.contains((int) event.getRawX(), (int) event.getRawY()) && visible) {
|
||||||
|
skippingInterception = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewGroup playQueue = child.findViewById(R.id.playQueue);
|
ViewGroup playQueue = child.findViewById(R.id.playQueue);
|
||||||
if (playQueue != null) {
|
if (playQueue != null) {
|
||||||
visible = playQueue.getGlobalVisibleRect(rect);
|
visible = playQueue.getGlobalVisibleRect(rect);
|
||||||
if (rect.contains((int) event.getX(), (int) event.getY()) && visible) return false;
|
if (rect.contains((int) event.getRawX(), (int) event.getRawY()) && visible) {
|
||||||
|
skippingInterception = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onInterceptTouchEvent(parent, child, event);
|
return super.onInterceptTouchEvent(parent, child, event);
|
||||||
|
|
|
@ -59,7 +59,7 @@ public abstract class PlayQueue implements Serializable {
|
||||||
streams = new ArrayList<>();
|
streams = new ArrayList<>();
|
||||||
streams.addAll(startWith);
|
streams.addAll(startWith);
|
||||||
history = new ArrayList<>();
|
history = new ArrayList<>();
|
||||||
history.add(streams.get(index));
|
if (streams.size() > index) history.add(streams.get(index));
|
||||||
|
|
||||||
queueIndex = new AtomicInteger(index);
|
queueIndex = new AtomicInteger(index);
|
||||||
disposed = false;
|
disposed = false;
|
||||||
|
@ -305,8 +305,10 @@ public abstract class PlayQueue implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
history.remove(streams.remove(removeIndex));
|
history.remove(streams.remove(removeIndex));
|
||||||
|
if (streams.size() > queueIndex.get()) {
|
||||||
history.add(streams.get(queueIndex.get()));
|
history.add(streams.get(queueIndex.get()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves a queue item at the source index to the target index.
|
* Moves a queue item at the source index to the target index.
|
||||||
|
@ -379,7 +381,9 @@ public abstract class PlayQueue implements Serializable {
|
||||||
streams.add(0, streams.remove(newIndex));
|
streams.add(0, streams.remove(newIndex));
|
||||||
}
|
}
|
||||||
queueIndex.set(0);
|
queueIndex.set(0);
|
||||||
|
if (streams.size() > 0) {
|
||||||
history.add(streams.get(0));
|
history.add(streams.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
broadcast(new ReorderEvent(originIndex, queueIndex.get()));
|
broadcast(new ReorderEvent(originIndex, queueIndex.get()));
|
||||||
}
|
}
|
||||||
|
@ -407,7 +411,9 @@ public abstract class PlayQueue implements Serializable {
|
||||||
} else {
|
} else {
|
||||||
queueIndex.set(0);
|
queueIndex.set(0);
|
||||||
}
|
}
|
||||||
|
if (streams.size() > queueIndex.get()) {
|
||||||
history.add(streams.get(queueIndex.get()));
|
history.add(streams.get(queueIndex.get()));
|
||||||
|
}
|
||||||
|
|
||||||
broadcast(new ReorderEvent(originIndex, queueIndex.get()));
|
broadcast(new ReorderEvent(originIndex, queueIndex.get()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
package org.schabi.newpipe.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.*;
|
||||||
|
|
||||||
|
public class ExpandableSurfaceView extends SurfaceView {
|
||||||
|
private int resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT;
|
||||||
|
private int baseHeight = 0;
|
||||||
|
private int maxHeight = 0;
|
||||||
|
private float videoAspectRatio = 0f;
|
||||||
|
private float scaleX = 1.0f;
|
||||||
|
private float scaleY = 1.0f;
|
||||||
|
|
||||||
|
public ExpandableSurfaceView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
if (videoAspectRatio == 0f) return;
|
||||||
|
|
||||||
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
boolean verticalVideo = videoAspectRatio < 1;
|
||||||
|
// Use maxHeight only on non-fit resize mode and in vertical videos
|
||||||
|
int height = maxHeight != 0 && resizeMode != AspectRatioFrameLayout.RESIZE_MODE_FIT && verticalVideo ? maxHeight : baseHeight;
|
||||||
|
|
||||||
|
if (height == 0) return;
|
||||||
|
|
||||||
|
float viewAspectRatio = width / ((float) height);
|
||||||
|
float aspectDeformation = videoAspectRatio / viewAspectRatio - 1;
|
||||||
|
scaleX = 1.0f;
|
||||||
|
scaleY = 1.0f;
|
||||||
|
|
||||||
|
switch (resizeMode) {
|
||||||
|
case AspectRatioFrameLayout.RESIZE_MODE_FIT:
|
||||||
|
if (aspectDeformation > 0) {
|
||||||
|
height = (int) (width / videoAspectRatio);
|
||||||
|
} else {
|
||||||
|
width = (int) (height * videoAspectRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case RESIZE_MODE_ZOOM:
|
||||||
|
if (aspectDeformation < 0) {
|
||||||
|
scaleY = viewAspectRatio / videoAspectRatio;
|
||||||
|
} else {
|
||||||
|
scaleX = videoAspectRatio / viewAspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
||||||
|
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale view only in {@link #onLayout} to make transition for ZOOM mode as smooth as possible
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
|
setScaleX(scaleX);
|
||||||
|
setScaleY(scaleY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param base The height that will be used in every resize mode as a minimum height
|
||||||
|
* @param max The max height for vertical videos in non-FIT resize modes
|
||||||
|
*/
|
||||||
|
public void setHeights(int base, int max) {
|
||||||
|
if (baseHeight == base && maxHeight == max) return;
|
||||||
|
baseHeight = base;
|
||||||
|
maxHeight = max;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AspectRatioFrameLayout.ResizeMode
|
||||||
|
public void setResizeMode(int newResizeMode) {
|
||||||
|
if (resizeMode == newResizeMode) return;
|
||||||
|
|
||||||
|
resizeMode = newResizeMode;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AspectRatioFrameLayout.ResizeMode
|
||||||
|
public int getResizeMode() {
|
||||||
|
return resizeMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAspectRatio(float aspectRatio) {
|
||||||
|
if (videoAspectRatio == aspectRatio) return;
|
||||||
|
|
||||||
|
videoAspectRatio = aspectRatio;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,27 +8,18 @@
|
||||||
android:background="@color/black"
|
android:background="@color/black"
|
||||||
android:gravity="center">
|
android:gravity="center">
|
||||||
|
|
||||||
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout
|
<org.schabi.newpipe.views.ExpandableSurfaceView
|
||||||
android:id="@+id/aspectRatioLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:layout_gravity="center">
|
|
||||||
|
|
||||||
<SurfaceView
|
|
||||||
android:id="@+id/surfaceView"
|
android:id="@+id/surfaceView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center"/>
|
android:layout_centerHorizontal="true"/>
|
||||||
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/surfaceForeground"
|
android:id="@+id/surfaceForeground"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@android:color/black"/>
|
android:background="@android:color/black"
|
||||||
|
android:layout_alignBottom="@+id/surfaceView"/>
|
||||||
</com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
|
|
||||||
|
|
||||||
<com.google.android.exoplayer2.ui.SubtitleView
|
<com.google.android.exoplayer2.ui.SubtitleView
|
||||||
android:id="@+id/subtitleView"
|
android:id="@+id/subtitleView"
|
||||||
|
@ -147,12 +138,6 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
<!-- It will be hidden in popup -->
|
|
||||||
<Space
|
|
||||||
android:id="@+id/spaceBeforeControls"
|
|
||||||
android:layout_width="16dp"
|
|
||||||
android:layout_height="0dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/topControls"
|
android:id="@+id/topControls"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -160,24 +145,26 @@
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:paddingTop="4dp"
|
android:paddingTop="@dimen/player_main_top_padding"
|
||||||
android:layout_toEndOf="@id/spaceBeforeControls"
|
android:paddingStart="@dimen/player_main_controls_padding"
|
||||||
|
android:paddingEnd="@dimen/player_main_controls_padding"
|
||||||
android:baselineAligned="false">
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/primaryControls"
|
android:id="@+id/primaryControls"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="50dp"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:paddingBottom="7dp"
|
android:layout_marginBottom="7dp"
|
||||||
tools:ignore="RtlHardcoded">
|
tools:ignore="RtlHardcoded">
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/playerCloseButton"
|
android:id="@+id/playerCloseButton"
|
||||||
android:layout_width="36dp"
|
android:layout_width="36dp"
|
||||||
android:layout_height="36dp"
|
android:layout_height="36dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
@ -193,8 +180,8 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
android:paddingRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
tools:ignore="RtlHardcoded"
|
tools:ignore="RtlHardcoded"
|
||||||
android:layout_weight="1">
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
@ -235,11 +222,9 @@
|
||||||
android:id="@+id/qualityTextView"
|
android:id="@+id/qualityTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:minWidth="50dp"
|
|
||||||
android:text="720p"
|
android:text="720p"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
@ -251,11 +236,10 @@
|
||||||
android:id="@+id/playbackSpeed"
|
android:id="@+id/playbackSpeed"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:minHeight="35dp"
|
android:minHeight="35dp"
|
||||||
android:minWidth="40dp"
|
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
|
@ -266,7 +250,7 @@
|
||||||
android:id="@+id/queueButton"
|
android:id="@+id/queueButton"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
@ -280,8 +264,7 @@
|
||||||
android:id="@+id/moreOptionsButton"
|
android:id="@+id/moreOptionsButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="8dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
|
@ -304,7 +287,7 @@
|
||||||
android:id="@+id/resizeTextView"
|
android:id="@+id/resizeTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:minWidth="50dp"
|
android:minWidth="50dp"
|
||||||
|
@ -318,7 +301,7 @@
|
||||||
android:id="@+id/captionTextView"
|
android:id="@+id/captionTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:gravity="center|left"
|
android:gravity="center|left"
|
||||||
android:minHeight="35dp"
|
android:minHeight="35dp"
|
||||||
|
@ -341,7 +324,7 @@
|
||||||
android:id="@+id/playWithKodi"
|
android:id="@+id/playWithKodi"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
@ -355,7 +338,7 @@
|
||||||
android:id="@+id/openInBrowser"
|
android:id="@+id/openInBrowser"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
@ -369,8 +352,7 @@
|
||||||
android:id="@+id/share"
|
android:id="@+id/share"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
|
@ -387,9 +369,7 @@
|
||||||
android:id="@+id/fullScreenButton"
|
android:id="@+id/fullScreenButton"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_marginTop="2dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="2dp"
|
|
||||||
android:padding="6dp"
|
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
|
@ -413,9 +393,8 @@
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingBottom="6dp"
|
android:paddingLeft="@dimen/player_main_controls_padding"
|
||||||
android:paddingLeft="16dp"
|
android:paddingRight="@dimen/player_main_controls_padding">
|
||||||
android:paddingRight="16dp">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/playbackCurrentTime"
|
android:id="@+id/playbackCurrentTime"
|
||||||
|
@ -470,7 +449,7 @@
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_marginStart="4dp"
|
android:layout_marginStart="4dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
|
|
@ -633,7 +633,7 @@
|
||||||
android:layout_marginRight="2dp"
|
android:layout_marginRight="2dp"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:src="@drawable/ic_pause_white_24dp"
|
android:src="?attr/play"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
tools:ignore="ContentDescription,RtlHardcoded"/>
|
tools:ignore="ContentDescription,RtlHardcoded"/>
|
||||||
|
|
||||||
|
|
|
@ -8,27 +8,18 @@
|
||||||
android:background="@color/black"
|
android:background="@color/black"
|
||||||
android:gravity="center">
|
android:gravity="center">
|
||||||
|
|
||||||
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout
|
<org.schabi.newpipe.views.ExpandableSurfaceView
|
||||||
android:id="@+id/aspectRatioLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:layout_gravity="center">
|
|
||||||
|
|
||||||
<SurfaceView
|
|
||||||
android:id="@+id/surfaceView"
|
android:id="@+id/surfaceView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center"/>
|
android:layout_centerHorizontal="true"/>
|
||||||
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/surfaceForeground"
|
android:id="@+id/surfaceForeground"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@android:color/black"/>
|
android:background="@android:color/black"
|
||||||
|
android:layout_alignBottom="@+id/surfaceView"/>
|
||||||
</com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
|
|
||||||
|
|
||||||
<com.google.android.exoplayer2.ui.SubtitleView
|
<com.google.android.exoplayer2.ui.SubtitleView
|
||||||
android:id="@+id/subtitleView"
|
android:id="@+id/subtitleView"
|
||||||
|
@ -145,12 +136,6 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true">
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
<!-- It will be hidden in popup -->
|
|
||||||
<Space
|
|
||||||
android:id="@+id/spaceBeforeControls"
|
|
||||||
android:layout_width="16dp"
|
|
||||||
android:layout_height="0dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/topControls"
|
android:id="@+id/topControls"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -158,24 +143,26 @@
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:paddingTop="4dp"
|
android:paddingTop="@dimen/player_main_top_padding"
|
||||||
android:layout_toEndOf="@id/spaceBeforeControls"
|
android:paddingStart="@dimen/player_main_controls_padding"
|
||||||
|
android:paddingEnd="@dimen/player_main_controls_padding"
|
||||||
android:baselineAligned="false">
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/primaryControls"
|
android:id="@+id/primaryControls"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="50dp"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:paddingBottom="7dp"
|
android:layout_marginBottom="7dp"
|
||||||
tools:ignore="RtlHardcoded">
|
tools:ignore="RtlHardcoded">
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/playerCloseButton"
|
android:id="@+id/playerCloseButton"
|
||||||
android:layout_width="36dp"
|
android:layout_width="36dp"
|
||||||
android:layout_height="36dp"
|
android:layout_height="36dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
@ -191,8 +178,8 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
android:paddingRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
tools:ignore="RtlHardcoded"
|
tools:ignore="RtlHardcoded"
|
||||||
android:layout_weight="1">
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
@ -233,11 +220,9 @@
|
||||||
android:id="@+id/qualityTextView"
|
android:id="@+id/qualityTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:minWidth="50dp"
|
|
||||||
android:text="720p"
|
android:text="720p"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
@ -249,11 +234,10 @@
|
||||||
android:id="@+id/playbackSpeed"
|
android:id="@+id/playbackSpeed"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:minHeight="35dp"
|
android:minHeight="35dp"
|
||||||
android:minWidth="40dp"
|
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
|
@ -264,7 +248,7 @@
|
||||||
android:id="@+id/queueButton"
|
android:id="@+id/queueButton"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
@ -278,8 +262,7 @@
|
||||||
android:id="@+id/moreOptionsButton"
|
android:id="@+id/moreOptionsButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="8dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
|
@ -302,7 +285,7 @@
|
||||||
android:id="@+id/resizeTextView"
|
android:id="@+id/resizeTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:minWidth="50dp"
|
android:minWidth="50dp"
|
||||||
|
@ -316,7 +299,7 @@
|
||||||
android:id="@+id/captionTextView"
|
android:id="@+id/captionTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:gravity="center|left"
|
android:gravity="center|left"
|
||||||
android:minHeight="35dp"
|
android:minHeight="35dp"
|
||||||
|
@ -339,7 +322,7 @@
|
||||||
android:id="@+id/playWithKodi"
|
android:id="@+id/playWithKodi"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
@ -353,7 +336,7 @@
|
||||||
android:id="@+id/openInBrowser"
|
android:id="@+id/openInBrowser"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
@ -367,8 +350,7 @@
|
||||||
android:id="@+id/share"
|
android:id="@+id/share"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="35dp"
|
android:layout_height="35dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
|
@ -385,9 +367,7 @@
|
||||||
android:id="@+id/fullScreenButton"
|
android:id="@+id/fullScreenButton"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_marginTop="2dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:layout_marginEnd="2dp"
|
|
||||||
android:padding="6dp"
|
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
|
@ -411,9 +391,8 @@
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingBottom="6dp"
|
android:paddingLeft="@dimen/player_main_controls_padding"
|
||||||
android:paddingLeft="16dp"
|
android:paddingRight="@dimen/player_main_controls_padding">
|
||||||
android:paddingRight="16dp">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/playbackCurrentTime"
|
android:id="@+id/playbackCurrentTime"
|
||||||
|
@ -468,7 +447,7 @@
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_marginStart="4dp"
|
android:layout_marginStart="4dp"
|
||||||
android:padding="6dp"
|
android:padding="@dimen/player_main_buttons_padding"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
|
|
@ -623,7 +623,7 @@
|
||||||
android:layout_marginRight="2dp"
|
android:layout_marginRight="2dp"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:src="@drawable/ic_pause_white_24dp"
|
android:src="?attr/play"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
tools:ignore="ContentDescription,RtlHardcoded"/>
|
tools:ignore="ContentDescription,RtlHardcoded"/>
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,15 @@
|
||||||
<dimen name="video_item_search_duration_margin">2dp</dimen>
|
<dimen name="video_item_search_duration_margin">2dp</dimen>
|
||||||
<dimen name="video_item_detail_description_to_details_margin">4dp</dimen>
|
<dimen name="video_item_detail_description_to_details_margin">4dp</dimen>
|
||||||
<dimen name="software_component_item_padding">8dp</dimen>
|
<dimen name="software_component_item_padding">8dp</dimen>
|
||||||
|
|
||||||
|
<!-- Players padding & sizes -->
|
||||||
|
<dimen name="player_main_controls_padding">16dp</dimen>
|
||||||
|
<dimen name="player_popup_controls_padding">6dp</dimen>
|
||||||
|
<dimen name="player_main_top_padding">4dp</dimen>
|
||||||
|
<dimen name="player_main_buttons_padding">6dp</dimen>
|
||||||
|
<dimen name="player_popup_buttons_padding">1dp</dimen>
|
||||||
|
<dimen name="player_main_buttons_min_width">40dp</dimen>
|
||||||
|
|
||||||
<!-- Miscellaneous -->
|
<!-- Miscellaneous -->
|
||||||
<dimen name="popup_default_width">180dp</dimen>
|
<dimen name="popup_default_width">180dp</dimen>
|
||||||
<dimen name="popup_minimum_width">150dp</dimen>
|
<dimen name="popup_minimum_width">150dp</dimen>
|
||||||
|
|
Loading…
Reference in a new issue