Android:允许在平板电脑上使用肖像和风景,但在手机上强制使用肖像?
我希望平板电脑能够显示纵向和横向(sw600dp或更高),但手机只能显示纵向。我找不到任何有条件地选择方向的方法。有什么建议吗?您可以尝试这种方法,首先获取设备的屏幕大小Android:允许在平板电脑上使用肖像和风景,但在手机上强制使用肖像?,android,tablet,screen-orientation,Android,Tablet,Screen Orientation,我希望平板电脑能够显示纵向和横向(sw600dp或更高),但手机只能显示纵向。我找不到任何有条件地选择方向的方法。有什么建议吗?您可以尝试这种方法,首先获取设备的屏幕大小 if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) { Toast.make
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);
以下是我是如何做到这一点的(灵感来自于):
在AndroidManifest.xml中,对于您希望能够在纵向和横向之间更改的每个活动(请确保添加屏幕大小-您以前不需要它!),您不需要在此处设置屏幕方向:
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()
在每个活动的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
}
我唯一不知道的是,当从横向切换到纵向时,如何让应用程序更改布局文件,反之亦然。我假设答案与上面的链接类似,但我无法让它对我起作用——它删除了我所有的数据。但是如果你有一个足够简单的应用程序,你有相同的纵向和横向布局文件,这应该是可行的。这里有一个使用和的好方法
将此bool资源以res/values格式作为bools.xml或其他格式(此处文件名无关紧要):
在最小宽度方向上超过600 dp的设备,或者在安卓3.2之前的设备(基本上是平板电脑)上x-large的设备,其性能将与普通设备一样。其他的一切(电话,差不多)都是肖像。我知道的老问题。为了让你的应用程序始终在纵向模式下运行,即使方向可能会改变或被改变等(例如在平板电脑上),我设计了此功能,用于将设备设置为正确的方向,而无需知道设备上纵向和横向功能是如何组织的
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); }
}
工作起来很有魅力
注意:
按您的活动更改此.activity
,或将其添加到主活动并删除此.activity
;-)
如果您想做相反的事情,您必须将代码更改为横向(但我认为这一点很清楚)。好吧,这有点晚了,但是,这里有一个仅XML,但是如果必须更改方向,一个黑客解决方案不会像
setRequestedOrientation
那样重新创建活动:
对《公约》的补充
您可以在Android Studio中执行以下步骤,添加res/values-sw600dp
和res/values-large
目录及其bools.xml
文件
值-sw600dp
首先,从项目选项卡中选择导航器中的项目(而不是Android)过滤器
然后右键单击app/src/main/res
目录。选择新的Android资源目录
选择最小屏幕宽度,然后按>按钮
键入600
以获得最小屏幕宽度。将自动生成目录名。说“好”
然后右键单击新创建的values-sw600dp
文件。选择新建值资源文件。键入bools
作为名称
价值大
只有在支持Android 3.2之前版本(API级别13)的情况下,才需要添加一个values large
目录。否则,您可以跳过此步骤。values large
目录对应于values-sw600dp
。(values xlarge
对应于values-sw720dp
)
要创建values large
目录,请执行与上述相同的步骤,但在本例中选择Size而不是最小屏幕宽度。选择Large。将自动生成目录名
如前所述,右键单击目录以创建bools.xml
文件。以下是最可靠的方法:
如上所述,在资源sw600dp中放置一个布尔值。它必须具有前缀sw,否则将无法正常工作:
在res/values-sw600dp/dimens.xml中
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">true</bool>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isTablet">false</bool>
</resources>
以及从您希望此行为的活动扩展而来的基本活动:
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 static boolean isXLargeScreen(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
public class LoginActivity extends BaseActivity //....
重要:即使您从BaseActivity
扩展,也必须将行android:configChanges=“orientation | screenSize”
添加到AndroidManifest.xml中的每个活动中:
<activity
android:name=".login.LoginActivity"
android:configChanges="orientation|screenSize">
</activity>
<activity
android:screenOrientation="portrait"
android:name=".MainActivityPhone"
android:theme="@style/AppTheme.NoActionBar" />
不幸的是,使用该方法将导致活动重新启动,因此即使您在onCreate方法中调用该方法,它也将经历活动生命周期,然后它将以请求的方向重新创建相同的活动。因此,在@ Brian Christensen的回答中,您应该考虑活动代码可能被调用两次,这可能会产生不良影响(不仅是视觉上的,而且还包括网络请求、分析等)。
此外,在我看来,在清单中设置configChanges属性是一个巨大的折衷,这可能需要巨大的重构成本
最后,尝试以某种方式设置screenOrientation(以避免重新启动问题)是不可能的,静态上是不可能的,因为静态清单无法更改,以编程方式,只能在已经启动的活动中调用该方法
总结:在我看来,@Brian Christensen的建议是最好的折衷办法,但要注意重新启动活动的问题。其他解决方案对我不起作用。我在对话和娱乐方面仍然有一些奇怪的定位问题。我的解决方案是扩展活动,将其强制为清单中的肖像
例如:
public class MainActivityPhone extends MainActivity {}
manifest.xml:
<activity
android:name=".login.LoginActivity"
android:configChanges="orientation|screenSize">
</activity>
<activity
android:screenOrientation="portrait"
android:name=".MainActivityPhone"
android:theme="@style/AppTheme.NoActionBar" />
在接受回答之后,我添加了带有t的kotlin文件
public class MainActivityPhone extends MainActivity {}
<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);
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
<?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)
}
}
<activity
android:screenOrientation="${screenOrientation}"
...
</activity>
android {
...
productFlavors {
normal {
manifestPlaceholders = [screenOrientation: "portrait"]
}
tablet {
manifestPlaceholders = [screenOrientation: "unspecified"]
}
}
}
app
src
tablet
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="{package}">
<supports-screens
android:smallScreens="false"
android:normalScreens="false"
android:largeScreens="true"
android:xlargeScreens="true"
android:requiresSmallestWidthDp="600"
/>
</manifest>
app-normal.apk/aab (v1.0.0, version code 1)
app-tablet.apk/aab (v1.0.0, version code 2)
android:screenOrientation="fullSensor"