我希望平板电脑能够显示肖像和景观(sw600dp或更大),但手机仅限于肖像。我找不到任何有条件地选择方向的方法。有什么建议吗?
当前回答
I recently came across this requirement but didn't want to use any of these solutions. All of them have in common that they call setRequestedOrientation programmatically. The problem with this is it sets the orientation too late and causes slight UI glitches. If your device is in landscape when you launch the app it loads in landscape then rotates. This is particularly noticeable if you use a theme to create a splash screen effect as you will see the background image in the wrong orientation. This can also have a side effect on how your app is shown in the recent apps and issues with configuration change as noted in other answers comments.
需要在清单中设置正确的方向,这样系统就可以在不启动应用程序的情况下知道方向。
这里有一个解决方案(这是一个相当大的努力,但你会睡得更好)
首先将清单中的方向设置为占位符
<activity
android:screenOrientation="${screenOrientation}"
...
</activity>
然后我们需要添加一个normal/tablet flavor来设置app/build.gradle中的值。(如果你已经在使用味道,可以用新的构建类型来实现)
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>
最后一个技巧是我们需要通过版本代码来区分构建,因为Playstore不能有两次带有匹配代码的上传。我们希望确保平板电脑(更严格的构建)具有更高的代码。一个简单的方法是取一个基本代码,然后平板电脑的基本* 2和普通的基本* 2 - 1。我使用CI与基本代码构建数字,但很容易在你的口味硬编码。
现在制作两种口味
app-normal.apk/aab (v1.0.0, version code 1)
app-tablet.apk/aab (v1.0.0, version code 2)
将它们以多个apk/aab的形式上传到Playstore,然后如果在平板电脑上下载,Playstore会提供旋转的apk,如果在手机上下载,则只提供一个纵向的apk。
注:仅适用于通过谷歌Playstore/Amazon Kindle分发
进一步阅读https://developer.android.com/google/play/publishing/multiple-apks https://developer.amazon.com/docs/fire-tablets/ft-screen-layout-and-resolution.html
其他回答
以下是接受的答案,我正在添加解决方案的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)
}
}
I recently came across this requirement but didn't want to use any of these solutions. All of them have in common that they call setRequestedOrientation programmatically. The problem with this is it sets the orientation too late and causes slight UI glitches. If your device is in landscape when you launch the app it loads in landscape then rotates. This is particularly noticeable if you use a theme to create a splash screen effect as you will see the background image in the wrong orientation. This can also have a side effect on how your app is shown in the recent apps and issues with configuration change as noted in other answers comments.
需要在清单中设置正确的方向,这样系统就可以在不启动应用程序的情况下知道方向。
这里有一个解决方案(这是一个相当大的努力,但你会睡得更好)
首先将清单中的方向设置为占位符
<activity
android:screenOrientation="${screenOrientation}"
...
</activity>
然后我们需要添加一个normal/tablet flavor来设置app/build.gradle中的值。(如果你已经在使用味道,可以用新的构建类型来实现)
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>
最后一个技巧是我们需要通过版本代码来区分构建,因为Playstore不能有两次带有匹配代码的上传。我们希望确保平板电脑(更严格的构建)具有更高的代码。一个简单的方法是取一个基本代码,然后平板电脑的基本* 2和普通的基本* 2 - 1。我使用CI与基本代码构建数字,但很容易在你的口味硬编码。
现在制作两种口味
app-normal.apk/aab (v1.0.0, version code 1)
app-tablet.apk/aab (v1.0.0, version code 2)
将它们以多个apk/aab的形式上传到Playstore,然后如果在平板电脑上下载,Playstore会提供旋转的apk,如果在手机上下载,则只提供一个纵向的apk。
注:仅适用于通过谷歌Playstore/Amazon Kindle分发
进一步阅读https://developer.android.com/google/play/publishing/multiple-apks https://developer.amazon.com/docs/fire-tablets/ft-screen-layout-and-resolution.html
下面是使用资源和大小限定符的好方法。
将这个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);
}
在最小宽度方向上超过600dp的设备,或者在android 3.2之前的设备(基本上是平板电脑)上的x-large设备将会像正常的设备一样,基于传感器和用户锁定旋转等。其他所有东西(手机,几乎)都只能是竖屏。
对已接受答案的补充
您可以在Android Studio中执行以下步骤来添加res/values-sw600dp和res/values-large目录及其bools.xml文件。
values-sw600dp
首先,在Project选项卡中选择导航器中的Project(而不是Android)过滤器。
然后右键单击app/src/main/res目录。选择“新建> Android资源目录”。
选择最小屏幕宽度,然后按>>按钮。
输入600作为最小的屏幕宽度。目录名称将自动生成。说好的。
然后右键单击新创建的values-sw600dp文件。选择“新建>值资源文件”。为名称键入bool。
values-large
只有在支持Android 3.2 (API级别13)之前,才需要添加一个值很大的目录。否则,您可以跳过此步骤。values-large目录对应于values-sw600dp。(values-xlarge对应values-sw720dp。)
要创建values-large目录,请执行与上面相同的步骤,但在本例中选择“大小”而不是“最小屏幕宽度”。选择大。目录名称将自动生成。
像以前一样右键单击该目录以创建bools.xml文件。
不幸的是,使用setRequestedOrientation(…)方法会导致活动重新启动,所以即使你在onCreate方法中调用这个,它也会经历活动生命周期,然后它会在请求的方向上重新创建相同的活动。所以在@Brian Christensen的回答中,你应该考虑到活动代码可能会被调用两次,这可能会产生不良影响(不仅是视觉上,而且在网络请求、分析等方面也会产生不良影响)。
此外,在清单中设置configChanges属性在我看来是一个很大的权衡,这可能会花费大量的重构成本。Android开发者不建议改变这个属性。
最后,尝试以不同的方式设置screenOrientation(以避免重新启动问题)是不可能的,静态不可能,因为静态manifest不能被改变,编程上只可能在已经启动的活动中调用该方法。
总结:在我看来,@Brian Christensen的建议是最好的权衡,但要注意重新启动活动的问题。
推荐文章
- Android:允许平板电脑竖屏和横屏,但强制手机竖屏?
- 如何使布局与视图填充剩余的空间?
- 字符串资源新行/n不可能?
- 如何点击或点击一个TextView文本
- Android房间-简单的选择查询-不能访问数据库在主线程
- Android: ScrollView vs NestedScrollView
- 错误:无法运行mksdcard SDK工具
- 未附加到窗口管理器的视图崩溃
- 将焦点设置为EditText
- 如何把空格字符放入XML字符串名?
- 我可以设置“android:layout_below”在运行时编程?
- Android Studio谷歌JAR文件导致GC开销限制超过错误
- 为什么每当我创建一个新项目时,Eclipse都会自动添加appcompat v7库支持?
- 如何同步项目到GitHub与Android工作室?
- Keytool错误:java.io。IoException:错误的AVA格式