Я хотів би, щоб планшети могли відображатись у портреті та пейзажі (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 на пристроях, що перебувають під керуванням 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. Тоді як питання стосується фізичного розміру екрана пристрою - планшета VS телефону. Це означає, що ви можете мати 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 (рівень 13 API). Інакше цей крок можна пропустити. 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 / dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">true</bool>
</resources>
в res / values / dimens.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" />
в активності splashcreen:
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 Devs не рекомендує змінювати цей атрибут .
Нарешті, намагатися встановити параметр screenOrientation якось інакше (щоб уникнути проблеми перезавантаження) неможливо, статично неможливо через статичний маніфест, який неможливо змінити, програмно можна викликати цей метод лише у вже розпочатій діяльності.
Короткий зміст: На мій погляд, пропозиція @Brian Christensen є найкращим компромісом, але будьте в курсі питання про перезапуск діяльності.
layout-land
всерединіres
папки.