Android VideoView изменение ориентации с буферизованным видео - PullRequest
50 голосов
/ 14 декабря 2010

Я пытаюсь повторить функциональность последнего приложения YouTube на Android Marketplace. При просмотре видео есть две отдельные компоновки: одна в портретной ориентации, которая предоставляет дополнительную информацию, и другая в альбомной ориентации, которая обеспечивает полноэкранный просмотр видео.

YouTube app portrait layout
Приложение YouTupe в портретном режиме

YouTube app landscape layout
Приложение YouTube в ландшафтном режиме

(Извините за случайность фотографий, но они были первыми фотографиями, которые я смог найти в реальном макете)

Это довольно легко сделать обычно - просто укажите альтернативный макет в layout-land, и все будет хорошо. Дело в том, что приложение YouTube действительно хорошо работает (и я пытаюсь его воспроизвести), что при изменении ориентации видео продолжает воспроизводиться и не требует повторной буферизации с самого начала.

Я выяснил, что переопределение onConfigurationChange () и установка новых LayoutParameters позволит мне изменить размер видео без принудительного создания буферов - однако видео будет случайным образом масштабироваться до различной ширины / высоты при повороте экрана несколько раз. Я пытался делать всевозможные вызовы invalidate () в VideoView, пытался вызвать RequestLayout () в родительском контейнере RelativeLayout и просто пробовал как можно больше разных вещей, но я не могу заставить его работать должным образом. Любой совет будет принята с благодарностью!

Вот мой код:

@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 какой-то интересный вывод, который появляется, когда мое видео вращается, что кажется виновником - хотя я понятия не имею, как это исправить:

Выход 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

Может быть, кто-то знает, что такое «Наложение» и почему он не получает правильное значение высоты?

Ответы [ 11 ]

0 голосов
/ 27 апреля 2017

Я пытался использовать код других ответов, но это не решило мою проблему, потому что, если я быстро повернул экран, размер моего видео был увеличен. Поэтому я частично использую их код, который помещаю в поток, который очень быстро обновляет окно. Итак, вот мой код:

  new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            while(true)
            {
                try
                {
                    Thread.sleep(1);
                }
                catch(InterruptedException e){}
                handler.post(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                                WindowManager.LayoutParams.FLAG_FULLSCREEN);
                    }
                });
            }
        }
    }).start();

Таким образом, размер видео будет всегда правильным (в моем случае).

...