it-swarm.com.de

Android: Porträt und Landschaft für Tablets zulassen, aber Porträt am Telefon erzwingen?

Ich möchte, dass Tablets im Hoch- und Querformat (sw600dp oder höher) angezeigt werden können, die Telefone jedoch nur für das Hochformat. Ich kann keinen Weg finden, um eine Orientierung bedingt zu wählen. Irgendwelche Vorschläge?

177
Kenny Wyland

Hier ist ein guter Weg mit Ressourcen und Qualifier .

Setzen Sie diese bool-Ressource in res/values ​​als bools.xml oder wie auch immer (Dateinamen spielen hier keine Rolle):

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

Setzen Sie dieses in res/values-sw600dp und res/values-xlarge:

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

Siehe diese ergänzende Antwort für Hilfe beim Hinzufügen dieser Verzeichnisse und Dateien in Android Studio.

Dann können Sie in der onCreate-Methode Ihrer Aktivitäten Folgendes tun:

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

Geräte mit mehr als 600 dp in der kleinsten Breitenrichtung oder x-large auf Geräten mit einer älteren Version als Android 3.2 (im Wesentlichen Tablets) verhalten sich normal, basierend auf sensor- und benutzergekoppelter Drehung usw. . Alles andere (Telefone, ziemlich viel) wird nur Porträt sein.

417

Sie können auf diese Weise zunächst die Bildschirmgröße des Geräts ermitteln 

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

und dann die Orientierung entsprechend einstellen 

setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
28
Avi Kumar Manku

So habe ich es gemacht (inspiriert von http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html ):

In AndroidManifest.xml für jede Aktivität, die Sie zwischen Hoch- und Querformat wechseln möchten (stellen Sie sicher, dass Sie screenSize hinzufügen - das war früher nicht nötig!). Hier müssen Sie keine Bildschirmausrichtung festlegen. :

Android:configChanges="keyboardHidden|orientation|screenSize"

Methoden, die jeder Aktivität hinzugefügt werden müssen:

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

und: (Wenn Sie diese Methode nicht überschreiben, ruft die App beim Ändern der Ausrichtung onCreate () auf.)

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

In onCreate () jeder Aktivität:

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

Das einzige, was ich nicht herausfinden kann, ist, wie man die App dazu bringt, beim Wechsel von Querformat zu Hochformat oder umgekehrt Layoutdateien zu ändern. Ich gehe davon aus, dass die Antwort etwas Ähnliches wie der obige Link ist, aber ich konnte das nicht für mich arbeiten lassen - es löschte alle meine Daten. Wenn Sie jedoch über eine einfache App verfügen, die dieselbe Layoutdatei für Hoch- und Querformat hat, sollte dies funktionieren.

8
Ginny

Ergänzung zur akzeptierten Antwort

Sie können in Android Studio die folgenden Schritte ausführen, um die Verzeichnisse res/values-sw600dp und res/values-large mit ihren bools.xml-Dateien hinzuzufügen.

werte-sw600dp

Wählen Sie auf der Registerkarte "Projekt" zunächst den Filter "Projekt" (statt Android) im Navigator aus.

 enter image description here

Klicken Sie dann mit der rechten Maustaste auf das Verzeichnis app/src/main/res. Wählen Sie New> Android Resource Directory.

Wählen Sie Kleinste Bildschirmbreite und drücken Sie die Taste >>

 enter image description here

Geben Sie 600 für die kleinste Bildschirmbreite ein. Der Verzeichnisname wird automatisch generiert. Sag OK.

 enter image description here

Klicken Sie dann mit der rechten Maustaste auf die neu erstellte values-sw600dp-Datei. Wählen Sie New> Values-Ressourcendatei. Geben Sie bools für den Namen ein.

werte groß

Das Hinzufügen eines values-large-Verzeichnisses ist nur erforderlich, wenn Sie vor Android 3.2 (API-Level 13) unterstützen. Ansonsten können Sie diesen Schritt überspringen. Das values-large-Verzeichnis entspricht values-sw600dp. (values-xlarge entspricht values-sw720dp.)

Um das Verzeichnis values-large zu erstellen, gehen Sie wie oben beschrieben vor. Wählen Sie in diesem Fall jedoch Size anstelle von Smallest Screen Width. Wählen Sie Large. Der Verzeichnisname wird automatisch generiert. 

 enter image description here

Klicken Sie mit der rechten Maustaste auf das Verzeichnis, um die bools.xml-Datei zu erstellen. 

7
Suragch

Nach Ginnys Antwort , denke ich, ist der zuverlässigste Weg dies zu tun:

Wie hier beschrieben, setzen Sie einen booleschen Wert in die Ressourcen sw600dp. Es muss das Präfix sw haben, sonst funktioniert es nicht richtig:

in res/values-sw600dp/dimens.xml

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

in res/values ​​/ dimens.xml

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

Erstellen Sie dann eine Methode, um diesen Booleschen Wert abzurufen:

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

Und eine Basisaktivität, die von den Aktivitäten ausgeht, bei denen Sie dieses Verhalten wünschen:

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

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

Jede Aktivität würde also BaseActivity erweitern:

public class LoginActivity extends BaseActivity //....

Important: Auch wenn Sie sich von BaseActivity erstrecken, müssen Sie der Activity in Ihrer AndroidManifest.xml die Zeile Android:configChanges="orientation|screenSize" hinzufügen:

    <activity
        Android:name=".login.LoginActivity"
        Android:configChanges="orientation|screenSize">
    </activity>
6
RominaV

Nun, dies ist etwas spät, aber hier ist ein XML-Only, aber eine Hack-Lösung, die keine Aktivität neu erstellt, wie setRequestedOrientation, wenn die Ausrichtung geändert werden muss:

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

4
guness

Andere Lösungen haben bei mir nicht funktioniert. Ich hatte immer noch ein seltsames Orientierungsproblem mit Dialogen und Erholungsproblemen. Meine Lösung bestand darin, die Aktivität zu erweitern und sie als Porträt im Manifest zu erzwingen.

Beispiel:

public class MainActivityPhone extends MainActivity {}

manifest.xml:

        <activity
        Android:screenOrientation="portrait"
        Android:name=".MainActivityPhone"
        Android:theme="@style/AppTheme.NoActionBar" />

in Splashscreen-Aktivität:

    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);
0
mengoni

Alte Frage, die ich kenne. Damit Ihre App auch im Hochformat ausgeführt werden kann, auch wenn die Ausrichtung möglicherweise geändert wird (zB auf Tablets), habe ich diese Funktion entwickelt, mit der Sie das Gerät in die richtige Ausrichtung bringen können, ohne dass Sie wissen müssen, wie das Hoch- und Querformat ist Funktionen sind auf dem Gerät organisiert.

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

    }

Klappt wunderbar! 

HINWEIS: Ändern Sie this.activity durch Ihre Aktivität oder fügen Sie ihn der Hauptaktivität hinzu und entfernen Sie this.activity ;-).

Wenn Sie das Gegenteil tun möchten, müssen Sie den Code in Querformat ändern (aber ich denke, es ist klar, wie das geht).

0
Codebeat

Wenn Sie die Methode setRequestedOrientation (...) verwenden, wird die Aktivität leider neu gestartet. Wenn Sie also die Methode onCreate aufrufen, durchläuft sie den Aktivitätslebenszyklus, und dann wird dieselbe Aktivität in der angeforderten Aktivität erneut erstellt Orientierung. Bei @Brian Christensens Antwort sollten Sie bedenken, dass der Aktivitätscode möglicherweise zweimal aufgerufen wird. Dies kann negative Auswirkungen haben (nicht nur visuell, sondern auch bei Netzwerkanfragen, Analysen usw.).

Außerdem ist das Festlegen des configChanges-Attributs im Manifest meiner Meinung nach ein großer Kompromiss, der massive Refactoring-Kosten verursachen kann. Android-Entwickler empfehlen nicht, dieses Attribut zu ändern .

Schließlich ist der Versuch, die screenOrientation anders einzustellen (um das Neustartproblem zu vermeiden) unmöglich, statisch unmöglich, da das statische Manifest nicht geändert werden kann. Programmgesteuert ist es nur möglich, diese Methode in der bereits gestarteten Aktivität aufzurufen. 

Zusammenfassung: Meiner Meinung nach ist der Vorschlag von @Brian Christensen der beste Kompromiss, aber seien Sie sich des Problems der Wiederaufnahme der Aktivität bewusst.

0
mathew11