Android:アクティビティの向きの変更を一時的に無効にする


116

私の主な活動には、中断されるべきではないデータベースの変更を行うコードがあります。別のスレッドで重い作業を行っており、キャンセル不可として設定した進行状況ダイアログを使用しています。しかし、私は自分の電話を回転させると、実行中のプロセスにとって本当に悪いアクティビティを再開し、強制的に閉じることに気づきました。

私がやりたいことは、プロセスが完了するまで画面の向きの変更をプログラムで無効にし、その時点で向きの変更を有効にすることです。


この部分については誰も触れていないようなので、ActivityInfo識別子を使用するためにandroid.content.pm.ActivityInfoをインポートする必要があります。
zsalwasser


1
参照:stackoverflow.com/a/32885911/2673792最適なソリューション
Sudhir Sinha

回答:


165

クリスが自己回答で説明したように、

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

その後

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

本当に魅力のように動作します...実際のデバイスで!

エミュレーターでテストするときに壊れているとは思わないでください。センサーの動きをエミュレートすることなく、ctrl + F11ショートカットは常に画面の向きを変更します。

編集:これは可能な最良の答えではありませんでした。コメントで説明されているように、この方法には問題があります。本当の答えはここにあります


それらの定数を見つけることができませんでした。それをありがとう。
クリストファーペリー

41
これらのメソッドには問題があります... setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);を呼び出す場合のようです。デバイスがデフォルトの向きで使用されていない場合、アクティビティの向きはすぐにデバイスのデフォルトの向きに変更(破棄および再作成)されます。たとえば、スマートフォンで横向きにすると、センサーを再アクティブ化するとアクティビティが縦向きに切り替わり、横向きに戻ります。Archos A5 ITの同じ反対の問題:縦向きで使用すると、アクティビティが横向きに切り替わり、縦向きに戻ります。
Kevin Gaudin、

1
元の質問に本当の答えがあります:stackoverflow.com/questions/3821423/...
ケビン・ゴーダン

2
これは私にはうまくいきませんでした。これはうまくいきました:stackoverflow.com/a/10488012/1369016私はsetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);を呼び出さなければなりませんでした。またはsetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); getResources()。getConfiguration()。orientationから取得した現在の方向に基づいています。
ティアゴ

ActivityInfo.SCREEN_ORIENTATION_SENSORAndroidのネイティブ方向ロックを尊重しません。方向をリセットActivityInfo.SCREEN_ORIENTATION_UNSPECIFIEDします。
tvkanters

43

他の答えはどれも私にとって完璧なトリックはしませんでしたが、これが私が見つけたものです。

現在の方向にロック...

if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

方向の変更を再度許可する必要がある場合は、デフォルトに戻します...

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

9
この問題Configuration.ORIENTATION_PORTRAITは、両方のランドスケープモード(つまり、「通常」モードと反転)で返されることです。そのため、スマートフォンが横向きに反転してActivityInfo.SCREEN_ORIENTATION_LANDSCAPEいて、それに設定すると、上下が逆になります。API 9では、ActivityInfoによってSCREEN_ORIENTATION_REVERSE_LANDSCAPE定数が導入されていますが、Configurationクラスを通じてそのような方向を検出する方法がわかりません。
BłażejCzapp

1
これはうまくいきました。上記の懸念への答えはこの答えにあります。stackoverflow.com/a/10453034/1223436
Zack

あまりにも私のニーズのための魅力のように働いた、華麗な感謝
user2029541

39

これは、API 8+で機能し、逆ポートレートとランドスケープで機能し、「自然な」方向がランドスケープであるGalaxyタブで機能する、より完全で最新のソリューションです(activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)方向をロック解除するための呼び出し)。

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
public static void lockActivityOrientation(Activity activity) {
    Display display = activity.getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    int height;
    int width;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
        height = display.getHeight();
        width = display.getWidth();
    } else {
        Point size = new Point();
        display.getSize(size);
        height = size.y;
        width = size.x;
    }
    switch (rotation) {
    case Surface.ROTATION_90:
        if (width > height)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        break;
    case Surface.ROTATION_180:
        if (height > width)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        break;          
    case Surface.ROTATION_270:
        if (width > height)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        break;
    default :
        if (height > width)
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        else
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

タブレットと携帯電話で私にとってはうまくいきました。
ScruffyFox 2014

私にとってあらゆる種類のデバイスで機能する唯一の正しい答え。
amdev 2014

間違いなく最高の答えです!このメソッドstaticを作成しActivity activityて、パラメータとして追加できます。
2014

18

逆方向モードも管理するために、そのコードを使用してアクティビティの方向を修正しました。

int rotation = getWindowManager().getDefaultDisplay().getRotation();

    switch(rotation) {
    case Surface.ROTATION_180:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        break;
    case Surface.ROTATION_270:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);         
        break;
    case  Surface.ROTATION_0:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        break;
    case Surface.ROTATION_90:
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        break;
    }

そして再びオリエンテーションを許可するには:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

17

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);現在の向きを横向きまたは縦向きにロックするために使用 します。

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);方向のロックを解除するために使用します。


短い一時ロックの最善の解決策。センサーの現在の向きをいじる必要はありません。
驚異的な1

2
Build.VERSION.SDK_INT> = 18上で動作し、より完全な答えは、このページにtdjprogで与えられるstackoverflow.com/a/41812971/5235263
bastami82

14

答えを見つけました。これを行うには、アクティビティsetRequestedOrientation(int)で、ここで指定された値の1つを使用して呼び出すことができます:http : //developer.android.com/reference/android/R.attr.html#screenOrientation

スレッドを開始する前にsetRequestedOrientation(OFF)(OFF = nosensor)を呼び出し、スレッドが完了したときにsetRequestedOrientation(ON)(ON = sensor)を呼び出しました。魅力のように機能します。


11

皆さんありがとう。Pilot_51のソリューションを変更して、確実に前の状態に復元するようにしました。また、非横長および非縦長の画面をサポートするための変更も加えました(ただし、そのような画面ではテストしていません)。

prevOrientation = getRequestedOrientation();
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}

それを復元するには

setRequestedOrientation(prevOrientation);

良いもの-なぜあなたが使用しなかったのかわからないswitch

3番目のオプションを追加した後、クリーンアップしてスイッチに変更するのを忘れました。
ProjectJourneyman '27 / 06/27

アクティビティオブジェクトへのアクセス権がなく、コンテキストActivityInfo.SCREEN_ORIENTATION_NOSENSOR | ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
max4ever

8
protected void setLockScreenOrientation(boolean lock) {
    if (Build.VERSION.SDK_INT >= 18) {
        setRequestedOrientation(lock?ActivityInfo.SCREEN_ORIENTATION_LOCKED:ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        return;
    }

    if (lock) {
        switch (getWindowManager().getDefaultDisplay().getRotation()) {
            case 0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; // value 1
            case 2: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; // value 9
            case 1: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // value 0
            case 3: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; // value 8
        }
    } else
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); // value 10
}

回答に説明を追加していただけませんか?
slfan 2017年

バックグラウンドにいくつかのジョブがある場合は、setLockScreenOrientation(true)を呼び出して向きをロックし、現在のアクティビティを破棄しないようにして、アクティビティを再作成します。これらのジョブが完了したことを確認したら、setLockScreenOrientation(false)を呼び出します。
tdjprog

2
これが最良の答えです!
Fakher

7

これは毎回機能し、現在の方向を維持するソリューションです(Activity.Info.SCREEN_ORIENTATION_PORTRAITたとえば、0°に設定を使用しますが、ユーザーは現在の方向として180°の方向を持つことができます)。

// Scope: Activity

private void _lockOrientation() {
    if (super.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
    } else {
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
    }
}

private void _unlockOrientation() {
    super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}



1

これは私にとっては効果的です。タブレット/電話の「自然な向き」の問題を解決します;)

int rotation = getWindowManager().getDefaultDisplay().getRotation();

        Configuration config = getResources().getConfiguration();
        int naturalOrientation;

        if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
                config.orientation == Configuration.ORIENTATION_LANDSCAPE)
                || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
                config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
            naturalOrientation = Configuration.ORIENTATION_LANDSCAPE;
        } else {
            naturalOrientation = Configuration.ORIENTATION_PORTRAIT;
        }

        // because getRotation() gives "rotation from natural orientation" of device (different on phone and tablet)
        // we need to update rotation variable if natural orienation isn't 0 (mainly tablets)
        if (naturalOrientation == Configuration.ORIENTATION_LANDSCAPE)
            rotation = ++rotation % 4;

        switch (rotation) {
            case Surface.ROTATION_0: //0
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                break;
            case Surface.ROTATION_90: //1
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                break;
            case Surface.ROTATION_180: //2
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                break;
            case Surface.ROTATION_270: //3
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
                break;
        }
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }

0

ディスプレイの回転に依存し、デバイスの向きを決定するソリューションを考え出しました。向きを知ることで、向きをロックし、後で必要に応じて解放することができます。このソリューションは、デバイスがリバースランドスケープモードであるかどうかも判別できます。

private void lockOrientation(){
    switch (((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation()) {


        // Portrait
        case Surface.ROTATION_0:
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            break;


        //Landscape     
        case Surface.ROTATION_90: 
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            break;


        // Reversed landscape
        case Surface.ROTATION_270:
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);             
            break;
    }
}

その後、方向を解放する必要がある場合は、このメソッドを呼び出すことができます。

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

0

このコードは読みやすいと思います。

private void keepOrientation() {

    int orientation = getResources().getConfiguration().orientation;
    int rotation = getWindowManager().getDefaultDisplay().getRotation();

    switch (rotation) {
        case Surface.ROTATION_0:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            break;
        case Surface.ROTATION_90:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            break;
        case Surface.ROTATION_180:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
            break;
        default:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
    }
}

0

4つの可能性をカバーするには、既存の回転/方向の値の組み合わせが必要であることがわかりました。ポートレート/ランドスケープの値とデバイスの自然な向きがあります。画面が「自然な」縦向きまたは横向きの場合、デバイスの自然な向きは0度の回転値を持つとしましょう。同様に、横向きまたは縦向きの場合、回転値は90度になります(0度の向きとは反対です)。したがって、0度または90度以外の回転値は「逆」方向を意味します。さて、ここにいくつかのコードがあります:

public enum eScreenOrientation 
{
PORTRAIT (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT),
LANDSCAPE (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),
PORTRAIT_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT),
LANDSCAPE_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE),
UNSPECIFIED_ORIENTATION (ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

    public final int activityInfoValue;

    eScreenOrientation ( int orientation )
    {
        activityInfoValue = orientation;
    }
}



public eScreenOrientation currentScreenOrientation ( )
{
    final int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();

    final int orientation = getResources().getConfiguration().orientation;
    switch ( orientation ) 
    {
    case Configuration.ORIENTATION_PORTRAIT:
        if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 )
            return eScreenOrientation.PORTRAIT;
        else
            return eScreenOrientation.PORTRAIT_REVERSE;
    case Configuration.ORIENTATION_LANDSCAPE:
        if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 )
            return eScreenOrientation.LANDSCAPE;
        else
            return eScreenOrientation.LANDSCAPE_REVERSE;
    default:
        return eScreenOrientation.UNSPECIFIED_ORIENTATION;
    }
}

public void lockScreenOrientation ( )
    throws UnsupportedDisplayException
{
    eScreenOrientation currentOrientation = currentScreenOrientation( );
    if ( currentOrientation == eScreenOrientation.UNSPECIFIED_ORIENTATION )
        throw new UnsupportedDisplayException("Unable to lock screen - unspecified orientation");
    else
        setRequestedOrientation( currentOrientation.activityInfoValue );
}

public void unlockScreenOrientation (  )
{
    setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED );
}

0

ロック解除では以前の状態とは対照的にUNSPECIFIEDに設定されていたため、ここではほとんどの回答が気に入らなかった。ProjectJourneymanはそれを考慮に入れましたが、それは素晴らしかったですが、私はロイによるロックコードを好みました。したがって、私の推奨は2つの組み合わせです。

private int prevOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;

private void unlockOrientation() {
    setRequestedOrientation(prevOrientation);
}

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private void lockOrientation() {
    prevOrientation = getRequestedOrientation();
    Display display = getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    int height;
    int width;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
        height = display.getHeight();
        width = display.getWidth();
    } else {
        Point size = new Point();
        display.getSize(size);
        height = size.y;
        width = size.x;
    }
    switch (rotation) {
        case Surface.ROTATION_90:
            if (width > height)
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            else
                setRequestedOrientation(9/* reversePortait */);
            break;
        case Surface.ROTATION_180:
            if (height > width)
                setRequestedOrientation(9/* reversePortait */);
            else
                setRequestedOrientation(8/* reverseLandscape */);
            break;
        case Surface.ROTATION_270:
            if (width > height)
                setRequestedOrientation(8/* reverseLandscape */);
            else
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            break;
        default :
            if (height > width)
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            else
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

0

使用できます

public void swapOrientaionLockState(){
    try{
        if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1) {
            Display defaultDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, defaultDisplay.getRotation());
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0);
        } else {
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 1);
        }

        Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, !orientationIsLocked() ? 1 : 0);

    } catch (Settings.SettingNotFoundException e){
        e.printStackTrace();
    }
}

public boolean orientationIsLocked(){
    if(canModifiSetting(mContext)){
        try {
            return Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0;
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
    }
    return false;
}

public static boolean canModifiSetting(Context context){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return Settings.System.canWrite(context);
    } else {
        return true;
    }
}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.