Как повторно использовать макет, установленный в setContentView? Андроид

Я пытаюсь использовать android:configChanges="keyboardHidden|orientation|screenSize" в своем манифесте, чтобы не потерять состояние моего VideoView при изменении конфигурации. Это означает, что мне нужно самому выбирать макеты в конфигурации. Проблема, с которой я сталкиваюсь, заключается в том, что когда я впервые инициализирую, какое представление использовать в onCreate, здесь:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getResources().getConfiguration().orientation ==
                Configuration.ORIENTATION_LANDSCAPE) {
            setContentView(R.layout.activity_make_photo_video_land);

        } else if (getResources().getConfiguration().orientation ==
                Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.activity_make_photo_video);
        }
}

Он выбирает правильный макет. Но когда мне нужно настроить макет при изменении конфигурации, как здесь:

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

        if (getResources().getConfiguration().orientation ==
                Configuration.ORIENTATION_LANDSCAPE) {
            setContentView(R.layout.activity_make_photo_video_land);
        } else if (getResources().getConfiguration().orientation ==
                Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.activity_make_photo_video);
        }


    }

Он не использует тот же экземпляр макета, а перезагружает его, из-за чего мой VideoView становится черным. После этого я не могу нажимать никакие кнопки.

Есть ли способ повторно использовать первоначальные макеты? Я пытался установить представления, подобные этому setContentView(R.layout.activity_make_photo_video_land);, для объекта Activity activity, но IDE не позволяет мне, он говорит Activity is incompatible with void. Потому что, если бы я мог получить ссылку на это представление, я мог бы использовать его повторно. Или есть более простой способ сделать это, которого я не вижу?

Спасибо.

введите здесь описание изображения


person Azurespot    schedule 01.04.2015    source источник


Ответы (2)


Я предлагаю альтернативное и простое решение вашей проблемы:

1. Переместите макет activity_make_photo_video_land в папку /res/layout-land/ и переименуйте его в activity_make_photo_video.xml.

Таким образом, ваш вид activity_make_photo_video_land (переименовать в activity_make_photo_video) будет увеличиваться при изменении ориентации на LANDSCAPE.

Таким образом, вам не требуется обрабатывать эти объекты вручную из кода Java.

Измените onCreate() на:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_make_photo_video_land);

}

Ваше приложение будет иметь один макет Activity_make_photo_video в папках /res/layout/ и /res/layout-land/ в обеих папках.

ОБНОВЛЕНИЕ :

Если вы не укажете иное, изменение конфигурации (например, изменение ориентации экрана, языка, устройств ввода и т. д.) приведет к уничтожению вашей текущей активности, проходя через обычный процесс жизненного цикла активности onPause(), onStop() и onDestroy() по мере необходимости. Если активность находилась на переднем плане или была видна пользователю, после вызова onDestroy() в этом экземпляре будет создан новый экземпляр активности с любым saveInstanceState, созданным предыдущим экземпляром из onSaveInstanceState(Bundle).

Переопределите onSaveInstanceState(Bundle) и сохраните свое состояние здесь

Вы можете проверить больше здесь

Я надеюсь, что это сработает

person Kushal    schedule 01.04.2015
comment
Спасибо, но это не сработает. Вся причина, по которой мне нужно сделать это вручную, состоит в том, чтобы попытаться сохранить состояние моего VideoView. Разрешение Android выбирать мои макеты, когда я переключаюсь между альбомной/портретной ориентацией и обратно, означает, что Activity перезапускается, и, следовательно, я теряю загруженное видео. Кроме того, любой макет, который я помещаю в папку layout, вызывает портрет. И любой макет, который я добавляю в layout-land, создает ландшафт, независимо от того, как он называется. - person Azurespot; 01.04.2015
comment
Я не совсем понимаю, но вы не можете поместить объект в Bundle: ... вы не можете поместить простой объект в Bundle. И причина этого в том, что точка этого сохраненного состояния заключается в том, чтобы оно было скопировано из вашего процесса, поэтому, если ваш процесс необходимо убить, его можно позже скопировать обратно в новый процесс для повторной инициализации. ваша активность/фрагмент из. Необработанный объект имеет смысл только в контексте процесса, в котором он выполняется, поэтому невозможно правильно скопировать ссылку на такой объект из вашего текущего процесса в другой. - person Azurespot; 01.04.2015
comment
Из здесь. - person Azurespot; 01.04.2015
comment
Если вы знаете простой рабочий пример, дайте мне знать. Я не вижу, как это будет выглядеть в коде. Спасибо. - person Azurespot; 01.04.2015
comment
Спасибо @Kushal, мне удалось найти код, очень повезло. Мне удалось переопределить эти 2 метода. Я не могу правильно отметить ваш ответ, так как я изменил много разных вещей, но ваш ответ указал мне направление для написания, так что спасибо! Я написал подробности в другом ответе, чтобы вести журнал для других. - person Azurespot; 01.04.2015
comment
Спасибо @NoniA. за это - person Kushal; 01.04.2015

Благодаря предложению @Kushal я изучил 2 метода onSaveInstanceState(Bundle savedInstanceState) и onRestoreInstanceState(Bundle savedInstanceState), чтобы сохранить состояние VideoView при изменении конфигурации (поскольку это было корнем моей проблемы, а использование setContentView было просто идеей взлома). Оказывается, я нашел там какой-то код. Вот что я сделал:

  1. Убедитесь, что у меня был альбомный xml и обычный xml. У меня в папках layout-land и layout соответственно с таким же названием.

  2. Переопределите эти 2 метода следующим образом:

    private int position = 0;
    
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        // use onSaveInstanceState in order to store the video
        // playback position for orientation change
        savedInstanceState.putInt("Position",  videoView.getCurrentPosition());
        videoView.pause();
    }
    
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // use onRestoreInstanceState in order to play the video playback
        // from the stored position
        position = savedInstanceState.getInt("Position");
        videoView.seekTo(position);
    }
    
  3. Вынул android:configChanges="keyboardHidden|orientation|screenSize" из моего манифеста.

  4. Удален метод onConfigurationChanged(Configuration newConfig) (он больше не нужен после №3).

Это сделало это! Я мог изменить ориентацию в любое время и записать свое видео в любое время. По возвращении из перекодирования видео оно легко отображалось как в альбомной, так и в портретной ориентации без потери видео (экран никогда не становился черным).

Единственная проблема, которая у меня сейчас есть, это то, что мой OnTouchListener отключен, но это уже другая проблема.

person Azurespot    schedule 01.04.2015