Android:检测方向已更改

发布于 2024-12-17 20:01:31 字数 517 浏览 2 评论 0原文

我需要检测应用程序中的方向变化,但我不希望我的布局从纵向更改为横向。 目前我正在使用 OrientationEventListener,但是检测方向角度还不够。我想检测用户从纵向变为横向,反之亦然,而这不仅仅是检测方向角是 90 度还是 270 度。

我想做与 Android 相同的检测来改变 Activity 的方向。我尝试覆盖 onConfigurationChanged 并检查方向是否为横向/纵向,但这仍然会将我的活动布局更改为横向。

有没有办法使用 onConfigurationChanged 但强制布局保持纵向?
是否有另一种方法可以在不使用 OrientationEventListener 的情况下检测方向变化。最终我可以实现我自己的方向改变算法,对此有什么想法吗?它必须比 if(90-THRESHOLD <=orientation <= 90+THRESHOLD) 更复杂,我想检测用户是否进行了完整的移动纵向->横向或横向->肖像。

感谢您的帮助,
菲利佩

I need to detect an orientation change in my application, but I don't want my layout to be changed from portrait to landscape.
Currently I'm using the OrientationEventListener however detecting the orientation angle is not enough. I want to detect that the user changed from portrait to landscape or viceversa, and that is not just detecting if the orientation angle is 90 or 270.

I want to do the same detection that the Android does to change the activity's orientantion. I tried overriding onConfigurationChanged and check if orientantion is landscape/portrait, however this still changes my activity layout to landscape.

Is there a way to use onConfigurationChanged but force the layout to stay in portrait?
Is there another way to detect orientantion change without using OrientationEventListener. Ultimately I can implement my own orientation changed algorithm, any ideas on this? It has to be something more complex than if(90-THRESHOLD <= orientation <= 90+THRESHOLD), I want to detect if the user made the complete movement Portrait->Landscape or Landscape->Portrait.

Thanks for the help,
Filipe

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤者何惧 2024-12-24 20:01:31

好吧,在尝试使用 Android API 但无法完成我需要的操作后,我实现了自己的算法,实际上并没有那么复杂:
我使用了 OrientationEventListener,并计算方向是否位于 4 个方向点(在我的代码中,我仅检测 LANDSCAPE_RIGHTPORTRAIT_UP

orientationListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_UI) {
        public void onOrientationChanged(int orientation) {
            if(canShow(orientation)){
                show();
            } else if(canDismiss(orientation)){
                dismiss();
            }
        }
    };

@Override
public void onResume(){
    super.onResume();
    orientationListener.enable();
}

@Override
public void onPause(){
    super.onPause();
    orientationListener.disable();
}

private boolean isLandscape(int orientation){
        return orientation >= (90 - THRESHOLD) && orientation <= (90 + THRESHOLD);
    }

private boolean isPortrait(int orientation){
    return (orientation >= (360 - THRESHOLD) && orientation <= 360) || (orientation >= 0 && orientation <= THRESHOLD);
}

public boolean canShow(int orientation){
    return !visible && isLandscape(orientation);
}

public boolean canDismiss(int orientation){
    return visible && !dismissing && isPortrait(orientation);
}

Ok, after trying to use the Android API and not being able to do what I need, I implemented my own algorithm and actually it wasn't that complicated:
I used a OrientationEventListener, and calculated if the orientation is in the 4 orientation points (in my code I only detect LANDSCAPE_RIGHT and PORTRAIT_UP:

orientationListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_UI) {
        public void onOrientationChanged(int orientation) {
            if(canShow(orientation)){
                show();
            } else if(canDismiss(orientation)){
                dismiss();
            }
        }
    };

@Override
public void onResume(){
    super.onResume();
    orientationListener.enable();
}

@Override
public void onPause(){
    super.onPause();
    orientationListener.disable();
}

private boolean isLandscape(int orientation){
        return orientation >= (90 - THRESHOLD) && orientation <= (90 + THRESHOLD);
    }

private boolean isPortrait(int orientation){
    return (orientation >= (360 - THRESHOLD) && orientation <= 360) || (orientation >= 0 && orientation <= THRESHOLD);
}

public boolean canShow(int orientation){
    return !visible && isLandscape(orientation);
}

public boolean canDismiss(int orientation){
    return visible && !dismissing && isPortrait(orientation);
}
剩一世无双 2024-12-24 20:01:31

嗨,尖叫声是您要找的吗?

// Set background image, rotatable
    View view = getWindow().getDecorView(); 
    int orientation = getResources().getConfiguration().orientation; 
    if (Configuration.ORIENTATION_LANDSCAPE == orientation) { 
        //Do SomeThing; // Landscape
    } else { 
        //Do SomeThing;  // Portrait
    } 

Hi screamingnoises is this what you`re looking for?

// Set background image, rotatable
    View view = getWindow().getDecorView(); 
    int orientation = getResources().getConfiguration().orientation; 
    if (Configuration.ORIENTATION_LANDSCAPE == orientation) { 
        //Do SomeThing; // Landscape
    } else { 
        //Do SomeThing;  // Portrait
    } 
夜深人未静 2024-12-24 20:01:31

我创建了以下类来检测方向变化,保持我的活动原始方向:

public class SensorOrientationChangeNotifier {

    public final String TAG = getClass().getSimpleName();
    private ArrayList<WeakReference<SensorOrientationChangeNotifier.Listener>> mListeners = new ArrayList<WeakReference<SensorOrientationChangeNotifier.Listener>>(3);

    private int mOrientation = 0;
    private SensorEventListener mSensorEventListener;
    private SensorManager mSensorManager;

    private static SensorOrientationChangeNotifier mInstance;

    public static SensorOrientationChangeNotifier getInstance() {
        if (mInstance == null)
            mInstance = new SensorOrientationChangeNotifier();

        return mInstance;
    }

    private SensorOrientationChangeNotifier() {
        mSensorEventListener = new NotifierSensorEventListener();
        Context applicationContext = GlobalData.getInstance().getContext();
        mSensorManager = (SensorManager) applicationContext.getSystemService(Context.SENSOR_SERVICE);

    }

    /**
     * Call on activity reset()
     */
    private void onResume() {
        mSensorManager.registerListener(mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
    }

    /**
     * Call on activity onPause()
     */
    private void onPause() {
        mSensorManager.unregisterListener(mSensorEventListener);
    }

    private class NotifierSensorEventListener implements SensorEventListener {

        @Override
        public void onSensorChanged(SensorEvent event) {
            float x = event.values[0];
            float y = event.values[1];
            int newOrientation = mOrientation;
            if (x < 5 && x > -5 && y > 5)
                newOrientation = 0;
            else if (x < -5 && y < 5 && y > -5)
                newOrientation = 90;
            else if (x < 5 && x > -5 && y < -5)
                newOrientation = 180;
            else if (x > 5 && y < 5 && y > -5)
                newOrientation = 270;

            //Log.e(TAG,"mOrientation="+mOrientation+"   ["+event.values[0]+","+event.values[1]+","+event.values[2]+"]");
            if (mOrientation != newOrientation){
                mOrientation = newOrientation;
                notifyListeners();
            }

        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }

    }

    public int getOrientation() {
        return mOrientation;
    }

    public interface Listener {
        void onOrientationChange(int orientation);
    }

    public void addListener(SensorOrientationChangeNotifier.Listener listener) {
        if (get(listener) == null) // prevent duplications
            mListeners.add(new WeakReference<SensorOrientationChangeNotifier.Listener>(listener));

        if (mListeners.size() == 1) {
            onResume(); // this is the first client
        }
    }

    public void remove(SensorOrientationChangeNotifier.Listener listener) {
        WeakReference<SensorOrientationChangeNotifier.Listener> listenerWR = get(listener);
        remove(listenerWR);
    }

    private void remove(WeakReference<SensorOrientationChangeNotifier.Listener> listenerWR) {
        if (listenerWR != null)
            mListeners.remove(listenerWR);

        if (mListeners.size() == 0) {
            onPause();
        }

    }

    private WeakReference<SensorOrientationChangeNotifier.Listener> get(SensorOrientationChangeNotifier.Listener listener) {
        for (WeakReference<SensorOrientationChangeNotifier.Listener> existingListener : mListeners)
            if (existingListener.get() == listener)
                return existingListener;
        return null;
    }

    private void notifyListeners() {
        ArrayList<WeakReference<SensorOrientationChangeNotifier.Listener>> deadLiksArr = new ArrayList<WeakReference<SensorOrientationChangeNotifier.Listener>>();
        for (WeakReference<SensorOrientationChangeNotifier.Listener> wr : mListeners) {
            if (wr.get() == null)
                deadLiksArr.add(wr);
            else
                wr.get().onOrientationChange(mOrientation);
        }

        // remove dead references 
        for (WeakReference<SensorOrientationChangeNotifier.Listener> wr : deadLiksArr) {
            mListeners.remove(wr);
        }
    }

    public boolean isPortrait(){
        return mOrientation == 0 || mOrientation == 180;
    }

    public boolean isLandscape(){
        return !isPortrait();
    }
}

按如下方式使用它:

在 AndroidManifest.xml 中 -

    <activity
        ...
        android:screenOrientation="portrait"
        >

在您的活动中:

public class MainActivity extends Activity implements  SensorOrientationChangeNotifier.Listener {

    @Override
    protected void onResume() {
        super.onResume();

        SensorOrientationChangeNotifier.getInstance().addListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        SensorOrientationChangeNotifier.getInstance().remove(this);
    }

    @Override
    public void onOrientationChange(int orientation) {
            if (orientation == 90 || orientation == 270){
                 // Do some landscape stuff
                } else {
                 // Do some portrait stuff
                 }
        }
    }
}

I created the following class to detect orientation changes, keeping my activity original orientation:

public class SensorOrientationChangeNotifier {

    public final String TAG = getClass().getSimpleName();
    private ArrayList<WeakReference<SensorOrientationChangeNotifier.Listener>> mListeners = new ArrayList<WeakReference<SensorOrientationChangeNotifier.Listener>>(3);

    private int mOrientation = 0;
    private SensorEventListener mSensorEventListener;
    private SensorManager mSensorManager;

    private static SensorOrientationChangeNotifier mInstance;

    public static SensorOrientationChangeNotifier getInstance() {
        if (mInstance == null)
            mInstance = new SensorOrientationChangeNotifier();

        return mInstance;
    }

    private SensorOrientationChangeNotifier() {
        mSensorEventListener = new NotifierSensorEventListener();
        Context applicationContext = GlobalData.getInstance().getContext();
        mSensorManager = (SensorManager) applicationContext.getSystemService(Context.SENSOR_SERVICE);

    }

    /**
     * Call on activity reset()
     */
    private void onResume() {
        mSensorManager.registerListener(mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
    }

    /**
     * Call on activity onPause()
     */
    private void onPause() {
        mSensorManager.unregisterListener(mSensorEventListener);
    }

    private class NotifierSensorEventListener implements SensorEventListener {

        @Override
        public void onSensorChanged(SensorEvent event) {
            float x = event.values[0];
            float y = event.values[1];
            int newOrientation = mOrientation;
            if (x < 5 && x > -5 && y > 5)
                newOrientation = 0;
            else if (x < -5 && y < 5 && y > -5)
                newOrientation = 90;
            else if (x < 5 && x > -5 && y < -5)
                newOrientation = 180;
            else if (x > 5 && y < 5 && y > -5)
                newOrientation = 270;

            //Log.e(TAG,"mOrientation="+mOrientation+"   ["+event.values[0]+","+event.values[1]+","+event.values[2]+"]");
            if (mOrientation != newOrientation){
                mOrientation = newOrientation;
                notifyListeners();
            }

        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }

    }

    public int getOrientation() {
        return mOrientation;
    }

    public interface Listener {
        void onOrientationChange(int orientation);
    }

    public void addListener(SensorOrientationChangeNotifier.Listener listener) {
        if (get(listener) == null) // prevent duplications
            mListeners.add(new WeakReference<SensorOrientationChangeNotifier.Listener>(listener));

        if (mListeners.size() == 1) {
            onResume(); // this is the first client
        }
    }

    public void remove(SensorOrientationChangeNotifier.Listener listener) {
        WeakReference<SensorOrientationChangeNotifier.Listener> listenerWR = get(listener);
        remove(listenerWR);
    }

    private void remove(WeakReference<SensorOrientationChangeNotifier.Listener> listenerWR) {
        if (listenerWR != null)
            mListeners.remove(listenerWR);

        if (mListeners.size() == 0) {
            onPause();
        }

    }

    private WeakReference<SensorOrientationChangeNotifier.Listener> get(SensorOrientationChangeNotifier.Listener listener) {
        for (WeakReference<SensorOrientationChangeNotifier.Listener> existingListener : mListeners)
            if (existingListener.get() == listener)
                return existingListener;
        return null;
    }

    private void notifyListeners() {
        ArrayList<WeakReference<SensorOrientationChangeNotifier.Listener>> deadLiksArr = new ArrayList<WeakReference<SensorOrientationChangeNotifier.Listener>>();
        for (WeakReference<SensorOrientationChangeNotifier.Listener> wr : mListeners) {
            if (wr.get() == null)
                deadLiksArr.add(wr);
            else
                wr.get().onOrientationChange(mOrientation);
        }

        // remove dead references 
        for (WeakReference<SensorOrientationChangeNotifier.Listener> wr : deadLiksArr) {
            mListeners.remove(wr);
        }
    }

    public boolean isPortrait(){
        return mOrientation == 0 || mOrientation == 180;
    }

    public boolean isLandscape(){
        return !isPortrait();
    }
}

Use it as follows:

In AndroidManifest.xml -

    <activity
        ...
        android:screenOrientation="portrait"
        >

In your activity:

public class MainActivity extends Activity implements  SensorOrientationChangeNotifier.Listener {

    @Override
    protected void onResume() {
        super.onResume();

        SensorOrientationChangeNotifier.getInstance().addListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        SensorOrientationChangeNotifier.getInstance().remove(this);
    }

    @Override
    public void onOrientationChange(int orientation) {
            if (orientation == 90 || orientation == 270){
                 // Do some landscape stuff
                } else {
                 // Do some portrait stuff
                 }
        }
    }
}
影子的影子 2024-12-24 20:01:31

Asaf Pinhassi 答案的 kotlin 版本。

import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import java.lang.ref.WeakReference
import java.util.*

class SensorOrientationChangeNotifier private constructor(context: Context) {
val TAG = javaClass.simpleName
private val mListeners = ArrayList<WeakReference<Listener?>>(3)
var orientation = 0
    private set
private val mSensorEventListener: SensorEventListener
private val mSensorManager: SensorManager

/**
 * Call on activity reset()
 */
private fun onResume() {
    mSensorManager.registerListener(mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL)
}

/**
 * Call on activity onPause()
 */
private fun onPause() {
    mSensorManager.unregisterListener(mSensorEventListener)
}

private inner class NotifierSensorEventListener : SensorEventListener {
    override fun onSensorChanged(event: SensorEvent) {
        val x = event.values[0]
        val y = event.values[1]
        var newOrientation: Int = orientation
        if (x < 5 && x > -5 && y > 5) newOrientation = 0 else if (x < -5 && y < 5 && y > -5) newOrientation = 90 else if (x < 5 && x > -5 && y < -5) newOrientation = 180 else if (x > 5 && y < 5 && y > -5) newOrientation = 270

        //Log.e(TAG,"mOrientation="+mOrientation+"   ["+event.values[0]+","+event.values[1]+","+event.values[2]+"]");
        if (orientation != newOrientation) {
            orientation = newOrientation
            notifyListeners()
        }
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}

interface Listener {
    fun onOrientationChange(orientation: Int)
}

fun addListener(listener: Listener) {
    if (get(listener) == null) // prevent duplications
        mListeners.add(WeakReference(listener))
    if (mListeners.size == 1) {
        onResume() // this is the first client
    }
}

fun remove(listener: Listener) {
    val listenerWR = get(listener)
    remove(listenerWR)
}

private fun remove(listenerWR: WeakReference<Listener?>?) {
    if (listenerWR != null) mListeners.remove(listenerWR)
    if (mListeners.size == 0) {
        onPause()
    }
}

private operator fun get(listener: Listener): WeakReference<Listener?>? {
    for (existingListener in mListeners) if (existingListener.get() === listener) return existingListener
    return null
}

private fun notifyListeners() {
    val deadLiksArr = ArrayList<WeakReference<Listener?>>()
    for (wr in mListeners) {
        if (wr.get() == null) deadLiksArr.add(wr) else wr.get()!!.onOrientationChange(orientation)
    }

    // remove dead references
    for (wr in deadLiksArr) {
        mListeners.remove(wr)
    }
}

val isPortrait: Boolean
    get() = orientation == 0 || orientation == 180

val isLandscape: Boolean
    get() = !isPortrait

companion object {
    private var mInstance: SensorOrientationChangeNotifier? = null
    fun getInstance(context: Context): SensorOrientationChangeNotifier? {
        if (mInstance == null) mInstance = SensorOrientationChangeNotifier(context)
        return mInstance
    }
}

init {
    mSensorEventListener = NotifierSensorEventListener()
    mSensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
}
}

A kotlin version of the Asaf Pinhassi answer.

import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import java.lang.ref.WeakReference
import java.util.*

class SensorOrientationChangeNotifier private constructor(context: Context) {
val TAG = javaClass.simpleName
private val mListeners = ArrayList<WeakReference<Listener?>>(3)
var orientation = 0
    private set
private val mSensorEventListener: SensorEventListener
private val mSensorManager: SensorManager

/**
 * Call on activity reset()
 */
private fun onResume() {
    mSensorManager.registerListener(mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL)
}

/**
 * Call on activity onPause()
 */
private fun onPause() {
    mSensorManager.unregisterListener(mSensorEventListener)
}

private inner class NotifierSensorEventListener : SensorEventListener {
    override fun onSensorChanged(event: SensorEvent) {
        val x = event.values[0]
        val y = event.values[1]
        var newOrientation: Int = orientation
        if (x < 5 && x > -5 && y > 5) newOrientation = 0 else if (x < -5 && y < 5 && y > -5) newOrientation = 90 else if (x < 5 && x > -5 && y < -5) newOrientation = 180 else if (x > 5 && y < 5 && y > -5) newOrientation = 270

        //Log.e(TAG,"mOrientation="+mOrientation+"   ["+event.values[0]+","+event.values[1]+","+event.values[2]+"]");
        if (orientation != newOrientation) {
            orientation = newOrientation
            notifyListeners()
        }
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}

interface Listener {
    fun onOrientationChange(orientation: Int)
}

fun addListener(listener: Listener) {
    if (get(listener) == null) // prevent duplications
        mListeners.add(WeakReference(listener))
    if (mListeners.size == 1) {
        onResume() // this is the first client
    }
}

fun remove(listener: Listener) {
    val listenerWR = get(listener)
    remove(listenerWR)
}

private fun remove(listenerWR: WeakReference<Listener?>?) {
    if (listenerWR != null) mListeners.remove(listenerWR)
    if (mListeners.size == 0) {
        onPause()
    }
}

private operator fun get(listener: Listener): WeakReference<Listener?>? {
    for (existingListener in mListeners) if (existingListener.get() === listener) return existingListener
    return null
}

private fun notifyListeners() {
    val deadLiksArr = ArrayList<WeakReference<Listener?>>()
    for (wr in mListeners) {
        if (wr.get() == null) deadLiksArr.add(wr) else wr.get()!!.onOrientationChange(orientation)
    }

    // remove dead references
    for (wr in deadLiksArr) {
        mListeners.remove(wr)
    }
}

val isPortrait: Boolean
    get() = orientation == 0 || orientation == 180

val isLandscape: Boolean
    get() = !isPortrait

companion object {
    private var mInstance: SensorOrientationChangeNotifier? = null
    fun getInstance(context: Context): SensorOrientationChangeNotifier? {
        if (mInstance == null) mInstance = SensorOrientationChangeNotifier(context)
        return mInstance
    }
}

init {
    mSensorEventListener = NotifierSensorEventListener()
    mSensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
}
}
月下客 2024-12-24 20:01:31

为了检测方向,我们将要求 Activity 向我们提供 Activity 的宽度和高度,这样我们就可以判断 Width > 是否为 Width > 。高度将是“横向”或相反高度>宽度为“肖像”-以下代码经过测试并且可以工作。

@SuppressWarnings("deprecation")
public void detectScreenOrientation(){
WindowManager wm = getWindowManager();
Display d = wm.getDefaultDisplay();
if (d.getWidth() > d.getHeight()){
    Log.d("Orientation","Landscape mode");
}
else {
    Log.d("Orientation", "Portrait mode");
}
}

To detect orientation, we will ask the activity to provide us with width and height of the activity, so we can find if Width > Height which will be "Landscape" or the opposite Height > width which is "Portrait" - The Following Code is tested and Working.

@SuppressWarnings("deprecation")
public void detectScreenOrientation(){
WindowManager wm = getWindowManager();
Display d = wm.getDefaultDisplay();
if (d.getWidth() > d.getHeight()){
    Log.d("Orientation","Landscape mode");
}
else {
    Log.d("Orientation", "Portrait mode");
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文