Android: Bir Aktivitedeki yön değişikliklerini geçici olarak devre dışı bırakın


116

Ana faaliyetim, kesintiye uğramaması gereken bazı veritabanı değişikliklerini yapan bir kod içeriyor. Ağır kaldırmayı başka bir iş parçacığında yapıyorum ve iptal edilemez olarak belirlediğim bir ilerleme iletişim kutusu kullanıyorum. Ancak, telefonumu döndürürsem, çalışmakta olan işlem için GERÇEKTEN kötü olan etkinliği yeniden başlattığını ve Kapatmaya Zorla aldığımı fark ettim.

Yapmak istediğim şey, sürecim tamamlanana kadar ekran yönü değişikliklerini programlı olarak devre dışı bırakmak, bu sırada yönelim değişiklikleri etkinleştirilir.


Kimse bu kısımdan bahsetmiyor gibi göründüğünden, ActivityInfo tanımlayıcısını kullanmak için android.content.pm.ActivityInfo'yu içe aktarmak isteyeceksiniz.
zsalwasser


1
Bakın: en iyi çözüm için stackoverflow.com/a/32885911/2673792
Sudhir Sinha

Yanıtlar:


165

Chris'in kendi kendine cevabında açıkladığı gibi ,

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

ve sonra

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

gerçekten cazibe gibi çalışıyor ... gerçek cihazlarda!

Emülatörde test ederken bozuk olduğunu düşünmeyin, ctrl + F11 kısayolu HER ZAMAN sensör hareketlerini taklit etmeden ekran yönünü değiştirir.

DÜZENLEME: Bu mümkün olan en iyi cevap değildi. Yorumlarda açıklandığı gibi, bu yöntemle ilgili sorunlar var. Gerçek cevap burada .


Bu sabitleri bulamadım. Bunun için teşekkürler.
Christopher Perry

41
Bu yöntemlerle ilgili bir sorun var ... setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); aygıt varsayılan yön kullanımında olmadığında, etkinlik yönü hemen aygıtın varsayılan yönüne değiştirilir (yok edilir ve yeniden oluşturulur). Örneğin, bir telefonda, onu yatay yönde tutarsanız, sensörleri yeniden etkinleştirirken etkinlik portreye ve tekrar yataya geçer. Archos A5 IT ile aynı zıt sorun: onu dikeyde kullanmak, aktivitenin manzaraya ve tekrar portreye geçmesine neden olur.
Kevin Gaudin

1
Orijinal sorunun gerçek cevabı orada: stackoverflow.com/questions/3821423/…
Kevin Gaudin

2
Bu benim için işe yaramadı. Ancak bu işe yaradı: stackoverflow.com/a/10488012/1369016 setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) çağırmak zorunda kaldım; veya setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); getResources (). getConfiguration (). orientation öğesinden alınan geçerli yönlendirmeye göre.
Tiago

ActivityInfo.SCREEN_ORIENTATION_SENSORAndroid'in yerel yönlendirme kilidine saygı göstermez. Yönlendirme sıfırlanıyor ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED.
tvkanters

43

Diğer yanıtların hiçbiri benim için mükemmel bir hile yapmadı, ama işte bunun işe yaradığını buldum.

Yönü akıma kilitle ...

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

Yön değiştirmeye tekrar izin verilmesi gerektiğinde, varsayılana geri dönün ...

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

9
Bununla ilgili sorun Configuration.ORIENTATION_PORTRAIT, her iki manzara modunda da (yani 'normal' ve tersine çevrilmiş) döndürülecek olmasıdır. Dolayısıyla, telefon ters yatay yöndeyse ve siz onu ayarlarsanız ActivityInfo.SCREEN_ORIENTATION_LANDSCAPEbaş aşağı dönecektir. API 9'da ActivityInfo SCREEN_ORIENTATION_REVERSE_LANDSCAPEsabiti tanıtır , ancak Configurationsınıf aracılığıyla böyle bir yönelimi tespit etmenin bir yolunu görmüyorum .
Błażej Czapp

1
Bu işe yaradı. Yukarıdaki endişenin cevabı bu cevapta yer almaktadır. stackoverflow.com/a/10453034/1223436
Zack

İhtiyaçlarım için de bir cazibe gibi çalıştı, mükemmel teşekkürler
user2029541

39

İşte API 8+ için çalışan, ters dikey ve yatay için çalışan ve "doğal" yönün yatay olduğu bir Galaxy sekmesinde çalışan daha eksiksiz ve güncel bir çözüm ( activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)yönün kilidini açma çağrısı ):

@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);
    }
}

Tablet ve telefonlarla benim için harika çalıştı.
ScruffyFox

Benim için her türlü cihazda çalışan tek doğru cevap.
amdev

Kesinlikle en iyi cevap! Bu yöntemi yapabilir staticve Activity activityparametre olarak ekleyebilirsiniz .
2014

18

Ters yönelim modlarını da yönetmek için, bu kodu etkinlik yönünü düzeltmek için kullandım:

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;
    }

Ve yeniden yönlendirmeye izin vermek için:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

17

kullanım setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);Yatay veya dikey olması fark etmeksizin mevcut yönlendirmeyi kilitlemek için .

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);Yönün kilidini açmak için kullanın .


Kısa bir geçici kilit için en iyi çözüm. Sensörün mevcut yönüyle uğraşmak yok.
İnanılmaz Ocak

2
Build.VERSION.SDK_INT> = 18 üzerinde çalışır, bu sayfada tdjprog tarafından daha eksiksiz bir cevap verilir stackoverflow.com/a/41812971/5235263
bastami82


11

Hepinize teşekkürler. Önceki duruma geri yüklediğimden emin olmak için Pilot_51'in çözümünü değiştirdim. Ayrıca yatay olmayan ve dikey olmayan ekranları desteklemek için bir değişiklik yaptım (ancak böyle bir ekranda test etmedim).

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);
}

Sonra onu geri yüklemek için

setRequestedOrientation(prevOrientation);

İyi şeyler - neden switcholsa kullanmadığınızdan emin değilim .

Üçüncü seçeneği ekledikten sonra temizlemeyi ve bir anahtara geçmeyi unuttum.
ProjectJourneyman

Etkinlik nesnesine erişiminiz yoksa, yalnızca 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
}

Cevabınıza biraz açıklama ekler misiniz lütfen?
slfan

Arka planda bazı işleriniz olduğunda, yönlendirmeyi kilitlemek ve mevcut etkinliği yeniden oluşturmak için yok etmeyi önlemek için setLockScreenOrientation (true) çağırmanız yeterlidir. bu işlerin bittiğinden emin olduğunuzda, setLockScreenOrientation (false) çağırın.
tdjprog

2
bu en iyi cevap!
Fakher

7

İşte her seferinde çalışan ve mevcut yönelimi koruyan bir çözüm ( Activity.Info.SCREEN_ORIENTATION_PORTRAITörneğin 0 ° 'ye kadar olan setleri kullanarak , ancak kullanıcı mevcut olanla 180 ° yönelim olabilir).

// 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);
}

2
Söylemeye değer: Yalnızca API 18+
Dmitry Zaytsev

1

kullanmak ActivityInfo.SCREEN_ORIENTATION_USEREğer onun cihazda etkinleştirilmiş yalnızca döndürme ekrana istiyorum.


1

Bu benim için mükemmel çalışıyor. Tablet / telefonun farklı "doğal yönelimi" ile sorunu çözer;)

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

Ekranın dönüşüne bağlı olan ve ardından cihazın yönüne karar veren bir çözüm buldum. Yönü bildiğimizden, yönlendirmeyi kilitleyebilir ve gerektiğinde daha sonra serbest bırakabiliriz. Bu çözüm aynı zamanda cihazın ters manzara modunda olup olmadığını da belirleyebilir .

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;
    }
}

Daha sonra yönlendirmeyi serbest bırakmamız gerekirse, bu yöntemi çağırabiliriz:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

0

Bence bu kodun okunması daha kolay.

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

Dört olasılığı kapsamak için mevcut rotasyon / oryantasyon değerlerinin bir kombinasyonunun gerekli olduğunu buldum; dikey / yatay değerler ve cihazın doğal yönü var. Ekran "doğal" dikey veya yatay yöndeyken cihazların doğal yönünün 0 derece döndürme değerine sahip olacağını varsayalım. Benzer şekilde, yatay veya dikey konumdayken 90 derecelik bir dönüş değeri olacaktır (0 derecedeki yönün tersi olduğuna dikkat edin). Dolayısıyla, 0 veya 90 derece olmayan döndürme değerleri, "Ters" yönelim anlamına gelecektir. Tamam, işte bazı kodlar:

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

Buradaki cevapların çoğunu beğenmedim, çünkü kilidinin kilidini açarken önceki durumun aksine UNSPECIFIED olarak ayarladılar. ProjectJourneyman bunu hesaba kattı, bu harikaydı, ancak Roy'un kilitleme kodunu tercih ettim. Yani benim tavsiyem ikisinin bir karışımı olacaktır:

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

Kullanabilirsiniz

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;
    }
}

-1

o kod satırını kullan

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  

etkinliğinizde oncreate yöntemi

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.