Chciałbym, aby tablety mogły wyświetlać się w orientacji pionowej i poziomej (w rozdzielczości sw600dp lub większej), ale telefony powinny być ograniczone tylko do portretu. Nie mogę znaleźć żadnego warunkowego wyboru orientacji. Jakieś sugestie?
Chciałbym, aby tablety mogły wyświetlać się w orientacji pionowej i poziomej (w rozdzielczości sw600dp lub większej), ale telefony powinny być ograniczone tylko do portretu. Nie mogę znaleźć żadnego warunkowego wyboru orientacji. Jakieś sugestie?
Odpowiedzi:
Oto dobry sposób na użycie kwalifikatorów zasobów i rozmiaru .
Umieść ten zasób bool w res / wartości jako bools.xml lub cokolwiek innego (nazwy plików nie mają tutaj znaczenia):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
Umieść to w res / wartości-sw600dp i res / wartości-xlarge:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
Zobacz tę dodatkową odpowiedź aby uzyskać pomoc dotyczącą dodawania 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 o rozdzielczości większej niż 600 dp w kierunku najmniejszej szerokości lub x-large na urządzeniach z systemem Android w wersji wcześniejszej niż 3.2 (zasadniczo tablety) będą zachowywać się normalnie, w oparciu o czujnik i obrót zablokowany przez użytkownika itp . Wszystko inne (telefony, właściwie) będzie tylko portretem.
xlarge
czy mogę po prostu używać sw600dp
? Prawdopodobnie obecnie nie ma tabletów z <3.2.
onCreate()
. Kiedy przeniosłem połączenie na setRequestedOrientation()
inną pozycję w czasie i kontekście, restart się nie powtórzył.
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 zgodnie z tym orientację
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Configuration
dostarcza screenLayout
informacje - DPI. Pytanie dotyczy natomiast wielkości ekranu urządzenia fizycznego - telefonu VS tabletu. Oznacza to, że możesz mieć Configuration.SCREENLAYOUT_SIZE_NORMAL
i byłby to tablet MDPI.
Możesz wykonać następujące kroki w Android Studio, aby dodać do nich katalogi res/values-sw600dp
ires/values-large
bools.xml
plikami.
Przede wszystkim z zakładki Projekt wybierz filtr Nawigatora (zamiast Androida) w nawigatorze.
Następnie kliknij app/src/main/res
katalog prawym przyciskiem myszy . Wybierz Nowy > Katalog zasobów Androida .
Wybierz opcję Najmniejsza szerokość ekranu , a następnie naciśnij przycisk >> .
Wpisz 600
najmniejszą szerokość ekranu. Nazwa katalogu zostanie wygenerowana automatycznie. Powiedz ok.
Następnie kliknij prawym przyciskiem myszy nowo utworzony values-sw600dp
plik. Wybierz Nowy > Plik zasobów wartości . Rodzajbools
nazwę.
Dodanie values-large
katalogu jest konieczne tylko w przypadku obsługi systemu Android w wersji wcześniejszej niż 3.2 (API poziom 13). W przeciwnym razie możesz pominąć ten krok. values-large
Katalogu odpowiada values-sw600dp
. ( values-xlarge
odpowiada values-sw720dp
.)
Aby utworzyć values-large
katalog, wykonaj te same kroki, co powyżej, ale w tym przypadku wybierz opcję Rozmiar zamiast Najmniejszej szerokości ekranu. Wybierz Large . Nazwa katalogu zostanie wygenerowana automatycznie.
Kliknij katalog prawym przyciskiem myszy, aby utworzyć bools.xml
plik.
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 portretem a krajobrazem (pamiętaj, aby dodać screenSize - nie było to potrzebne!) Nie musisz tutaj ustawiać orientacji ekranu. :
android:configChanges="keyboardHidden|orientation|screenSize"
Metody dodawania w każdym działaniu:
public static boolean isXLargeScreen(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
i: (jeśli nie zastąpisz tej metody, aplikacja wywoła funkcję 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 funkcji 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
}
Jedyne, czego nie potrafię zrozumieć, to jak zmusić aplikację do zmiany plików układu podczas przełączania z orientacji poziomej na pionową lub odwrotnie. Zakładam, że odpowiedzią jest zrobienie czegoś podobnego do powyższego linku, ale nie mogłem tego zrobić dla mnie - usunęło to wszystkie moje dane. Ale jeśli masz na tyle prostą aplikację, że masz ten sam plik układu dla portretu i krajobrazu, to powinno działać.
Po odpowiedzi Ginny uważam, że najbardziej wiarygodnym sposobem jest:
Jak opisano tutaj , umieść wartość logiczną w zasobach sw600dp. Musi mieć prefiks sw, w przeciwnym razie nie będzie działał poprawnie:
w res / wartości-sw600dp / dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">true</bool>
</resources>
w res / wartości / dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">false</bool>
</resources>
Następnie utwórz metodę odzyskania wartości logicznej:
public class ViewUtils {
public static boolean isTablet(Context context){
return context.getResources().getBoolean(R.bool.isTablet);
}
}
I podstawowe działanie, które należy rozszerzyć z działań, w których chcesz tego zachowania:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!ViewUtils.isTablet(this)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
Dlatego każde działanie rozszerzy BaseActivity:
public class LoginActivity extends BaseActivity //....
Ważne : nawet jeśli przedłużasz BaseActivity
, musisz dodać linię android:configChanges="orientation|screenSize"
do każdego Activity
z pliku AndroidManifest.xml:
<activity
android:name=".login.LoginActivity"
android:configChanges="orientation|screenSize">
</activity>
Cóż, jest to trochę za późno, ale tutaj jest tylko XML, ale rozwiązanie hakerskie, które nie odtwarza działania tak setRequestedOrientation
, jakby miało zmienić orientację:
Po zaakceptowaniu odpowiedzi dodaję plik kotlin z rozwiązaniem, mam nadzieję, że komuś pomoże
Umieścić ten zasób bool w res/values
jak bools.xml lub cokolwiek (nazwy plików nie ma znaczenia tutaj):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
Włóż to res/values-sw600dp
i res/values-sw600dp-land
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
Następnie dodaj go poniżej linii w swojej aktywności lub fragmentacji
class MyActivity : Activity() {
@SuppressLint("SourceLockedOrientationActivity")
override fun onCreate(savedInstanceState: Bundle?) {
if (resources.getBoolean(R.bool.portrait_only)) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
super.onCreate(savedInstanceState)
}
@SuppressLint("SourceLockedOrientationActivity")
override fun onConfigurationChanged(newConfig: Configuration) {
if (resources.getBoolean(R.bool.portrait_only)) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
super.onConfigurationChanged(newConfig)
}
}
Inne rozwiązania nie działały dla mnie. Nadal miałem dziwny problem z orientacją związany z dialogami i problemami z rekreacją. Moim rozwiązaniem było rozszerzenie działania, zmuszając go jako manifest w portrecie.
Przykład:
public class MainActivityPhone extends MainActivity {}
manifest.xml:
<activity
android:screenOrientation="portrait"
android:name=".MainActivityPhone"
android:theme="@style/AppTheme.NoActionBar" />
w działaniu ekranu powitalnego:
Intent i = null;
boolean isTablet = getResources().getBoolean(R.bool.is_tablet);
if (!isTablet)
i = new Intent(this, MainActivityPhone.class);
else
i = new Intent(this, MainActivity.class);
startActivity(i);
Stare pytanie, które znam. Aby aplikacja działała zawsze w trybie pionowym, nawet gdy orientacja może być lub jest zamieniona itp. (Na przykład na tabletach), zaprojektowałem tę funkcję, która służy do ustawiania urządzenia we właściwej orientacji bez konieczności poznawania orientacji pionowej i poziomej funkcje 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 marzenie!
UWAGA: Zmień this.activity
według swojej aktywności lub dodaj ją do głównej aktywności i usuń this.activity
;-)
Jeśli chcesz zrobić odwrotnie, musisz zmienić kod na poziomy (ale myślę, że jest jasne, jak to zrobić).
Niestety przy użyciu metody setRequestedOrientation (...) spowoduje ponowne uruchomienie działania, więc nawet jeśli wywołasz to w metodzie onCreate, przejdzie przez cykl życia działania, a następnie odtworzy tę samą aktywność w żądanej orientacji. Dlatego w odpowiedzi @Brian Christensen powinieneś wziąć pod uwagę, że kod aktywności może zostać wywołany dwukrotnie, co może mieć złe skutki (nie tylko wizualne, ale także na żądania sieciowe, analizy itp.).
Ponadto ustawienie atrybutu configChanges w manifeście jest moim zdaniem dużym kompromisem, który może wymagać ogromnych kosztów refaktoryzacji. Android Devs nie zaleca zmiany tego atrybutu .
Wreszcie próba ustawienia nieco innej orientacji ekranu (aby uniknąć problemu z ponownym uruchomieniem) jest niemożliwa, statycznie niemożliwa z powodu statycznego manifestu, którego nie można zmienić, programowo można wywołać tę metodę tylko w już rozpoczętym działaniu.
Podsumowanie: Moim zdaniem sugestia @Brian Christensen jest najlepszym kompromisem, ale należy pamiętać o problemie z ponownym uruchomieniem.
layout-land
wewnętrznegores
.