Answers:
将此bool资源作为bools.xml或其他内容(在这里文件名无关紧要)放入res / values中:
<?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的设备,或在Android 3.2之前的设备(基本上是平板电脑)上为x-large的设备,将根据传感器和用户锁定的旋转等情况表现出正常的行为。其他所有内容(电话,几乎全部)将仅是肖像。
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
文件。
首先,从“项目”选项卡中,在导航器中选择“项目”(而不是Android)过滤器。
然后右键单击app/src/main/res
目录。选择“ 新建” >“ Android资源目录”。
选择最小屏幕宽度,然后按>>按钮。
键入600
的最小屏幕宽度。目录名称将自动生成。说OK。
然后右键单击新创建的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
}
在每个Activity的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
}
我似乎无法弄清的唯一一件事是,当从横向切换为纵向时,如何使应用程序更改布局文件,反之亦然。我认为答案的作用与上述链接相似,但我无法解决该问题-它删除了我的所有数据。但是,如果您有一个足够简单的应用程序,并且具有用于纵向和横向的相同布局文件,则应该可以使用。
遵循Ginny的回答,我认为最可靠的方法如下:
如上所述这里,投入资源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
,也必须在AndroidManifest.xml中android:configChanges="orientation|screenSize"
向每行添加以下行Activity
:
<activity
android:name=".login.LoginActivity"
android:configChanges="orientation|screenSize">
</activity>
好吧,这有点晚了,但是这里是一个仅XML的黑客解决方案,它不会像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>
然后,将其添加到活动或fragmentvity的以下行中
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开发人员不建议更改该属性。
最后,尝试将screenOrientation设置为某种不同(以避免重新启动问题)是不可能的,由于静态清单不能更改,因此在静态上是不可能的,以编程方式只能在已经开始的活动中调用该方法。
简介:在我看来,@ Brian Christensen的建议是最好的折衷方案,但请注意重新开始的活动问题。
layout-land
内部res
文件夹中那样设计手机的横向布局。