我目前正在制作视频直播应用,我希望实现像Youtube这样的用户界面。
注意:我不需要Youtube视频。我想从我的服务器流式传输视频。
我做了一些研究,发现了这个库:Draggablepanel
并尝试添加到我的项目中。这是我的片段布局的代码:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#000000"
tools:context=".VLCActivity">
<com.github.pedrovgs.DraggableView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:draggable_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/draggable_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
draggable_view:top_view_id="@+id/surface"
draggable_view:bottom_view_id="@+id/bottom"
draggable_view:top_view_x_scale_factor="@dimen/x_scale_factor"
draggable_view:top_view_y_scale_factor="@dimen/y_scale_factor"
draggable_view:top_view_height="@dimen/top_fragment_height"
draggable_view:top_view_margin_right="@dimen/top_fragment_margin"
draggable_view:top_view_margin_bottom="@dimen/top_fragment_margin"
draggable_view:enable_minimized_horizontal_alpha_effect="false"
draggable_view:top_view_resize="true"
android:background="@android:color/black">
<SurfaceView
android:id="@+id/surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
<FrameLayout
android:id="@+id/bottom"
android:layout_width="match_parent"
android:layout_height="0dp">
</FrameLayout>
<ProgressBar
android:id="@+id/pb"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</com.github.pedrovgs.DraggableView>
<include
android:id="@+id/include"
layout="@layout/actionbar_video_chat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"></include>
和Java代码:
public class VLCFragment extends Fragment implements IVLCVout.Callback {
private SurfaceView mSurface;
private SurfaceHolder holder;
private LibVLC libvlc;
private MediaPlayer mMediaPlayer = null;
private int mVideoWidth;
private int mVideoHeight;
public int mHeight;
public int mWidth;
ProgressBar pb;
Toolbar vToolbar;
ImageView back,close;
DraggableView draggableView;
private String mFilePath ="rtmp://184.72.239.149/vod/mp4:bigbuckbunny_1500.mp4";
public VLCFragment() {
// Required empty public constructor
}
public static VLCFragment newInstance()
{
return new VLCFragment();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
DisplayMetrics displayMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
mHeight = displayMetrics.heightPixels;
mWidth = displayMetrics.widthPixels;
}
@Override
public void onStart()
{
super.onStart();
createPlayer(mFilePath);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_vlc, container, false);
vToolbar = view.findViewById(R.id.videotoolbar);
draggableView = view.findViewById(R.id.draggable_view);
mSurface = view.findViewById(R.id.surface);
holder = mSurface.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
pb = view.findViewById(R.id.pb);
pb.setVisibility(View.VISIBLE);
back = view.findViewById(R.id.room_back);
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
draggableView.minimize();
//getActivity().onBackPressed();
}
});
return view;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
draggableView.maximize();
}
/**
* Used to set size for SurfaceView
*
* @param width
* @param height
*/
private void setSize(int width, int height) {
mVideoWidth = width;
mVideoHeight = height;
if (mVideoWidth * mVideoHeight <= 1)
return;
if (holder == null || mSurface == null)
return;
int w = getActivity().getWindow().getDecorView().getWidth();
int h = getActivity().getWindow().getDecorView().getHeight();
boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (w > h && isPortrait || w < h && !isPortrait) {
int i = w;
w = h;
h = i;
}
float videoAR = (float) mVideoWidth / (float) mVideoHeight;
float screenAR = (float) w / (float) h;
if (screenAR < videoAR)
h = (int) (w / videoAR);
else
w = (int) (h * videoAR);
holder.setFixedSize(mVideoWidth, mVideoHeight);
ViewGroup.LayoutParams lp = mSurface.getLayoutParams();
lp.width = w;
lp.height = h;
mSurface.setLayoutParams(lp);
mSurface.invalidate();
pb.setVisibility(View.INVISIBLE);
}
/**
* Creates MediaPlayer and plays video
*
* @param media
*/
private void createPlayer(String media)
{
//releasePlayer();
try {
if (media.length() > 0) {
Toast toast = Toast.makeText(getActivity(), media, Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
0);
toast.show();
}
// Create LibVLC
// TODO: make this more robust, and sync with audio demo
ArrayList<String> options = new ArrayList<String>();
//options.add("--subsdec-encoding <encoding>");
options.add("--aout=opensles");
options.add("--audio-time-stretch"); // time stretching
options.add("-vvv"); // verbosity
libvlc = new LibVLC(getActivity(), options);
holder.setKeepScreenOn(true);
// Creating media player
mMediaPlayer = new MediaPlayer(libvlc);
mMediaPlayer.setEventListener(mPlayerListener);
// Seting up video output
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.setVideoView(mSurface);
vout.setWindowSize(mWidth,mHeight);
vout.addCallback(this);
vout.attachViews();
Media m = new Media(libvlc, Uri.parse(media));
mMediaPlayer.setMedia(m);
mMediaPlayer.play();
} catch (Exception e) {
pb.setVisibility(View.INVISIBLE);
Toast.makeText(getActivity(), "Error in creating player!", Toast
.LENGTH_LONG).show();
}
}
private void releasePlayer()
{
if (libvlc == null)
return;
mMediaPlayer.stop();
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.removeCallback(this);
vout.detachViews();
holder = null;
libvlc.release();
libvlc = null;
mVideoWidth = 0;
mVideoHeight = 0;
}
/**
* Registering callbacks
*/
private MediaPlayer.EventListener mPlayerListener = new MyPlayerListener(this);
@Override
public void onNewLayout(IVLCVout vout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) {
if (width * height == 0)
return;
// store video size
mVideoWidth = width;
mVideoHeight = height;
setSize(mVideoWidth, mVideoHeight);
}
@Override
public void onSurfacesCreated(IVLCVout vout) {
}
@Override
public void onSurfacesDestroyed(IVLCVout vout) {
}
@Override
public void onHardwareAccelerationError(IVLCVout vlcVout) {
//Log.e(TAG, "Error with hardware acceleration");
this.releasePlayer();
Toast.makeText(getActivity(), "Error with hardware acceleration", Toast.LENGTH_LONG).show();
}
private static class MyPlayerListener implements MediaPlayer.EventListener {
private WeakReference<VLCFragment> mOwner;
public MyPlayerListener(VLCFragment owner) {
mOwner = new WeakReference<VLCFragment>(owner);
}
@Override
public void onEvent(MediaPlayer.Event event) {
VLCFragment player = mOwner.get();
switch (event.type) {
case MediaPlayer.Event.EndReached:
// Log.d(TAG, "MediaPlayerEndReached");
player.releasePlayer();
break;
case MediaPlayer.Event.Playing:
case MediaPlayer.Event.Paused:
case MediaPlayer.Event.Stopped:
default:
break;
}
}
}
@Override
public void onResume()
{
super.onResume();
draggableView.maximize();
}
@Override
public void onPause()
{
super.onPause();
releasePlayer();
}
@Override
public void onDetach()
{
super.onDetach();
releasePlayer();
}
private void startVideo() {
if (!mMediaPlayer.isPlaying()) {
mMediaPlayer.play();
}
}
private void pauseVideo() {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
}
}
}
我有一个名为GlobalScreen的活动,它包含一个tabview,每个标签都是一个片段,显示为here。我有一个名为Roomsfragment的片段,里面有一个recyclerview。单击某个项目应该转到包含VLC播放器的片段以流式传输视频。通过这个当前的实现,我能够实现this。
到目前为止,我尝试了什么:
首先尝试在android oreo中引入Pictureinpicture模式。但该方法似乎在Android N及以下版本中无效。
接下来尝试在没有draggableview库的情况下通过在Roomsfragment xml中添加一个名为preview的framelayout并在开始时隐藏它来实现此目的。对于视频屏幕,我首先创建了一个活动,并在那里添加了一个片段来播放视频。我使用startactivityforresult()方法开始了这个活动。当我按下视频播放器活动的后退按钮时,我会回到上一个屏幕,在onActivityResult()中,我会使预览布局可见,并用相同的视频片段替换它。但是初始化vlc播放器有一个延迟,所以决定改变它以获得更好的用户体验。
答案 0 :(得分:-2)
遵循此github link ...猜测。这就是您要寻找的...
完整的YouTuDraggingView
类如下:
public class YouTuDraggingView extends RelativeLayout implements View.OnClickListener {
static final int STATUS_MAX = 1;
static final int STATUS_MIN = 0;
static final int STATUS_DRAG = 2;
interface Callback {
void onVideoViewHide();
void videoSize(int width, int height);
void onIconClick(IconType iconType);
void status(int status);
}
enum IconType {
PAUSE,
PLAY,
CLOSE
}
Callback mCallback;
IconType statusType = IconType.PLAY;
// Draggable view and details below View
DispatchLayout mBackgroundView;
View mDetailView;
View titleLayout;
View pauseIv;
View closeIv;
View pauseLayout;
View closeLayout;
View mTopView;
Activity mActivity;
MarginViewWrapper mBackgroundViewWrapper;
MarginViewWrapper mTopViewWrapper;
MarginViewWrapper titleWrapper;
MarginViewWrapper pauseIvWrapper;
MarginViewWrapper closeIvWrapper;
float mRangeScrollY;
float mRangeNodeScrollY;
//Current ratio
float nowStateScale;
float MIN_RATIO_HEIGHT_NODE = 0.40f;
static float MIN_RATIO_HEIGHT = 0.30f;
float MIN_RATIO_WIDTH = 0.95f;
static final float VIDEO_RATIO = 16f / 9f;
int finalVideoLeftRightOffset;
//Original width of the video layout
float mTopViewOriginalWidth;
//The original height of the video layout
float mTopOriginalHeight;
float mBackgroundOriginalHeight;
//Bottom distance
float bottomHeight = DensityUtil.dip2px(getContext(), 80);
long rangeDuration = 350;
long dismissDuration = 100;
boolean activityFullscreen = false;
OrientationEventListener mOrientationListener;
private int isRotate;//0 Representing direction lock,1 Represents no direction lock
private long orientationListenerDelayTime = 0;
static boolean isPortraitToLandscape = false;
static boolean isLandscapeToPortrait = false;
public YouTuDraggingView(Context context) {
this(context, null);
}
public YouTuDraggingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public YouTuDraggingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mActivity = getActivityFromView(this);
activityFullscreen = (mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN;
addView(LayoutInflater.from(getContext()).inflate(R.layout.youtu_dispatch, null), 0);
mBackgroundView = findViewById(R.id.backgroundView);
mTopView = findViewById(R.id.videoView);
View videoParentLayout = findViewById(R.id.videoParentLayout);
mDetailView = findViewById(R.id.scroll_view);
titleLayout = findViewById(R.id.titleLayout);
pauseLayout = findViewById(R.id.pauseLayout);
closeLayout = findViewById(R.id.closeLayout);
pauseIv = findViewById(R.id.pauseIv);
closeIv = findViewById(R.id.closeIv);
pauseIv.setBackgroundResource(R.drawable.pause);
mBackgroundView.setParentView(this);
setBackgroundColor(Color.BLACK);
mBackgroundView.setOnClickListener(this);
pauseLayout.setOnClickListener(this);
closeLayout.setOnClickListener(this);
videoParentLayout.setOnClickListener(this);
//Initialize the wrapper class
mBackgroundViewWrapper = new MarginViewWrapper(mBackgroundView);
mTopViewWrapper = new MarginViewWrapper(mTopView);
titleWrapper = new MarginViewWrapper(titleLayout);
pauseIvWrapper = new MarginViewWrapper(pauseLayout);
closeIvWrapper = new MarginViewWrapper(closeLayout);
initData();
}
private void initOrientationListener() {
if (mOrientationListener != null) {
return;
}
mOrientationListener = new OrientationEventListener(mActivity) {
@Override
public void onOrientationChanged(int orientation) {
try {
//Get open system
isRotate = Settings.System.getInt(getContext().getContentResolver(), Settings.System.ACCELEROMETER_ROTATION);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
if (isRotate == 0) return;
if ((orientation >= 300 || orientation <= 30) && System.currentTimeMillis() - orientationListenerDelayTime > 1000) {
if (isLandscapeToPortrait) {
isLandscapeToPortrait = false;
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
orientationListenerDelayTime = System.currentTimeMillis();
} else if (orientation >= 260 && orientation <= 280
&& System.currentTimeMillis() - orientationListenerDelayTime > 1000) {
if (isPortraitToLandscape) {
isPortraitToLandscape = false;
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
orientationListenerDelayTime = System.currentTimeMillis();
} else if (orientation >= 70 && orientation <= 90
&& System.currentTimeMillis() - orientationListenerDelayTime > 1000) {
if (isPortraitToLandscape) {
isPortraitToLandscape = false;
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
orientationListenerDelayTime = System.currentTimeMillis();
}
}
};
if (mOrientationListener.canDetectOrientation()) {
mOrientationListener.enable();
} else {
mOrientationListener.disable();
}
}
private void initData() {
initOrientationListener();
//Current zoom ratio
nowStateScale = 1f;
if (isLandscape()) {
mTopViewOriginalWidth = DensityUtil.getScreenW(getContext());
if (activityFullscreen) {
mTopOriginalHeight = DensityUtil.getScreenH(getContext());
} else {
mTopOriginalHeight = DensityUtil.getScreenH(getContext()) - DensityUtil.getStatusBarH(getContext());
}
MIN_RATIO_HEIGHT_NODE = 0.35f;
MIN_RATIO_HEIGHT = 0.25f;
mDetailView.setVisibility(View.GONE);
} else {
mTopViewOriginalWidth = mBackgroundView.getContext().getResources().getDisplayMetrics().widthPixels;
mTopOriginalHeight = (mTopViewOriginalWidth / VIDEO_RATIO);
mDetailView.setVisibility(View.VISIBLE);
}
mTopViewWrapper.setHeight(mTopOriginalHeight);
mTopViewWrapper.setWidth(mTopViewOriginalWidth);
if (MIN_RATIO_HEIGHT_NODE < MIN_RATIO_HEIGHT) {
throw new RuntimeException("MIN_RATIO_HEIGHT_NODE can't smaller than MIN_RATIO_HEIGHT_NODE");
}
}
public Boolean isLandscape() {
return getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
resetRangeAndSize();
}
public void resetRangeAndSize() {
mTopViewOriginalWidth = DensityUtil.getScreenW(getContext());
if (isLandscape()) {
mTopOriginalHeight = activityFullscreen ? DensityUtil.getScreenH(getContext()) : DensityUtil.getScreenOriginH(getContext());
MIN_RATIO_HEIGHT_NODE = 0.35f;
MIN_RATIO_HEIGHT = 0.25f;
mDetailView.setVisibility(View.GONE);
} else {
mTopOriginalHeight = (mTopViewOriginalWidth / VIDEO_RATIO);
MIN_RATIO_HEIGHT_NODE = 0.45f;
MIN_RATIO_HEIGHT = 0.35f;
}
float height = activityFullscreen ? DensityUtil.getScreenH(getContext()) : DensityUtil.getScreenOriginH(getContext());
mRangeScrollY = height - MIN_RATIO_HEIGHT * mTopOriginalHeight - bottomHeight;
mRangeNodeScrollY = height - MIN_RATIO_HEIGHT_NODE * mTopOriginalHeight - bottomHeight;
mBackgroundOriginalHeight = height;
finalVideoLeftRightOffset = (int) ((mTopViewOriginalWidth - mTopViewOriginalWidth * MIN_RATIO_WIDTH) / 2);
}
void notifyStatus() {
if (statusType == IconType.PLAY) {
statusType = IconType.PAUSE;
pauseIv.setBackgroundResource(R.drawable.play);
mCallback.onIconClick(IconType.PAUSE);
} else {
statusType = IconType.PLAY;
pauseIv.setBackgroundResource(R.drawable.pause);
mCallback.onIconClick(IconType.PLAY);
}
}
void changeStatus(IconType iconType) {
if (iconType == IconType.PLAY) {
statusType = IconType.PAUSE;
pauseIv.setBackgroundResource(R.drawable.play);
} else if (iconType == IconType.PAUSE) {
statusType = IconType.PLAY;
pauseIv.setBackgroundResource(R.drawable.pause);
}
}
void updateDismissView(int m) {
ViewGroup.LayoutParams params = getLayoutParams();
params.width = -1;
params.height = -1;
setLayoutParams(params);
float fullY = mRangeScrollY + mTopOriginalHeight * MIN_RATIO_HEIGHT;
float offset = mRangeScrollY;
if (m < fullY && m > mRangeScrollY) {
offset = mRangeScrollY + (m - mRangeScrollY);
}
if (m >= fullY) {
offset = fullY;
}
if (m < mRangeScrollY) {
offset = mRangeScrollY;
}
float alphaPercent = (m - mRangeScrollY) / (fullY - mRangeScrollY);
mBackgroundViewWrapper.setMarginTop(Math.round(offset));
mBackgroundViewWrapper.setMarginBottom(Math.round(bottomHeight - (m - mRangeScrollY)));
mBackgroundView.setAlpha((1 - alphaPercent));
}
void updateVideoView(int m) {
if (mBackgroundViewWrapper.getMarginTop() > 0) {
mCallback.status(STATUS_DRAG);
}
//If the current state is minimized,First set our layout width to MATCH_PARENT
if (nowStateScale == MIN_RATIO_HEIGHT) {
ViewGroup.LayoutParams params = getLayoutParams();
params.width = -1;
params.height = -1;
setLayoutParams(params);
}
//marginTop The maximum value is allScrollY, the minimum is 0
if (m > mRangeScrollY)
m = (int) mRangeScrollY;
if (m < 0)
m = 0;
//The percentage of the video view height 100% - 0%
float marginPercent = (mRangeScrollY - m) / mRangeScrollY;
float nodeMarginPercent = (mRangeNodeScrollY - m) / mRangeNodeScrollY;
float videoNodeWidthPercent = MIN_RATIO_WIDTH + (1f - MIN_RATIO_WIDTH) * nodeMarginPercent;
float videoNodeHeightPercent = MIN_RATIO_HEIGHT_NODE + (1f - MIN_RATIO_HEIGHT_NODE) * nodeMarginPercent;
float detailPercent = m / mRangeNodeScrollY;
int videoLeftRightOffset = (int) ((mTopViewOriginalWidth - mTopViewOriginalWidth * videoNodeWidthPercent) / 2);
int detailBottomOffset = Math.round(bottomHeight * detailPercent);
//Cannot exceed the bottom spacing
if (detailBottomOffset >= bottomHeight) {
detailBottomOffset = Math.round(bottomHeight);
}
if (m >= mRangeNodeScrollY) {
mDetailView.setVisibility(View.GONE);
float alphaPercent = (m - mRangeNodeScrollY) / (mRangeScrollY - mRangeNodeScrollY);
//Background moving height
float offHeight = Math.round(mBackgroundOriginalHeight * MIN_RATIO_HEIGHT_NODE - (m - mRangeNodeScrollY));
//Video View's moving height
float offHeight2 = Math.round(mTopOriginalHeight * MIN_RATIO_HEIGHT_NODE - (m - mRangeNodeScrollY));
mBackgroundViewWrapper.setMarginTop(m);
mBackgroundViewWrapper.setHeight(offHeight);
float videoRightOffset = (m - mRangeNodeScrollY) / (mRangeScrollY - mRangeNodeScrollY) * mTopViewOriginalWidth * MIN_RATIO_WIDTH * 2 / 3;
float topViewWidth = Math.round(mTopViewOriginalWidth * MIN_RATIO_WIDTH - videoRightOffset);
mTopViewWrapper.setHeight(offHeight2);
mTopViewWrapper.setWidth(topViewWidth);
//The width of the slide when the head reaches the minimum width
float pieceWidth = mTopViewOriginalWidth * MIN_RATIO_WIDTH / 3;
float minWidthOffset = topViewWidth - pieceWidth;
float imageLayoutWidth = pieceWidth / 2;
//Control position at minimum layout
float titleWidth = pieceWidth - minWidthOffset;
float pauseWidth = imageLayoutWidth;
float closeWidth = imageLayoutWidth;
float pauseLeftOffset = pieceWidth - minWidthOffset;
float closeLeftOffset = pieceWidth + pieceWidth / 2 - minWidthOffset;
if (minWidthOffset >= pieceWidth) {
titleWidth = 0;
pauseLeftOffset = 0;
pauseWidth = imageLayoutWidth - minWidthOffset + pieceWidth;
}
if (minWidthOffset >= pieceWidth + imageLayoutWidth) {
pauseWidth = 0;
closeLeftOffset = 0;
closeWidth = imageLayoutWidth - minWidthOffset + pieceWidth + imageLayoutWidth;
}
if (minWidthOffset >= pieceWidth * 2) {
closeWidth = 0;
}
titleWrapper.setWidth(Math.round(titleWidth));
titleWrapper.setHeight(offHeight2);
pauseIvWrapper.setWidth(Math.round(pauseWidth));
pauseIvWrapper.setHeight(offHeight2);
pauseIvWrapper.setMarginLeft(Math.round(pauseLeftOffset));
closeIvWrapper.setWidth(closeWidth);
closeIvWrapper.setHeight(offHeight2);
closeIvWrapper.setMarginLeft(Math.round(closeLeftOffset));
pauseIv.setAlpha(alphaPercent);
closeIv.setAlpha(alphaPercent);
titleLayout.setAlpha(alphaPercent);
} else {
mDetailView.setVisibility(View.VISIBLE);
mBackgroundViewWrapper.setHeight(Math.round(mBackgroundOriginalHeight * videoNodeHeightPercent));
mTopViewWrapper.setWidth(Math.round(mTopViewOriginalWidth * videoNodeWidthPercent));
mTopViewWrapper.setHeight(Math.round(mTopOriginalHeight * videoNodeHeightPercent));
mBackgroundViewWrapper.setMarginTop(m);
}
mBackgroundViewWrapper.setWidth(Math.round(mTopViewOriginalWidth * videoNodeWidthPercent));
mBackgroundViewWrapper.setMarginRight(videoLeftRightOffset);
mBackgroundViewWrapper.setMarginLeft(videoLeftRightOffset);
mBackgroundViewWrapper.setMarginBottom(detailBottomOffset);
mDetailView.setAlpha(marginPercent);
this.getBackground().setAlpha((int) (marginPercent * 255 * 0.6f));
mCallback.videoSize(mTopViewWrapper.getWidth(), mTopViewWrapper.getHeight());
mBackgroundView.setAlpha(1);
}
void dismissView() {
float fullY = mRangeScrollY + mTopOriginalHeight * MIN_RATIO_HEIGHT;
AnimatorSet set = new AnimatorSet();
set.playTogether(ObjectAnimator.ofFloat(mBackgroundView, "alpha", 1f, 0),
ObjectAnimator.ofInt(mBackgroundViewWrapper, "marginTop",
mBackgroundViewWrapper.getMarginTop(), Math.round(fullY)));
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(INVISIBLE);
mBackgroundView.setAlpha(1f);
}
});
set.setDuration((long) (dismissDuration * mBackgroundViewWrapper.getMarginTop() / fullY)).start();
if (mCallback != null)
mCallback.onVideoViewHide();
}
void confirmState(float v, int dy) {
if (mBackgroundViewWrapper.getMarginTop() >= mRangeScrollY) {
if (v > 15) {
dismissView();
} else {
goMin(true);
}
} else {
//Dy is used to judge whether the direction is sliding in the opposite direction.
//Change the state if the width reaches a certain value when the finger is raised or the speed reaches a certain value.
if (nowStateScale == 1f) {
if (mTopViewOriginalWidth - mBackgroundView.getWidth() >= mTopViewOriginalWidth * (1 - MIN_RATIO_WIDTH) / 3 || (v > 5 && dy > 0)) {
goMin();
} else {
goMax();
}
} else {
if (mTopViewOriginalWidth - mBackgroundView.getWidth() <= 2 * mTopViewOriginalWidth * (1 - MIN_RATIO_WIDTH) / 3 || (v > 5 && dy < 0)) {
goMax();
} else {
goMin();
}
}
}
}
public void fullScreenGoMin() {
if (isLandscape()) {
nowStateScale = MIN_RATIO_HEIGHT;
if (!activityFullscreen) {
mActivity.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
resetRangeAndSize();
mBackgroundViewWrapper.setMarginTop(Math.round(mRangeScrollY));
updateVideoView(Math.round(mRangeScrollY));
} else {
goMin();
}
}
public void goLandscapeMin() {
mCallback.status(STATUS_MIN);
nowStateScale = MIN_RATIO_HEIGHT;
resetRangeAndSize();
mBackgroundViewWrapper.setMarginTop(Math.round(mRangeScrollY));
updateVideoView(Math.round(mRangeScrollY));
}
public void goPortraitMin() {
nowStateScale = MIN_RATIO_HEIGHT;
mCallback.status(STATUS_MIN);
resetRangeAndSize();
mBackgroundViewWrapper.setMarginTop(Math.round(mRangeScrollY));
updateVideoView(Math.round(mRangeScrollY));
}
public void goPortraitMax() {
if (!activityFullscreen) {
mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
mCallback.status(STATUS_MAX);
nowStateScale = 1f;
resetRangeAndSize();
mBackgroundViewWrapper.setMarginTop(0);
updateVideoView(0);
}
public void goFullScreen() {
if (!activityFullscreen) {
mActivity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
mCallback.status(STATUS_MAX);
mBackgroundViewWrapper.setWidth(DensityUtil.getScreenW(getContext()));
mBackgroundViewWrapper.setHeight(DensityUtil.getScreenH(getContext()));
mTopViewWrapper.setWidth(DensityUtil.getScreenW(getContext()));
mTopViewWrapper.setHeight(DensityUtil.getScreenH(getContext()));
mCallback.videoSize(mTopViewWrapper.getWidth(), mTopViewWrapper.getHeight());
}
public void goMax() {
if (nowStateScale == MIN_RATIO_HEIGHT) {
MangalStuti.toolbar.setVisibility(GONE);
YoutubeControlPanel.openYouTube.setVisibility(VISIBLE);
YoutubeControlPanel.downIv.setVisibility(VISIBLE);
YoutubeControlPanel.total.setVisibility(VISIBLE);
YoutubeControlPanel.current.setVisibility(VISIBLE);
ViewGroup.LayoutParams params = getLayoutParams();
params.width = -1;
params.height = -1;
setLayoutParams(params);
}
ValueAnimator valueAnimator = ValueAnimator.ofFloat(mBackgroundViewWrapper.getMarginTop(), 0);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
updateVideoView((int) value);
if (value == 0) {
if (isLandscape()) {
goFullScreen();
}
mCallback.status(STATUS_MAX);
}
}
});
valueAnimator.setDuration((long) (mBackgroundViewWrapper.getMarginTop() / mRangeScrollY * rangeDuration)).start();
nowStateScale = 1.0f;
}
public void goMin() {
goMin(false);
}
public void goMin(final boolean isDismissToMin) {
MangalStuti.toolbar.setVisibility(VISIBLE);
nowStateScale = MIN_RATIO_HEIGHT;
YoutubeControlPanel.openYouTube.setVisibility(INVISIBLE);
YoutubeControlPanel.downIv.setVisibility(INVISIBLE);
YoutubeControlPanel.total.setVisibility(INVISIBLE);
YoutubeControlPanel.current.setVisibility(INVISIBLE);
final float fullTop = Math.abs(mBackgroundViewWrapper.getMarginTop() - mRangeScrollY);
ValueAnimator valueAnimator = ValueAnimator.ofFloat(mBackgroundViewWrapper.getMarginTop(), mRangeScrollY);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
mBackgroundView.setAlpha(isDismissToMin ? (value / fullTop) : 1);
updateVideoView((int) value);
if (value == mRangeScrollY) {
ViewGroup.LayoutParams p = getLayoutParams();
p.width = -2;
p.height = -2;
setLayoutParams(p);
mCallback.status(STATUS_MIN);
}
}
});
valueAnimator.setDuration((long) (Math.abs((1 - mBackgroundViewWrapper.getMarginTop() / mRangeScrollY)) * rangeDuration)).start();
}
//Get current status
public float getNowStateScale() {
return nowStateScale;
}
public boolean isMin() {
return nowStateScale == MIN_RATIO_HEIGHT;
}
public boolean isMax() {
return nowStateScale == 1f;
}
public void show() {
setVisibility(VISIBLE);
statusType = IconType.PLAY;
pauseIv.setBackgroundResource(R.drawable.pause);
//The default is to change from the bottom to the top.
mBackgroundViewWrapper.setMarginTop((int) mRangeScrollY);
goMax();
}
public void setCallback(Callback callback) {
mCallback = callback;
}
class MarginViewWrapper {
private ViewGroup.MarginLayoutParams params;
private View viewWrapper;
MarginViewWrapper(View view) {
this.viewWrapper = view;
params = (ViewGroup.MarginLayoutParams) viewWrapper.getLayoutParams();
if (params instanceof LinearLayout.LayoutParams) {
((LinearLayout.LayoutParams) params).gravity = Gravity.START;
}
}
int getWidth() {
return params.width < 0 ? (int) mTopViewOriginalWidth : params.width;
}
int getHeight() {
return params.height < 0 ? (int) mTopOriginalHeight : params.height;
}
void setWidth(float width) {
if (width == mTopViewOriginalWidth) {
params.width = -1;
params.setMargins(0, 0, 0, 0);
} else
params.width = (int) width;
viewWrapper.setLayoutParams(params);
}
void setHeight(float height) {
params.height = (int) height;
viewWrapper.setLayoutParams(params);
}
void setMarginTop(int m) {
params.topMargin = m;
viewWrapper.setLayoutParams(params);
}
void setMarginBottom(int m) {
params.bottomMargin = m - MangalStuti.actionBarHeight;
viewWrapper.setLayoutParams(params);
}
int getMarginTop() {
return params.topMargin;
}
void setMarginRight(int mr) {
params.rightMargin = mr;
viewWrapper.setLayoutParams(params);
}
void setMarginLeft(int mr) {
params.leftMargin = mr;
viewWrapper.setLayoutParams(params);
}
int getMarginRight() {
return params.rightMargin;
}
int getMarginLeft() {
return params.leftMargin;
}
int getMarginBottom() {
return params.bottomMargin;
}
}
public static Activity getActivityFromView(View view) {
if (null != view) {
Context context = view.getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
}
return null;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.videoParentLayout:
if (nowStateScale == MIN_RATIO_HEIGHT) {
goMax();
}
break;
case R.id.downIv:
fullScreenGoMin();
break;
case R.id.pauseLayout:
if (MediaPlayerManager.instance().getPlayerState() == MediaPlayerManager.PlayerState.ERROR ||
MediaPlayerManager.instance().getPlayerState() == MediaPlayerManager.PlayerState.PREPARING) {
return;
}
notifyStatus();
break;
case R.id.closeLayout:
dismissView();
mCallback.onIconClick(YouTuDraggingView.IconType.CLOSE);
break;
case R.id.statusIv:
notifyStatus();
break;
}
}
void fullScreenChange() {
if (isLandscape()) {
isLandscapeToPortrait = true;
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
} else {
isPortraitToLandscape = true;
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
}
boolean handleKeyDown(int keyCode) {
if (keyCode == KeyEvent.KEYCODE_BACK && getNowStateScale() == 1f) {
if (isPortraitToLandscape) {
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
goPortraitMax();
} else if (isLandscape()) {
fullScreenGoMin();
} else {
goMin();
}
return true;
}
return false;
}
public void e(String msg) {
Log.e("Youtu", msg);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//The current screen is landscape
if (getNowStateScale() == 1f) {
goFullScreen();
} else {
goLandscapeMin();
}
} else {
//The current screen is a vertical screen
if (getNowStateScale() == 1f) {
goPortraitMax();
} else {
goPortraitMin();
}
}
}
}
在“视频活动”的onCreate方法中,添加以下行:
mVideoView = findViewById(R.id.videoView);
mYouTuDraggingView = findViewById(R.id.youtube_view);
mYouTuDraggingView.setCallback(this);
playVideo();
您的playVideo方法..
private void playVideo() {
mYouTuDraggingView.show();
mVideoView.setUp("https://github.com/moyokoo/Media/blob/master/Azshara.mp4?raw=true"); // edit it with your video link
mVideoView.start();
MediaPlayerManager.instance().setScreenScale(ScaleType.SCALE_CENTER_CROP);
}
还如下更改xml中的videoView
:
<com.example.m.youtu.YouTuDraggingView
android:id="@+id/your_video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:orientation="vertical"
android:visibility="invisible"/>
简而言之,您要查找的方法是goMin();
类的goMax();
和YoutuDraggingView
。