【问题标题】:Different layout for "Landscape" and "Landscape-reverse" orientation“横向”和“横向”方向的不同布局
【发布时间】:2016-01-11 19:36:28
【问题描述】:

我的问题:

对于某些要求,我的活动需要两种不同的 xml 布局:

  • 一个用于横向模式。
  • 还有一个用于横向反转模式(横向倒置)。

不幸的是,Android 不允许为横向反转创建单独的布局(就像我们可以使用 layout-landlayout-port 为纵向和横向创建一样)。

AFAIK,唯一的方法是从 java 代码中更改 activity-xml。

我试过的:

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) 按照this answer 中的建议使用OrientationEventListenerSENSOR_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" 方向之间更改活动布局是否有更好的解决方案?

非常感谢任何建议。

【问题讨论】:

    标签: android orientation landscape device-orientation orientation-changes


    【解决方案1】:

    您是否尝试使用suggested here?。您可以使用活动属性sensorLandscape处理具有不同类型配置反向和标准的事件

    已编辑:尝试使用此处所述的 Display.getOrientation http://android-developers.blogspot.in/2010/09/one-screen-turn-deserves-another.html

    并且不要忘记在清单中的活动上设置 configChanges 标志以手动处理 onConfigurationChanges() 中的更改。

    因此,这样做似乎唯一的方法就是尽可能频繁地监听 SensorManager。

    SensorManager sensorMan = (SensorManager)getSystemService(SENSOR_SERVICE);
    Sensor sensor = sensorMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sensorMan.registerListener(...)
    

    【讨论】:

    • 感谢您的回答。我刚刚尝试了你的建议,但没有奏效。皮特的回答是完全错误的。 --1) 对于android:screenOrientation 属性,您不能使用|。 --2) Configuration.orientationActivityInfo.SCREEN_ORIENTATION_PORTRAIT 或其他常量无关。
    • 因为 Configuration.orientation 的值 = 1 或 = 2(ORIENTATION_PORTRAITORIENTATION_LANDSCAPE),而 ActivityInfo 的常量的值是 0、1、8 和 9。
    • 好的,你遇到过 Dan Morrill 的这个话题吗 - android-developers.blogspot.in/2010/09/… >问题是,设备如何告诉你它已经被重新定向?答案是:android.view.Display.getRotation()。该方法将返回四个值之一,指示设备尚未重新定向 (ROTATION_0),或者已重新定向 90 度、180 度或 270 度(分别为 ROTATION_90、ROTATION_180 和 ROTATION_270。)
    • 使用getRotation() 将返回正确的值。但问题是在哪里使用它?我在onConfigurationChanged() 方法中添加了getRotation() 的开关盒,当您进行90° 旋转时它工作正常,但对于180° 旋转onConfigurationChanged() 将不会被调用,因为屏幕尺寸没有从陆地改变到土地转(或港口转港口转)。
    • 我知道,但实际上并没有发生这种情况(至少在我的三星 S3、Nexus 7、Nexus 10 和 Acer iconia 中是这样)。顺便说一句,尝试使用 Activity 创建一个简单的项目,然后在 onCreate 方法中添加一个断点(或一些日志),然后快速旋转 180°(从纵向到纵向旋转或从陆地到陆地旋转)你会看到 onCreate() 方法并不总是被调用。我认为android认为从模式切换到reverse-mod不会影响大小,因此不需要重新创建活动或调用onConfigurationChanged()。或者它只是一个 Android 错误。
    【解决方案2】:

    为了实现这个目标,你需要实现一个旋转监听器, 您还需要知道 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();
    }
    

    最后一步:享受

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 2014-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多