![Android 10 Kotlin编程通俗演义](https://wfqqreader-1252317822.image.myqcloud.com/cover/471/34752471/b_34752471.jpg)
5.5 让内容滚动
在上一节做的登录页面上增加一个按钮“注册”,将ID设为“buttonRegister”,放到“登录”按钮的下面,效果如图5-56所示。然后运行App,旋转一下屏幕,运行效果如图5-57所示。
“注册”按钮看不到了!为什么?显然屏幕的高度不够了,内容在纵向上超出了屏幕,怎么办呢?使用滚动条!然而,Layout是没有滚动功能的,要想提供滚动功能,需要使用控件ScrollView。
ScrollView可以在子控件高度超出自己的范围时在纵向上提供滚动功能。如果想横向滚动,可以使用HorizontalScrollView。各种ScrollView都有自己的要求:只能容纳一个子控件。
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P82_3296.jpg?sign=1739297687-zZuTNs4bXhbKEhmWfGLVWmvaLdsz4AoR-0-963df0f32abf70e2c47ebfb09f50eed3)
图5-56
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P82_3298.jpg?sign=1739297687-DGcMLugP5maa0VHxWfUOIo4847NxVp1G-0-2f8eff022003df041602dd24e3b3cc4e)
图5-57
我们让ConstraintLayout成为ScrollView的子控件,然后设置ConstraintLayout的高度由其内容决定,也就是由组成登录界面的各子控件来共同决定。ScrollView必须有办法计算出其子控件的高度才行,否则不知道该怎么滚。所以ConstraintLayout被放在ScrollView中后,其高度不能再设为match_parent,如果子控件的高度永远与它一样高,那么永远不需要滚动。其子控件应体现出内容的高度,这里也就是组成登录功能的控件共同占据的高度,所以RelativeLayout的layout_height值必须为wrap_content。下面我们按照这个原理一步步改造界面。
5.5.1 添加ScrollView作为最外层容器
可以试着拖一个ScrollView到页面中,如图5-58所示。不行,无法将控件拖到页面中作为最外层的控件,此时需要手动编辑源码。把页面切换到源码模式,在最外层的元素“<android.support.constraint. ConstraintLayout>”外面添加标记“<ScrollView>”,在ConstraintLayout的结束标记“</android.support. constraint.ConstraintLayout>”下面添加ScrollView的结束标记“</ScrollView>”,也就是让ScrollView元素包着RelativeLayout元素。然后,还需要把RelativeLayout标记中的一些属性(这些属性必须放在最外层的元素中)移动到ScrollView标记中:
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" tools:context=".MainActivity"
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P83_3315.jpg?sign=1739297687-VgtwADbPjWQfS1k3e23Xj1dSbdNzeSho-0-be78869fb750f885f79a657b909683c8)
图5-58
还要为ScrollView设置宽和高。它既然是最外层的控件,就应该充满整个父控件(Activity)。现在layout文件的源码变为:
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P83_9928.jpg?sign=1739297687-x3fmQ45y6PpnF98wsQde2sJp9bJ4SWQc-0-ecc9d751938931311d8e6b1e83d94b7d)
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P84_3324.jpg?sign=1739297687-Sq5B8ObuTsvzmr2VAzfotzndsMfvAUAl-0-1fe59027572c98cdd1ea31bcdf358e75)
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P85_9929.jpg?sign=1739297687-jjJQ4UfUVzlfW5aHa7QHJpN9OSGE2XMS-0-a403c3ceda8018e15fe4f29826fec7a4)
切换到预览模式,会惊奇地发现ConstraintLayout的高度变了,如图5-59所示。虽然ConstraintLayout的高度值还是match_parent,但是被放到在ScrollView中时这个值并不起作用,实际上却变成了wrap_content。
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P85_3341.jpg?sign=1739297687-fVyF3Zd35NCpHlhXGZU7DkK4yagFlJqI-0-e549760dfc412877b06e9038dc31cdbc)
图5-59
再运行App,旋转屏幕,就可以上下滚动了,效果如图5-60所示。
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P85_3343.jpg?sign=1739297687-K56C3YidiJvK0rmLuThjOi0mXm42zGj6-0-8f959cd4a4df6197c634caae077f46f6)
图5-60
5.5.2 禁止旋转
除了使用ScrollView外,还有一个办法可以解决横屏显示不全的问题,那就是不支持横屏!这需要固定Activity的方向,即在Manifest文件中设一下,如图5-61所示。
属性名screenOrientation表示屏幕方向,值portrait(原意是肖像画,是长的)表示竖屏、landscape(原意是风景画,是宽的)表示横屏。如果不设置此属性,就表示横竖屏都支持。
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P86_3359.jpg?sign=1739297687-YEsUjXvVHXBuvmFg5YJn8HFBO0iK36pF-0-331057c4f1b272f03846e7855c6e7129)
图5-61
5.5.3 为横屏和竖屏分别创建Layout
可以为一个页面创建横屏和竖屏两个资源。Android App会根据屏幕方向自动选择资源,为横屏和竖屏创建看起来很不一样的界面效果。实际上这个功能除了支持横屏和竖屏外,还支持不同的屏幕分辨率。当然最好还是用一个Layout能自适应横屏、竖屏和各种分辨率,但有时是做不到的。
下面将当前Layout作为竖屏资源,演示一下如何为它创建横屏资源。选择菜单命令,如图5-62所示。
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P86_3361.jpg?sign=1739297687-ZvbeTEIIrKaSTPylJnKYs1tNHFrw9nI9-0-0b18e74ab6d61a61e5c186c7fe9df817)
图5-62
选择“Create Landscape Variation(创建横屏变体)”命令,会为当前Layout添加一个新的资源文件。新文件默认复制了原文件的内容,可以在此基础上进行修改,比如把ScrollView去掉,因为我们可以在Landscape资源中以另一种方式摆放控件让它们充分利用横屏空间。
当前资源下面包含了两个文件(见图5-63),在文件系统中的组织和命名如图5-64所示。
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P86_3363.jpg?sign=1739297687-3NpZ4jGsqCQ9vUFE998wBEbe5bZhEkpH-0-f2da8d4eb93bd6fbc5f9b5f35320f8c1)
图5-63
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P86_3365.jpg?sign=1739297687-SWjT1s7yEigmmgiKMIvA1d3lSnlNpsNT-0-3ff237daba0e7778262096f0e0e53aaa)
图5-64
5.5.4 让内容居中
现在还有一个不完美的地方:内容不居中。在竖屏时,内容靠在上部,最好的方式是屏幕足够时居中,屏幕不够时滚动。注意,要先把横屏layout文件删掉。
ScrollView代表屏幕(充满父控件),ConstraintLayout代表内容区,只要设置ConstraintLayout在ScrollView纵向上居中就能达到目标。设置方法有两种:一是查找ScrollView中是否存在设置子控件摆放位置的属性,二是查找ConstraintLayout中是否存在设置其在父控件中如何摆放的属性。ConstraintLayout中有个叫layout_gravity的属性,表示其在父控件中的重心,有很多值可以设置,这里设置为center_vertical,如图5-65所示。
![](https://epubservercos.yuewen.com/232C60/18562449008361306/epubprivate/OEBPS/Images/Figure-P87_3384.jpg?sign=1739297687-Z0Sr1NGmTB9VI6CF6jUOelG9sFnyj9j8-0-0cba124e287339473daf82847efbe6de)
图5-65
ConstraintLayout纵向居中了,收工!