【问题标题】:Detect device orientation when Activity orientation is locked当活动方向被锁定时检测设备方向
【发布时间】:2014-04-17 10:51:33
【问题描述】:

在我的项目中,我必须锁定活动的方向。 (我无法重新创建活动)

我想在用户更改设备方向时显示一条消息: “视图被锁定在这个位置......”

我可以使用此代码轻松锁定方向:

if(version >= Build.VERSION_CODES.JELLY_BEAN_MR2){
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
    }else{
        int orientation = activity.getResources().getConfiguration().orientation;
        if(orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }else{
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
    }

使用此代码,视图被锁定,但我无法检测到用户何时更改设备方向。

如果我使用以下代码:

@Override
   public void onConfigurationChanged(Configuration newConfig) {
     //Check if the orientation has change
     if(newConfig.orientation != mOrientation){
        Toast.makeText(this, "Message for user", Toast.LENGTH_SHORT).show();
     }

     //Try to lock the view but not working
     newConfig.orientation = mOrientation;

     //Obligatory line that reload the view and cannot be delete
     //(is the biggest prolem of this code)
     super.onConfigurationChanged(newConfig);
   }

如果有人知道锁定视图并检测设备方向变化的方法,那真的会对我有所帮助。

谢谢大家

【问题讨论】:

    标签: android view locking orientation


    【解决方案1】:

    也可以用SensorManager解决。这是一个简单的演示,展示了如何将锁定活动的图像方向保持正确为纵向:

    主活动:

    import android.content.Context;
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.Surface;
    import android.widget.ImageView;
    
    public class MainActivity extends AppCompatActivity {
        private ImageView img;
    
        private SensorManager mSensorManager;
        private Sensor mOrientation;
    
        float value_0 = -10000;
        float value_1 = -10000;
        private SensorEventListener mOrientationSensorListener = new SensorEventListener() {
            int orientation = -1;
    
            @Override
            public void onSensorChanged(SensorEvent event) {
                int value ;
                if(value_0 == event.values[0] && value_1==event.values[1]){
                    return;
                }
    //            Log.d("values:", "values:" + event.values[0]+", "+event.values[1]);
                if (event.values[1] > 0 && event.values[0] == 0) {
                    value = Surface.ROTATION_0;//portrait
                    if (orientation != value) {
                        updateImageRotation(value);
                        Log.d("orientation", "portrait  + update");
                    }
                    orientation = value;
                    Log.d("orientation", "portrait ");
                }
    
    
                if (event.values[1] < 0 && event.values[0] == 0) {
                    value = Surface.ROTATION_180;//portrait reverse
                    if (orientation != value) {
                        updateImageRotation(value);
                        Log.d("orientation", "portrait reverse + update");
                    }
                    orientation = value;
                    Log.d("orientation", "portrait reverse");
                }
    
                if (event.values[0] > 0 && event.values[1] == 0) {
                    value = Surface.ROTATION_90;//portrait reverse
                    if (orientation != value) {
                        updateImageRotation(value);
                        Log.d("orientation", "landscape  + update");
                    }
                    orientation = value;
                    Log.d("orientation", "landscape");
                }
    
                if (event.values[0] < 0 && event.values[1] == 0) {
                    value = Surface.ROTATION_270;//portrait reverse
                    if (orientation != value) {
                        updateImageRotation(value);
                        Log.d("orientation", "landscape  + update");
                    }
                    orientation = value;
                    Log.d("orientation", "landscape reverse");
                }
    
                value_0=event.values[0];
                value_1=event.values[1];
            }
    
            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {
    
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            img = (ImageView) findViewById(R.id.img);
            // Get sensor manager
            mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            // Get the default sensor of specified type
            mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            if (mOrientation != null) {
                mSensorManager.registerListener(mOrientationSensorListener, mOrientation,
                        SensorManager.SENSOR_DELAY_GAME);
            }
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            if (mOrientation != null) {
                mSensorManager.unregisterListener(mOrientationSensorListener);
            }
        }
    
    
        private void updateImageRotation(int degree) {
    
            switch (degree) {
                case Surface.ROTATION_0:
                    img.setRotation(0);
                    break;
                case Surface.ROTATION_90:
                    img.setRotation(90);
                    break;
                case Surface.ROTATION_180:
                    img.setRotation(180);
                    break;
                case Surface.ROTATION_270:
                    img.setRotation(270);
                    break;
            }
        }
    }
    

    在清单中。方向锁定为portrait,并且需要传感器作为功能 ma​​nifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest package="permissionsmngr.com.apipas.rotationmanage"
              xmlns:android="http://schemas.android.com/apk/res/android">
    
        <uses-feature
            android:name="android.hardware.sensor.accelerometer"
            android:required="true"/>
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity
                android:name=".MainActivity"
                android:screenOrientation="portrait"
                >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        android:id="@+id/activity_main"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="permissionsmngr.com.apipas.rotationmanage.MainActivity">
    
        <ImageView
            android:layout_centerInParent="true"
            android:id="@+id/img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher"
            />
    </RelativeLayout>
    

    【讨论】:

    • 为什么选择 SensorEventListener 而不是 SensorEventListener2?
    • @chinmish 没什么特别的 .. 只是对接收 onFlushCompleted 不感兴趣
    • 您好,这是如何工作的?我的意思是,我看到 event.values[0] 和 event.values[1] 从正数变为负数,反之亦然,但它们永远不会完全 == 0
    【解决方案2】:

    下面的代码对我有用。

    MainActivity.java:

    public class MainActivity extends Activity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            startService( new Intent(this, Receiver.class) );
    }
    }
    

    BackgroundService.java

    public class Receiver extends Service {
        private static final String BCAST_CONFIGCHANGED = "android.intent.action.CONFIGURATION_CHANGED";
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            IntentFilter filter = new IntentFilter();
            filter.addAction(BCAST_CONFIGCHANGED);
            this.registerReceiver(mBroadcastReceiver, filter);
        }
    
        @Override
        public void onDestroy() {
        }
    
        @Override
        public void onStart(Intent intent, int startid) {
        }
    
        public BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent myIntent) {
                if ( myIntent.getAction().equals( BCAST_CONFIGCHANGED ) ) {
                    if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
                    }
                    else {
                    }
                }
            }
        };
    }
    

    Manifestfile.xml

    <service android:name=".Receiver">
                <intent-filter>
                    <action android:name="android.intent.action.CONFIGURATION_CHANGED"/>
                </intent-filter>
            </service>
    

    【讨论】:

    • 谢谢。但是这个解决方案的问题是,如果我锁定视图 CONFIGURATION_CHANGED 意图,就不再需要调用了。 (我认为当视图被锁定时改变设备的方向不要改变配置)
    【解决方案3】:

    您可以简单地使用OrientationEventListener 从传感器获取方向 (用 Kotlin 编写):

    class MainActivity : AppCompatActivity() {
    
        private var orientationEventListener: OrientationEventListener? = null
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            ...
    
            orientationEventListener = object : OrientationEventListener(context) {
                override fun onOrientationChanged(orientation: Int) {
                    // orientation is in degrees
    
                    // Show "The View is locked in this position ..." message if orientation is between 45° and 315°
                    viewModel.showViewIsLocked(orientation in 45..315)
                }
            }       
        }
    
        override fun onResume() {
            super.onResume()
            orientationEventListener?.enable()      
        }
    
        override fun onPause() {
            orientationEventListener?.disable()
            super.onPause()
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-16
      • 2015-11-13
      • 1970-01-01
      • 2013-10-29
      相关资源
      最近更新 更多