Android VideoView 方向随缓冲视频而变化 [英] Android VideoView orientation change with buffered video

查看:33
本文介绍了Android VideoView 方向随缓冲视频而变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Android 市场中复制最新版 YouTube 应用的功能.观看视频时,有两种不同的布局,一种是纵向布局,可提供附加信息,另一种是横向布局,可提供视频的全屏视图.

I'm trying to replicate the functionality of the latest YouTube app in the Android marketplace. When watching a video there's two separate layouts, one in portrait which provides additional info, and one in landscape which provides a full screen view of the video.


纵向模式下的 YouTupe 应用


横向模式的 YouTube 应用

(抱歉照片的随机性,但它们是我能找到的实际布局的第一张照片)

(Sorry for the randomness of the photos, but they were the first pics I could find of the actual layout)

这通常很容易做到——只需在 layout-land 中指定一个替代布局,一切都会好起来的.YouTube 应用程序做得非常好的一件事(我正在尝试复制)是在方向改变时,视频会继续播放并且不必从头开始重新缓冲.

This is pretty easy to do normally - just specify an alternate layout in layout-land and all will be good. The thing that the YouTube app does really well (and what I'm trying to replicate) is that on orientation change, the video continues playing and doesn't have to re-buffer from the beginning.

我发现覆盖 onConfigurationChange() 并设置新的 LayoutParameters 将允许我在不强制重新缓冲的情况下调整视频的大小 - 但是当多次旋转屏幕时,视频会随机缩放到不同的宽度/高度.我尝试在 VideoView 上进行各种 invalidate() 调用,尝试在父 RelativeLayout 容器上调用 RequestLayout() 并尝试尽可能多的不同事情,但我似乎无法让它正常工作.任何建议将不胜感激!

I've figured out that overriding onConfigurationChange() and setting new LayoutParameters will allow me to resize the video without forcing a rebuffer - however the video will randomly scale to different widths/heights when rotating the screen multiple times. I've tried doing all sorts of invalidate() calls on the VideoView, tried calling RequestLayout() on the parent RelativeLayout container and just trying as many different things as I can, but I can't seem to get it to work properly. Any advice would be greatly appreciated!

这是我的代码:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        questionText.setVisibility(View.GONE);
        respond.setVisibility(View.GONE);
        questionVideo.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    } else {
        questionText.setVisibility(View.VISIBLE);
        respond.setVisibility(View.VISIBLE);
        Resources r = getResources();
        int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150.0f, r.getDisplayMetrics());
        questionVideo.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, height));
    }
}

我在 logcat 中发现了一些有趣的输出,这些输出在我的视频旋转时出现,这似乎是罪魁祸首 - 尽管我不知道如何修复它:

I've discovered in logcat some interesting output that comes up when my video is rotated which seems to be the culprit - although I have no idea how to fix it:

正确调整大小时的 Logcat 输出(占据整个窗口)

注意 h=726

12-13 15:37:35.468  1262  1270 I ActivityManager: Config changed: { scale=1.0 imsi=310/4 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=210}
12-13 15:37:35.561  1262  1268 I TIOverlay: Position/X0/Y76/W480/H225
12-13 15:37:35.561  1262  1268 I TIOverlay: Adjusted Position/X1/Y0/W403/H225
12-13 15:37:35.561  1262  1268 I TIOverlay: Rotation/90
12-13 15:37:35.561  1262  1268 I Overlay : v4l2_overlay_set_position:: w=480 h=224
12-13 15:37:35.561  1262  1268 I Overlay : v4l2_overlay_set_position:: w=402 h=726
12-13 15:37:35.561  1262  1268 I Overlay : dumping driver state:
12-13 15:37:35.561  1262  1268 I Overlay : output pixfmt:
12-13 15:37:35.561  1262  1268 I Overlay : w: 432
12-13 15:37:35.561  1262  1268 I Overlay : h: 240
12-13 15:37:35.561  1262  1268 I Overlay : color: 7
12-13 15:37:35.561  1262  1268 I Overlay : UYVY
12-13 15:37:35.561  1262  1268 I Overlay : v4l2_overlay window:
12-13 15:37:35.561  1262  1268 I Overlay : window l: 1 
12-13 15:37:35.561  1262  1268 I Overlay : window t: 0 
12-13 15:37:35.561  1262  1268 I Overlay : window w: 402 
12-13 15:37:35.561  1262  1268 I Overlay : window h: 726

不正确调整大小时的 Logcat 输出(占全屏的一小部分)

注意 h=480

12-13 15:43:00.085  1262  1270 I ActivityManager: Config changed: { scale=1.0 imsi=310/4 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=216}
12-13 15:43:00.171  1262  1268 I TIOverlay: Position/X0/Y76/W480/H225
12-13 15:43:00.171  1262  1268 I TIOverlay: Adjusted Position/X138/Y0/W266/H225
12-13 15:43:00.171  1262  1268 I TIOverlay: Rotation/90
12-13 15:43:00.179  1262  1268 I Overlay : v4l2_overlay_set_position:: w=480 h=224
12-13 15:43:00.179  1262  1268 I Overlay : v4l2_overlay_set_position:: w=266 h=480
12-13 15:43:00.179  1262  1268 I Overlay : dumping driver state:
12-13 15:43:00.179  1262  1268 I Overlay : output pixfmt:
12-13 15:43:00.179  1262  1268 I Overlay : w: 432
12-13 15:43:00.179  1262  1268 I Overlay : h: 240
12-13 15:43:00.179  1262  1268 I Overlay : color: 7
12-13 15:43:00.179  1262  1268 I Overlay : UYVY
12-13 15:43:00.179  1262  1268 I Overlay : v4l2_overlay window:
12-13 15:43:00.179  1262  1268 I Overlay : window l: 138 
12-13 15:43:00.179  1262  1268 I Overlay : window t: 0 
12-13 15:43:00.179  1262  1268 I Overlay : window w: 266 
12-13 15:43:00.179  1262  1268 I Overlay : window h: 480

也许有人知道叠加"是什么以及为什么它没有得到正确的高度值?

Maybe someone knows what 'Overlay' is and why it's not getting the correct height value?

推荐答案

(2016 年 6 月)

这个答案很旧(我认为是 android 2.2/2.3)并且可能不像下面的其他答案那么相关!除非您在旧版 Android 上进行开发,否则请先关注它们 :)

This answer is very old (I think android 2.2/2.3) and probably is not as relevant as the other answers below! Look to them first unless you're dev-ing on legacy Android :)

我能够将问题缩小到 VideoView 类中的 onMeasure 函数.通过创建子类并覆盖 onMeasure 函数,我能够获得所需的功能.

I was able to narrow down the problem to the onMeasure function in the VideoView class. By creating a child class and overriding the onMeasure function, I was able to get the desired functionality.

public class VideoViewCustom extends VideoView {

    private int mForceHeight = 0;
    private int mForceWidth = 0;
    public VideoViewCustom(Context context) {
        super(context);
    }

    public VideoViewCustom(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VideoViewCustom(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setDimensions(int w, int h) {
        this.mForceHeight = h;
        this.mForceWidth = w;

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.i("@@@@", "onMeasure");

        setMeasuredDimension(mForceWidth, mForceHeight);
    }
}

然后在我的活动中我做了以下事情:

Then inside my Activity I just did the following:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        questionVideo.setDimensions(displayHeight, displayWidth);
        questionVideo.getHolder().setFixedSize(displayHeight, displayWidth);

    } else {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

        questionVideo.setDimensions(displayWidth, smallHeight);
        questionVideo.getHolder().setFixedSize(displayWidth, smallHeight);

    }
}

行:

questionVideo.getHolder().setFixedSize(displayWidth, smallHeight);

是完成这项工作的关键.如果你在没有这个人的情况下进行 setDimensions 调用,视频仍然不会调整大小.

is key in order to make this work. If you do the setDimensions call without this guy, the video still will not resize.

您唯一需要做的另一件事是确保您也在 onCreate() 方法中调用 setDimensions() 否则您的视频将不会开始缓冲,因为视频不会被设置为在任何尺寸的表面上绘制.

The only other thing you need to do is ensure that you call setDimensions() inside the onCreate() method as well or your video will not start buffering as the video won't be set to draw on a surface of any size.

// onCreate()
questionVideo.setDimensions(initialWidth, initialHeight); 

最后一个关键部分 - 如果您发现自己想知道为什么 VideoView 没有在旋转时调整大小,您需要确保您要调整大小的尺寸完全strong> 等于或小于可见区域.我遇到了一个非常大的问题,当我在屏幕上仍然有通知栏/标题栏时,我将 VideoView 的宽度/高度设置为整个显示大小,并且根本没有调整 VideoView 的大小.只需删除通知栏和标题栏即可解决问题.

One last key part - if you ever find yourself wondering why the VideoView isn't resizing on rotation, you need to ensure the dimensions you're resizing to are either exactly equal to the visible area or less than it. I had a really big problem where I was setting the VideoView's width/height to the entire display size when I still had the notification bar/title bar on the screen and it was not resizing the VideoView at all. Simply removing the notification bar and title bar fixed the problem.

希望这对未来的人有所帮助!

Hopefully this helps someone in the future!

这篇关于Android VideoView 方向随缓冲视频而变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆