Android: Zezwalaj na portret i krajobraz dla tabletów, ale Wymuś portret na telefonie?

Chciałbym, aby Tablety mogły być wyświetlane w pionie i poziomie (sw600dp lub nowszy), ale telefony mają być ograniczone tylko do portretu. Nie mogę znaleźć sposobu, aby warunkowo wybrać orientację. Jakieś sugestie?

Author: Kenny Wyland, 2012-03-09

8 answers

Oto dobry sposób na wykorzystanie zasobów i kwalifikatorówRozmiar .

Umieść ten zasób bool w res / values jako bool.xml czy cokolwiek (nazwy plików tu nie mają znaczenia):

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <bool name="portrait_only">true</bool>
    </resources>

Umieść ten w res / values-sw600dp i Res / values-xlarge:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <bool name="portrait_only">false</bool>
    </resources>

Zobacz ta dodatkowa odpowiedź aby uzyskać pomoc w dodawaniu tych katalogów i plików w Android Studio.

Następnie w metodzie onCreate swoich działań możesz to zrobić:

    if(getResources().getBoolean(R.bool.portrait_only)){
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

Urządzenia, które są więcej niż 600 dp w kierunku najmniejszej szerokości lub X-large na urządzeniach z Androidem 3.2 (W zasadzie Tablety) będzie zachowywać się jak normalnie, w oparciu o czujnik i obrót zablokowany przez użytkownika itp. Wszystko inne (telefony, praktycznie) będzie tylko portretowe.

 407
Author: Brian Christensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:08

Możesz spróbować w ten sposób najpierw uzyskać rozmiar ekranu urządzenia

if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {     
    Toast.makeText(this, "Large screen",Toast.LENGTH_LONG).show();

}
else if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {     
    Toast.makeText(this, "Normal sized screen" , Toast.LENGTH_LONG).show();

} 
else if ((getResources().getConfiguration().screenLayout &      Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {     
    Toast.makeText(this, "Small sized screen" , Toast.LENGTH_LONG).show();
}
else {
    Toast.makeText(this, "Screen size is neither large, normal or small" , Toast.LENGTH_LONG).show();
}

A następnie Ustaw orientację zgodnie z tym

setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 28
Author: Avi Kumar Manku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-21 15:03:21

Oto Jak to zrobiłem (zainspirowany http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html ):

W AndroidManifest.xml , dla każdej aktywności, którą chcesz mieć możliwość zmiany między pionowym a poziomym (upewnij się, że dodałeś screenSize - nie potrzebowałeś tego!) Nie musisz tutaj ustawiać orientacji ekranu. :
android:configChanges="keyboardHidden|orientation|screenSize"

Metody dodawania do każdego działania:

public static boolean isXLargeScreen(Context context) {
    return (context.getResources().getConfiguration().screenLayout
    & Configuration.SCREENLAYOUT_SIZE_MASK)
    >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
} 

I: (jeśli nie nadpisasz tej metody, aplikacja wywoła onCreate () podczas zmiany orientacji)

@Override
public void onConfigurationChanged (Configuration newConfig)
{       
    super.onConfigurationChanged(newConfig);

    if (!isXLargeScreen(getApplicationContext()) ) {            
        return; //keep in portrait mode if a phone      
    }

    //I set background images for landscape and portrait here
}

W onCreate() każdego działania:

if (!isXLargeScreen(getApplicationContext())) { //set phones to portrait; 
   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);            
}
else {
  //I set background images here depending on portrait or landscape orientation 
}

Jedyną rzeczą, której nie mogę zrozumieć, jest to, jak sprawić, by aplikacja zmieniała Pliki Układów podczas przełączania z poziomego na pionowy lub odwrotnie. Zakładam, że odpowiedź robi coś podobnego do tego, co robi powyższy link, ale nie mogłem tego zrobić dla mnie - usunął wszystkie moje dane. Ale jeśli masz wystarczająco prostą aplikację, że masz ten sam plik układu dla orientacji pionowej i poziomej, to powinno zadziałać.

 8
Author: Ginny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-26 13:41:42

Uzupełnienie do zaakceptowanej odpowiedzi

Możesz wykonać następujące kroki w Android Studio, aby dodać katalogi res/values-sw600dp i res/values-large z ich plikami bools.xml.

Wartości-sw600dp

Przede wszystkim z zakładki projekt wybierz filtr projekt (a nie Android) w nawigatorze.

Tutaj wpisz opis obrazka

Następnie kliknij prawym przyciskiem myszy katalog app/src/main/res. Wybierz Nowy > Android Resource Directory .

Wybierz najmniejsza szerokość ekranu, a następnie naciśnij >> guzik.

Tutaj wpisz opis obrazka

Wpisz 600 dla najmniejszej szerokości ekranu. Nazwa katalogu zostanie wygenerowana automatycznie. Powiedz OK.

Tutaj wpisz opis obrazka

Następnie kliknij prawym przyciskiem myszy na nowo utworzonym pliku values-sw600dp. Wybierz Nowy > Values resource file . Wpisz bools dla nazwy.

Wartości-Duże

Dodanie katalogu values-large jest konieczne tylko wtedy, gdy obsługują pre Android 3.2 (poziom API 13). W przeciwnym razie możesz pominąć ten krok. Katalog values-large odpowiada values-sw600dp. (values-xlarge odpowiada values-sw720dp.)

Aby utworzyć katalog values-large, wykonaj te same kroki jak powyżej, ale w tym przypadku wybierz Rozmiar zamiast najmniejszą szerokość ekranu. Wybierz Duży . Nazwa katalogu zostanie wygenerowana automatycznie.

Tutaj wpisz opis obrazka

Kliknij prawym przyciskiem myszy katalog jak poprzednio, aby utworzyć plik bools.xml.

 7
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:26

Cóż, to trochę za późno, ale tutaj jest XML-Only ale hack rozwiązanie, które nie odtwarza aktywności, jak setRequestedOrientation robi, jeśli ma zmienić orientację:

Https://stackoverflow.com/a/27015879/1281930

 4
Author: guness,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:07

Po odpowiedź Ginny, myślę, że najbardziej niezawodny sposób, aby to zrobić jest następujący:

Jak opisano tutaj , umieść logikę w zasobach sw600dp. Musi mieć prefiks sw w przeciwnym razie nie będzie działać poprawnie:

W res / wartościach-sw600dp / dimens.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="isTablet">true</bool>
</resources>

W res / values / dimens.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="isTablet">false</bool>
</resources>

Następnie wykonaj metodę, aby odzyskać ten boolean:

public class ViewUtils {
    public static boolean isTablet(Context context){
        return context.getResources().getBoolean(R.bool.isTablet);
    }
}

I podstawowej działalności, aby rozszerzyć z działań, gdzie chcesz to zachowanie:

public abstract class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (!ViewUtils.isTablet(this)) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }
}

Więc każda aktywność rozszerzyłaby BaseActivity:

public class LoginActivity extends BaseActivity //....

Ważne : nawet jeśli rozciągasz się od BaseActivity, musisz dodać linię android:configChanges="orientation|screenSize" do każdego Activity W AndroidManifest.xml:

    <activity
        android:name=".login.LoginActivity"
        android:configChanges="orientation|screenSize">
    </activity>
 4
Author: RominaV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:07

Wiem stare pytanie. Aby uruchomić aplikację zawsze w trybie pionowym, nawet gdy orientacja może być lub jest zamieniana itp. (na przykład na tabletach) zaprojektowałem tę funkcję, która służy do ustawiania urządzenia w odpowiedniej orientacji bez potrzeby wiedzieć, jak funkcje pionowe i poziome są zorganizowane na urządzeniu.

   private void initActivityScreenOrientPortrait()
    {
        // Avoid screen rotations (use the manifests android:screenOrientation setting)
        // Set this to nosensor or potrait

        // Set window fullscreen
        this.activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        DisplayMetrics metrics = new DisplayMetrics();
        this.activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

         // Test if it is VISUAL in portrait mode by simply checking it's size
        boolean bIsVisualPortrait = ( metrics.heightPixels >= metrics.widthPixels ); 

        if( !bIsVisualPortrait )
        { 
            // Swap the orientation to match the VISUAL portrait mode
            if( this.activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT )
             { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); }
            else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ); }
        }
        else { this.activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); }

    }
Działa jak czar!

Zawiadomienie: Zmień this.activity według swojej aktywności lub dodaj ją do głównej aktywności i usuń this.activity ;-)

Jeśli chcesz zrobić przeciwnie, musisz zmienić kod na krajobraz (ale myślę, że jest jasne, jak to zrobić).

 0
Author: Codebeat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-13 15:54:21

Niestety, używając metody setRequestedOrientation(...) spowoduje ponowne uruchomienie aktywności, więc nawet jeśli wywołasz ją w metodzie onCreate, przejdzie ona przez cykl życia aktywności, a następnie odtworzy tę samą aktywność w żądanej orientacji. Tak więc przy odpowiedzi @ Brian Christensen powinieneś wziąć pod uwagę, że kod aktywności może być wywołany dwa razy, może to mieć złe efekty (nie tylko wizualne, ale także przy żądaniach sieciowych, analitycznych itp.).

Ponadto, aby ustawienie atrybutu configChanges w manifeście jest moim zdaniem dużym kompromisem, który może wymagać ogromnych kosztów refaktoryzacji. twórcy Androida nie zalecają zmiany tego atrybutu .

Wreszcie, próba ustawienia screen orientation w jakiś sposób inaczej (aby uniknąć problemu ponownego uruchamiania) jest niemożliwa, statycznie niemożliwa ze względu na statyczny manifest, którego nie można zmienić, programowo jest możliwe tylko wywołanie tej metody w już uruchomionej aktywności.

Podsumowanie: moim zdaniem sugestia @Brian Christensen jest najlepszym kompromisem, ale pamiętaj o problemie z ponownym uruchomieniem.

 0
Author: mathew11,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-03 16:01:15