Различная компоновка для альбомной и альбомной-обратной ориентации

Моя проблема:

Для некоторых требований мне нужны два разных макета xml для моей деятельности:

  • Один для ландшафтного режима.
  • И еще один для режима Горизонтально-обратный (перевернутый или перевернутый).

К сожалению, Android не позволяет создавать отдельные макеты для альбомной ориентации и реверса (как мы можем сделать для портретной и альбомной ориентации с layout-land и layout-port).

AFAIK, единственный способ - изменить Activity-xml из java-кода.

Что я пробовал:

1) Переопределите метод onConfigurationChanged() для обнаружения изменений ориентации, но я не могу понять, является ли он альбомным или альбомным-обратным:

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

     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
         Log.d("TEST","Landscape");
     }

}

android:configChanges="keyboardHidden|orientation|screenSize|layoutDirection" в моем теге активности в манифесте)

2) Используйте OrientationEventListener с SENSOR_DELAY_NORMAL, как предлагается в этом ответе, но ориентация устройства изменяется перед вводом моих блоков if, поэтому я получаю отложенное обновление представления:

mOrientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL){

            @Override
            public void onOrientationChanged(int orientation) {

                if (orientation==0){
                    Log.e("TEST", "orientation-Portrait  = "+orientation);
                } else if (orientation==90){
                    Log.e("TEST", "orientation-Landscape = "+orientation);
                } else if(orientation==180){
                    Log.e("TEST", "orientation-Portrait-rev = "+orientation);
                }else if (orientation==270){
                    Log.e("TEST", "orientation-Landscape-rev = "+orientation);
                } else if (orientation==360){
                    Log.e("TEST", "orientation-Portrait= "+orientation);
                }

            }};

Мой вопрос:

Есть ли лучшее решение для изменения макета деятельности между ориентацией "Landscape" и "Landscape-reverse"?

Любые предложения приветствуются.


person Rami    schedule 11.01.2016    source источник


Ответы (2)


Вы пытаетесь выполнить это, как здесь? Вы можете обрабатывать событие с различными типами конфигурации как обратной, так и стандартной, используя атрибут активности sensorLandscape

EDITED: попробуйте использовать Display.getOrientation, как описано здесь http://android-developers.blogspot.in/2010/09/one-screen-turn-desizes-another.html

И не забудьте установить флаг configChanges для активности в манифесте, чтобы вручную обрабатывать изменения в onConfigurationChanges().

Так что, похоже, единственный способ сделать это - как можно чаще слушать SensorManager.

SensorManager sensorMan = (SensorManager)getSystemService(SENSOR_SERVICE);
Sensor sensor = sensorMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMan.registerListener(...)
person N. Chebotarev    schedule 11.01.2016
comment
Спасибо за ваш ответ. Я только что попробовал ваше предложение и не сработал. Ответ Пита совершенно неправильный. --1) С атрибутом android:screenOrientation нельзя использовать |. --2) Configuration.orientation не имеет ничего общего делать с ActivityInfo.SCREEN_ORIENTATION_PORTRAIT или другими константами. - person Rami; 12.01.2016
comment
Поскольку Configuration.orientation имеет значение = 1 или = 2 (ORIENTATION_PORTRAIT или ORIENTATION_LANDSCAPE), а константы ActivityInfo имеют 0, 1,8 и 9 как значения. - person Rami; 12.01.2016
comment
Хорошо, знакомы ли вы с этой темой Дэна Моррилла - android-developers.blogspot.in/2010/09/› Вопрос в том, как устройство сообщает вам, что оно было переориентировано? И ответ: android.view.Display.getRotation (). Этот метод вернет одно из четырех значений, указывающих, что либо устройство не было переориентировано (ROTATION_0), либо оно было переориентировано на 90 градусов, 180 градусов или 270 градусов (которые соответственно равны ROTATION_90, ROTATION_180 и ROTATION_270.) - person N. Chebotarev; 12.01.2016
comment
Использование getRotation() вернет правильное значение. Но проблема в том, где это использовать? Я добавил случай переключателя getRotation() в метод onConfigurationChanged(), он отлично работает, когда вы делаете поворот на 90 °, но для поворота на 180 ° onConfigurationChanged() не будет вызываться, потому что размер экрана не был изменен с земли на землю-оборот (или порт на порт-rev). - person Rami; 12.01.2016
comment
Activity воссоздает себя каждый раз при изменении конфигурации, так как для этого необходимо повторно надуть соответствующий макет. Итак, теоретически вы можете вызвать getOrientation где угодно, например в onStart или onCreate. - person N. Chebotarev; 13.01.2016
comment
Чтобы использовать onConfigurationChanged (), вы должны установить флаг configChanged для активности в манифесте приложения. В противном случае функция configurationChanged () не будет вызываться и действие будет воссоздано. См. Атрибут javadoc ›Укажите одно или несколько изменений конфигурации, которые действие будет обрабатывать само. Если не указано иное, действие будет перезапущено, если в системе произойдет какое-либо из этих изменений конфигурации. В противном случае действие останется запущенным, а его метод Activity.onConfigurationChanged () будет вызван с новой конфигурацией. - person N. Chebotarev; 13.01.2016
comment
Я знаю это, но практически этого не произошло (по крайней мере, в моем Samsung S3, Nexus 7, Nexus 10 и Acer iconia). Кстати, попробуйте создать простой проект с Activity, затем добавьте точку останова (или какой-нибудь журнал) в методе onCreate, затем сделайте быстрое вращение на 180 ° (exp от портрета к портретному обороту или земля к земле-обороту), вы видите, что метод onCreate () не всегда вызывается. Я думаю, что Android посчитал, что переключение из режима в режим реверсирования не влияет на размер, поэтому нет необходимости воссоздавать действие или вызывать onConfigurationChanged (). А может, это просто ошибка Android. - person Rami; 13.01.2016
comment
PS: Я также пробовал использовать android:configChanges="keyboardHidden|orientation|screenSize|layoutDirection" в теге активности в манифесте, и это то же самое. - person Rami; 13.01.2016
comment
В этой теме groups.google.com/forum/#!topic/android- developers / IgBNQNgFUmk содержит ответ от разработчика фреймворка Android Дайанн Хакборн. Она подтверждает, что не существует удобного способа обработки события изменения ориентации. Таким образом, одним из возможных решений должно быть прослушивание SensorManager с соответствующей плотностью и надежда, что это не слишком сильно повлияет на батарею. - person N. Chebotarev; 13.01.2016
comment
Спасибо за ссылку, по крайней мере, она подтверждает мои результаты. Спасибо за это :) - person Rami; 14.01.2016

для достижения этой цели вам необходимо реализовать слушатель вращения, вам также необходимо знать, что Android уничтожает объекты и воссоздает их для загрузки ваших макетов, значений ... на основе квалификаторов конфигурации

ШАГ 01: создайте интерфейс Java [RotationCallbackFn]

    public interface rotationCallbackFn {
        void onRotationChanged(int lastRotation, int newRotation);
    }

ШАГ 02: создайте класс Java [RotationListenerHelper]

import android.content.Context;
import android.hardware.SensorManager;
import android.view.OrientationEventListener;
import android.view.WindowManager;

public class rotationListenerHelper {

private int lastRotation;

private WindowManager windowManager;
private OrientationEventListener orientationEventListener;

private rotationCallbackFn callback;

public rotationListenerHelper() {
}

public void listen(Context context, rotationCallbackFn callback) {
    // registering the listening only once.
    stop();
    context = context.getApplicationContext();
    this.callback = callback;
    this.windowManager = (WindowManager) context
            .getSystemService(Context.WINDOW_SERVICE);

    this.orientationEventListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) {
        @Override
        public void onOrientationChanged(int orientation) {
            WindowManager localWindowManager = windowManager;
            rotationCallbackFn localCallback = rotationListenerHelper.this.callback;
            if(windowManager != null && localCallback != null) {
                int newRotation = localWindowManager.getDefaultDisplay().getRotation();
                if (newRotation != lastRotation) {
                    localCallback.onRotationChanged(lastRotation, newRotation);
                    lastRotation = newRotation;
                }
            }
        }
    };
    this.orientationEventListener.enable();

    lastRotation = windowManager.getDefaultDisplay().getRotation();
}

public void stop() {
    if(this.orientationEventListener != null) {
        this.orientationEventListener.disable();
    }
    this.orientationEventListener = null;
    this.windowManager = null;
    this.callback = null;
}

}

ШАГ 03: добавьте эти операторы в свой mainActivity

// declaration
private rotationListenerHelper rotationListener = null;
private Context mContext;
//...

/* constructor ----------------------------------------------------------------*/
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mContext = this;

    final int curOrientation =  getWindowManager().getDefaultDisplay().getRotation();

    switch (curOrientation) {
        case 0:
            //. SCREEN_ORIENTATION_PORTRAIT
            setContentView(R.layout.your_layout_port);
            break;
            //----------------------------------------
        case 2:
            //. SCREEN_ORIENTATION_REVERSE_PORTRAIT
            setContentView(R.layout.your_layout_port_rev);
            break;
            //----------------------------------------
        case 1:
            //. SCREEN_ORIENTATION_LANDSCAPE
            setContentView(R.layout.your_layout_land);
            break;
            //----------------------------------------
        case 3:
            //. SCREEN_ORIENTATION_REVERSE_LANDSCAPE
            setContentView(R.layout.your_layout_land_rev);
            break;
            //----------------------------------------
    } /*endSwitch*/

    rotationListener = new rotationListenerHelper();
    rotationListener.listen(mContext, rotationCB);

    //...
}

private rotationCallbackFn rotationCB = new rotationCallbackFn() {
    @Override
    public void onRotationChanged(int lastRotation, int newRotation) {
        Log.d(TAG, "onRotationChanged: last " + (lastRotation) +"  new " + (newRotation));

        /**
        * no need to recreate activity if screen rotate from portrait to landscape
        * android do the job in order to reload resources
        */

        if (
                (lastRotation == 0 && newRotation == 2) ||
                (lastRotation == 2 && newRotation == 0) ||
                (lastRotation == 1 && newRotation == 3) ||
                (lastRotation == 3 && newRotation == 1)
                )
            ((Activity) mContext).recreate();
    }
};

/* destructor -----------------------------------------------------------------*/
@Override
protected void onDestroy() {
    rotationListener.stop();
    rotationListener = null;
    Log.i(TAG, "onDestroy: activity destroyed");
    super.onDestroy();
}

ЗАКЛЮЧИТЕЛЬНЫЙ ШАГ: НАСЛАЖДАЙТЕСЬ

person tdjprog    schedule 23.01.2017