Я хотел бы, чтобы планшеты могли отображаться в книжной и альбомной ориентации (sw600dp или выше), но телефоны должны быть только в портретной ориентации. Я не могу найти способ условно выбрать ориентацию. Какие-либо предложения?
Я хотел бы, чтобы планшеты могли отображаться в книжной и альбомной ориентации (sw600dp или выше), но телефоны должны быть только в портретной ориентации. Я не могу найти способ условно выбрать ориентацию. Какие-либо предложения?
Ответы:
Вот хороший способ использования ресурсов и определителей размера .
Поместите этот ресурс bool в res / values как bools.xml или как угодно (имена файлов здесь не имеют значения):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
Поместите это в res / values-sw600dp и res / values-xlarge:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
См. Этот дополнительный ответ для помощи по добавлению этих каталогов и файлов в Android Studio.
Затем в методе onCreate ваших действий вы можете сделать это:
if(getResources().getBoolean(R.bool.portrait_only)){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Устройства, которые имеют более 600 dp в направлении наименьшей ширины или x-large на устройствах до Android 3.2 (планшеты, в основном), будут вести себя как обычно, основываясь на повороте датчика и блокировки пользователя и т . Д. Все остальное (телефоны, в значительной степени) будет только портретным.
xlarge
тоже нужно использовать или я могу просто использовать sw600dp
? Вероятно, сейчас нет планшетов, работающих под <3.2.
onCreate()
. Когда я переместил вызов в setRequestedOrientation()
другую позицию по времени и контексту, перезапуск больше не происходил.
Вы можете попробовать этот способ сначала получить размер экрана устройства
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();
}
а затем установить ориентацию в соответствии с этим
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Configuration
предоставляет screenLayout
информацию - DPI. Тогда как вопрос касается размера экрана физического устройства - телефона против планшета. Это означает, что вы можете иметь Configuration.SCREENLAYOUT_SIZE_NORMAL
планшет MDPI.
Вы можете сделать следующие шаги в Android Studio, чтобы добавить res/values-sw600dp
и res/values-large
каталоги с ихbools.xml
файлами.
Прежде всего, на вкладке Project выберите фильтр Project (а не Android) в навигаторе.
Затем щелкните правой кнопкой мыши app/src/main/res
каталог. Выберите « Создать» > « Каталог ресурсов Android». .
Выберите наименьшая ширина экрана , а затем нажмите кнопку >> .
Введите 600
для наименьшей ширины экрана. Имя каталога будет создано автоматически. Скажи "ОК.
Затем щелкните правой кнопкой мыши по вновь созданному values-sw600dp
файлу. Выберите « Создать» > « Файл значений» . Типbools
имя.
Добавление values-large
каталога необходимо только в том случае, если вы поддерживаете предварительную версию Android 3.2 (уровень API 13). В противном случае вы можете пропустить этот шаг. values-large
Каталог соответствует values-sw600dp
. ( values-xlarge
соответствуетvalues-sw720dp
.)
Чтобы создать values-large
каталог, выполните те же действия, что и выше, но в этом случае выберите Размер, а не Наименьшую ширину экрана. Выберите Большой . Имя каталога будет создано автоматически.
Щелкните правой кнопкой мыши каталог, как и прежде, чтобы создать bools.xml
файл.
Вот как я это сделал (вдохновлено http://androidblogger.blogspot.com/2011/08/orientation-for-both-phones-and-tablets.html ):
В AndroidManifest.xml для каждого действия вы хотите иметь возможность переключаться между портретным и ландшафтным режимом (убедитесь, что вы добавили screenSize - вам это раньше не нужно!) Вам не нужно устанавливать здесь ориентацию экрана. :
android:configChanges="keyboardHidden|orientation|screenSize"
Методы, которые нужно добавить в каждое действие:
public static boolean isXLargeScreen(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
и: (если вы не переопределите этот метод, приложение вызовет onCreate () при изменении ориентации)
@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
}
В onCreate () каждого действия:
if (!isXLargeScreen(getApplicationContext())) { //set phones to portrait;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else {
//I set background images here depending on portrait or landscape orientation
}
Единственное, чего я не могу понять, это как заставить приложение изменять файлы макетов при переключении с альбомного на портретное и наоборот. Я предполагаю, что ответ делает нечто похожее на то, что делает приведенная выше ссылка, но я не смог заставить это работать на меня - он удалил все мои данные. Но если у вас достаточно простое приложение с одинаковым файлом макета для портретной и альбомной ориентации, это должно сработать.
После ответа Джинни я думаю, что самый надежный способ сделать это заключается в следующем:
Как описано здесь , поместите логическое значение в ресурсы sw600dp. Он должен иметь префикс sw, иначе он не будет работать должным образом:
в res / values-sw600dp / dimensions.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">true</bool>
</resources>
в res / values / dimensions.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">false</bool>
</resources>
Затем создайте метод для получения этого логического значения:
public class ViewUtils {
public static boolean isTablet(Context context){
return context.getResources().getBoolean(R.bool.isTablet);
}
}
И базовое действие, расширяемое от действий, в которых вы хотите это поведение:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!ViewUtils.isTablet(this)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
Таким образом, каждое действие будет расширять BaseActivity:
public class LoginActivity extends BaseActivity //....
Важно : даже если вы выходите из BaseActivity
, вы должны добавить строку android:configChanges="orientation|screenSize"
к каждому Activity
в вашем AndroidManifest.xml:
<activity
android:name=".login.LoginActivity"
android:configChanges="orientation|screenSize">
</activity>
Ну, это немного поздно, но вот XML-Only, но решение для взлома, которое не воссоздает действие, как setRequestedOrientation
если бы нужно было изменить ориентацию:
После принято ответа я добавляю файл kotlin с решением, надеюсь, он кому-нибудь поможет
Поместите этот ресурс bool res/values
как bools.xml или как угодно (имена файлов здесь не важны):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
Поместите это res/values-sw600dp
и res/values-sw600dp-land
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
Затем добавьте его в нижних строках вашей деятельности или фрагментированности
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)
}
}
Другие решения не работали для меня. У меня все еще были странные проблемы с ориентацией на диалоги и вопросы отдыха. Мое решение состояло в том, чтобы продлить действие, сделав его портретом в манифесте.
Пример:
public class MainActivityPhone extends MainActivity {}
manifest.xml:
<activity
android:screenOrientation="portrait"
android:name=".MainActivityPhone"
android:theme="@style/AppTheme.NoActionBar" />
в заставке деятельности:
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);
Старый вопрос я знаю. Чтобы приложение всегда работало в портретном режиме, даже если ориентация может быть или поменялась местами и т. Д. (Например, на планшетах), я разработал эту функцию, которая используется для установки устройства в правильной ориентации без необходимости знать, как портрет и пейзаж функции организованы на устройстве.
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); }
}
Работает как шарм!
ВНИМАНИЕ: измените this.activity
свою деятельность или добавьте ее к основной деятельности и удалите this.activity
;-)
Если вы хотите сделать обратное, вы должны изменить код на ландшафт (но я думаю, что это понятно).
К сожалению, используя метод setRequestedOrientation (...) приведет к перезапуску действия, поэтому даже если вы вызовете его в методе onCreate, он пройдет жизненный цикл действия и затем заново создаст то же действие в запрошенной ориентации. Таким образом, при ответе @Brian Christensen вы должны учитывать, что код активности может вызываться дважды, что может иметь плохие последствия (не только визуальные, но и при сетевых запросах, аналитике и т. Д.).
Более того, установка атрибута configChanges в манифесте, на мой взгляд, является большим компромиссом, который может потребовать огромных затрат на рефакторинг. Разработчики Android не рекомендуют менять этот атрибут .
Наконец, попытка установить screenOrientation как-то иначе (чтобы избежать проблемы перезапуска) невозможна, статически невозможна из-за статического манифеста, который нельзя изменить, программно можно вызвать этот метод только в уже запущенном действии.
Резюме: На мой взгляд, предложение @Brian Christensen - лучший компромисс, но имейте в виду проблему возобновления активности.
layout-land
внутреннейres
папки.