Android: permitir retrato y paisaje para tabletas,pero forzar retrato en el teléfono?


Me gustaría que las tabletas puedan mostrarse en vertical y horizontal (sw600dp o superior), pero que los teléfonos se limiten solo a vertical. No puedo encontrar ninguna manera de elegir condicionalmente una orientación. Alguna sugerencia?

Author: Kenny Wyland, 2012-03-09

8 answers

Aquí hay una buena manera de usar recursos y calificadores de tamaño.

Ponga este recurso bool en res/values como bools.xml o lo que sea (los nombres de archivo no importan aquí):

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

Pon esto en res / values-sw600dp y res / values-xlarge:

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

Consulte esta respuesta complementaria para obtener ayuda para agregar estos directorios y archivos en Android Studio.

Entonces, en el método onCreate de tus Actividades puedes hacer esto:

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

Dispositivos que son más de 600 dp en la dirección de ancho más pequeña, o x-large en dispositivos pre-Android 3.2 (tabletas, básicamente) se comportarán como normales, basado en el sensor y la rotación bloqueada por el usuario, etc. Todo lo demás (teléfonos, más o menos) será solo retrato.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:03:08

Puede probar de esta manera primero obtener el tamaño de pantalla del dispositivo

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

Y luego establecer la orientación de acuerdo con eso

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-21 15:03:21

Así es como lo hice (inspirado por http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html ):

En AndroidManifest.xml, para cada actividad que desea ser capaz de cambiar entre retrato y paisaje (asegúrese de agregar tamaño de pantalla - que no solía necesitar esto!) No es necesario establecer una orientación de pantalla aquí. :

android:configChanges="keyboardHidden|orientation|screenSize"

Métodos para agregar en cada Actividad:

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

Y: (si no anula este método, la aplicación llamará onCreate () al cambiar de orientación)

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

En onCreate () de cada Actividad:

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

Lo único que parece que no puedo averiguar es cómo conseguir que la aplicación cambie los archivos de diseño al cambiar de paisaje a retrato o viceversa. Asumo que la respuesta es hacer algo similar a lo que hace el enlace anterior, pero no pude hacer que funcione para mí: eliminó todos mis datos. Pero si usted tiene una aplicación lo suficientemente simple que usted tiene el mismo archivo de diseño para retrato y paisaje, esto debería funcionar.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-26 13:41:42

Suplemento de la respuesta aceptada

Puedes hacer los siguientes pasos en Android Studio para agregar los directorios res/values-sw600dp y res/values-large con sus archivos bools.xml.

Valores-sw600dp

En primer lugar, desde la pestaña Proyecto seleccione el filtro Proyecto (en lugar de Android) en el navegador.

introduzca la descripción de la imagen aquí

Luego haga clic derecho en el directorio app/src/main/res. Elija Nuevo > Directorio de Recursos de Android .

Seleccionar El ancho de pantalla más pequeño , y luego presione >> botón.

introduzca la descripción de la imagen aquí

Escriba 600 para el ancho de pantalla más pequeño. El nombre del directorio se generará automáticamente. Di OK.

introduzca la descripción de la imagen aquí

Luego haga clic derecho en el archivo values-sw600dp recién creado. Elija Nuevo > Values resource file . Escriba bools para el nombre.

Valores-grandes

Agregar un directorio values-large solo es necesario si son compatibles con Android 3.2 anterior (nivel de API 13). De lo contrario, puede omitir este paso. El directorio values-large corresponde a values-sw600dp. (values-xlarge corresponde a values-sw720dp.)

Para crear el directorio values-large, siga los mismos pasos que los anteriores, pero en este caso elija Size en lugar de Smallest Screen Width. Seleccione Large. El nombre del directorio se generará automáticamente.

introduzca la descripción de la imagen aquí

Haga clic derecho en el directorio como antes para crear el archivo 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:26

Bueno, esto es un poco tarde pero, aquí hay un XML-Only pero una solución de hackeo que no recrea una actividad como lo hace setRequestedOrientation si tiene que cambiar de orientación:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:07

Siguiendo la respuesta de Ginny , creo que la forma más confiable de hacerlo es la siguiente:

Como se describe aquí, ponga un booleano en resources sw600dp. Debe tener el prefijo sw de lo contrario no funcionará correctamente:

En res/values-sw600dp/dimens.xml

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

En res/values/dimens.xml

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

Luego haga un método para recuperar ese booleano:

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

Y una actividad base para extender desde las actividades donde desea esto comportamiento:

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

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

Así que cada actividad extendería la actividad base:

public class LoginActivity extends BaseActivity //....

Importante : incluso si se extiende desde BaseActivity, debe agregar la línea android:configChanges="orientation|screenSize" a cada Activity en su 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:07

Vieja pregunta que conozco. Para ejecutar su aplicación siempre en modo vertical, incluso cuando la orientación puede ser o se intercambia, etc. (por ejemplo, en tabletas) Diseñé esta función que se utiliza para configurar el dispositivo en la orientación correcta sin la necesidad de saber cómo se organizan las características de retrato y paisaje en el dispositivo.

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

    }

Funciona como un encanto!

AVISO: Cambie this.activity por su actividad o agréguela a la actividad principal y elimínela this.activity ;-)

Si quieres hacer el al contrario, debes cambiar el código a apaisado(pero creo que está claro cómo hacerlo).

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-13 15:54:21

Desafortunadamente, usando el método setRequestedOrientation(...) hará que la actividad se reinicie, por lo que incluso si llama a esto en el método onCreate, pasará por el ciclo de vida de la actividad y luego recreará la misma actividad en la orientación solicitada. Así que en la respuesta de @Brian Christensen debes considerar que el código de actividad podría ser llamado dos veces, esto podría tener efectos negativos (no solo visuales, sino también en solicitudes de red, análisis, etc.).

Además, establecer el atributo configChanges en el manifiesto es, en mi opinión, una gran compensación, que podría tener un costo de refactorización masivo. Los desarrolladores de Android no recomiendan cambiar ese atributo .

Finalmente, intentar establecer la orientación de la pantalla de alguna manera diferente (para evitar el problema de reinicio) es imposible, estáticamente imposible debido al manifiesto estático que no se puede cambiar, programáticamente solo es posible llamar a ese método en la actividad ya iniciada.

Resumen: En mi opinión, la sugerencia de @Brian Christensen es la mejor opción, pero tenga en cuenta el problema del reinicio de la actividad.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-03 16:01:15