1.Android Studio工作区
菜单栏File->New->New Project 新建项目,在打开的页面(图1)中选择Empty Activity
图1 新建项目
在New Project页面中填入Name,选择Save location、Language(Java or Kotlin)、最低SDK版本,如图2所示。
图2 新建项目
如图2所示,包名(Package name)遵循了“DNS反转”的约定,也就是将组织或公司的域名反转后,在尾部附加上应用名称。遵循此约定可以保证包名的唯一性。一直以来,Java是Android开发唯一的官方支持语言,直到2017.05,Android开发团队在Google I/O大会上宣布Kotlin为Android开发又一官方支持语言。但是本学习笔记依旧采用Java语言。
Android Studio工作区窗口区域划分如图3所示。导航栏和工具栏以及最上方的菜单栏不用多说了。周围一圈是工具窗口栏,平常都是隐藏状态,需要哪个点出来即可。中间区域是编辑器窗口,写xml和java代码都是在这个地方。左侧和下方是工具窗口,其中左侧是项目工具窗口,能够查看和管理所有与项目相关的文件,可以切换为Android视角、Project视角或其他视角;下方是构建工具窗口,可以在这里看到项目的编译过程和构建状态。
图3 Android Studio工作区划分
2.项目组成
在Android视角下,项目包括app和Gradle Scripts两部分。其中app表示app模块,包含三个子目录,如图4所示:
图4 app部分组成
1.manifests子目录,里面包含AndroidManifest.xml文件,是app的运行配置文件。
2.java子目录,包含三个名称相同的包。第一包存放当前模块的java源代码,后两个存放测试用的java代码。
3.res子目录,存放当前模块的资源文件,其下包括四个子目录:
- drawable子目录存放图形描述文件与图片文件;
- layout子目录存放app页面的布局文件;
- minmap子目录存放app的启动图标;
- values子目录存放一些常量定义文件,e.g., 字符串常量strings.xml,像素常量dimens.xml,颜色常量colors.xml,样式风格定义styles.xml等。
Gradle Scripts部分主要包括工程的编译配置文件,如图5所示,主要有:
图5 Gradle Scripts部分组成
1.build.gradle文件,分为Project(项目级)和Modul(模块级),用于描述编译规则
2.gradle.properties,配置编译工程的命令行参数,一般无需改动
3.proguard-rules.pro,用于描述java代码的混淆规则
4.settings.gradle,配置需要编译哪些模块,默认是app,表示只编译app模块
5.local.properties,项目的本地配置文件,在工程编译时自动生成,用于描述开发者电脑的环境配置,包括SDK、NDK的本地路径等。
3.视图部件常用属性
新建Empty Activity项目,Android Studio会自动建立MainActivity.java文件和与之相对应的activity_main.xml布局文件。按照约定,布局文件按的命名基于其关联的*activity.java文件:‘activity_’+activity.java文件去掉Activity部分并全部转小写,单词之间以下划线隔开。例如,SplashScreenActivity.java对应的布局文件名为activity_splash_screen.xml。
双击app/res/layout/activity_main.xml文件,编辑视图文件。在右上角可以切换Code/Split/Design视角。我个人日常喜欢用Split视角。
视图(View)是用户界面的构造模块。显示在屏幕上的一切都是视图。用户能看到并与之交互的视图称为部件(widget,也可称为控件)。widget是View的一个子类。有些部件用来显示文字(TextView)或图像(ImageView),有些部件可以用来点击以触发事件任务(Button)。ViewGroup是View的一个特殊子类,它包含并布置其他视图,因此又被称为布局,规划其他视图内容应该显示在哪里。
部件的常用属性(tip:并不是所有的部件都具有如下属性):
- layout_width, layout_height
https://developer.android.google.cn/reference/android/view/ViewGroup.LayoutParams?hl=zh-cn#attr_android:layout_height
分别用于指定视图的宽度和高度。几乎每类部件都需要指定这两个属性。其值可以是固定数值或者特定参数,e.g.,
android: layout_height="wrap_content" // 表示与内容自适应。本文需要多大的显示空间,当前视图就占据多大尺寸。但是最宽不能超过上级视图的宽度,否则就要换行;最高不能超过上级视图的高度,否则就会被隐藏。 android: layout_height="match_parent" // 表示与上级视图保持一致 android: layout_height="5dp" // 固定数值5dp,关于dp, sp, px的区别见下文
- layout_margin, layout_marginLeft, layout_marginRight, layout_marginBottom, layout_marginEnd, layout_marginHorizontal, layout_marginStart, layout_maginTop, layout_marginVertical
https://developer.android.google.cn/reference/android/view/ViewGroup.MarginLayoutParams?hl=zh-cn
指定边距,值可以为负数。边距属性是布局参数,决定了部件间的距离。由于部件对外界一无所知,因此边距必须由该部件的父部件负责。margin provides the space between the border and outer elements.
- padding, paddingLeft, paddingRight, paddingBottom, paddingEnd, paddingHorizontal, paddingStart, paddingTop, paddingVertical
https://developer.android.google.cn/reference/android/view/View?hl=zh-cn#size,-padding-and-margins
指定内边距,值不可以为负数。不是布局参数,表示在绘制部件自身时,要比所含内容大多少。padding provides the space between the border and the content of an element
- text
指定部件要显示的文字内容。属性值可以采用硬编码的方式,即直接指定固定的值,例如android: text=”Beijing is the capital of China.”。但是最好不要直接使用字符串值,而是应以’@string/’语言形式对字符串资源的引用。字符串资源放在app/res/values/strings.xml文件中。例如,下方代码显示在strings.xml文件中,定义了名为test的字符串。
<resources> <string name="app_name">FirstJavaDemo</string> <string name="test">Beijing is the capital of China.</string> </resources>
那么在activity_main.xml文件中可以引用test字符串。例如下方代码中android: text=”@string/test”
<TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="2" android:gravity="center" android:text="@string/test" android:textSize="20dp"/>
- textsize
指定部件要显示的文本大小,需要指定单位。文本大小的单位包括px,dp,sp
px(pixels):手机屏幕的最小显示单位,与设备的显示屏有关。不推荐使用px。
dp(virtual pixel unit, density-independent pixel),与设备无关的显示单位,只与屏幕的尺寸有关。通常,在设置边距、内边距或任何不打算按像素值指定尺寸的情况下,都使用dp单位。使用dp的好处是,无论屏幕密度如何,总能获得同样的尺寸。
sp(scale independent pixels):跟dp差不多,专门用来设置字体大小。手机在系统设置里可以调整字体大小。设置普通字体时,同数值的dp和sp一样大;如果设置为大字体,用dp设置的文字大小没有变化,用sp设置的文字就变大了。如图6所示。sp是Android推荐的字号单位。
图6 dp与sp的区别
像素是图像构成的基本单元。单个像素的大小并不固定,跟随屏幕大小和像素数量的关系变化,一个像素点为1px。分辨率(resolution)是指屏幕的垂直和水平方向的像素数量。分辨率是1920*1080,表示垂直方向有1920个像素,水平方向有1080个像素。像素密度(dpi)是指屏幕上每英寸(1英寸=2.54cm)距离中有多少个像素点,单位是PPI(pixels per inch)。密度(density)是指屏幕上每平方英寸中含有的像素点数量。Android中,规定以160PPI为基准:1dp=1px。
OPPO Reno8 6.43英寸,分辨率2400*1080
斜边像素数量:math.floor(math.sqrt(2400**2+1080**2))=2631
像素密度DPI=math.floor(2631/6.43)=409PPI
密度Density=409**2=167281
设备独立像素1dp=409/160=2.55px
4.常用的布局
4.1.线性布局 LinearLayout
https://developer.android.google.cn/reference/android/widget/LinearLayout?hl=zh-cn
下级视图按顺序排列。
主要属性:
- android: orientation 表示线性布局的方向,值可以为horizontal(水平布局)或者vertical(垂直布局)
- android: gravity 指定下级视图在线性布局内x,y轴方向上的定位。例如上方居中可以表示为”top|center_horizontal”,居中可以表示为”center”,左下方可以表示为”left|bottom”
- android: layout_gravity 设置自身相当于父容器的对齐方式
- android: layout_weight 表示权重,指线性布局的下级视图各自拥有多大比例的宽或高。指定layout_weight时,layout_width或者layout_height属性之一需要设置为0dp。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:layout_margin="20dp"> <TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="2" android:text="@string/test_bj" android:textSize="30dp" android:gravity="center"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_true" android:layout_gravity="center" android:layout_marginRight="20dp"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_false" android:layout_gravity="center" android:layout_marginLeft="20dp"/> </LinearLayout> </LinearLayout>
LinearLayout
4.2.相对布局 RelativeLayout
https://developer.android.google.cn/reference/android/widget/RelativeLayout?hl=zh-cn
下级视图的位置由其他视图决定。如果没有设定下级视图的参照物,下级视图默认显示相对布局内部的左上角。用于确定下级视图位置的参照物包括:
- 与该视图自身平级的视图(引用指定视图的id)
相对位置的属性取值 | 相对位置说明 |
layout_toLeftOf | 当前视图在指定视图的左边 |
layout_toRightOf | 当前视图在指定视图的右边 |
layout_above | 当前视图在指定视图的上方 |
layout_below | 当前视图在指定视图的下方 |
layout_alignLeft | 当前视图与指定视图的左侧对齐 |
layout_alignRight | 当前视图与指定视图的右侧对齐 |
layout_alignTop | 当前视图与指定视图的顶部对齐 |
layout_alignBottom | 当前视图与指定视图的底部对齐 |
- 该视图的上级视图,也就是它归属的RelativeLayout
相对位置的属性取值 | 相对位置说明 |
layout_centerInParent | 当前视图在上级视图中间 |
layout_centerHorizontal | 当前视图在上级视图的水平方向居中 |
layout_centerVertical | 当前视图在上级视图的垂直方向居中 |
layout_alignParentLeft | 当前视图与上级视图的左侧对齐 |
layout_alignParentRight | 当前视图与上级视图的右侧对齐 |
layout_alignParentTop | 当前视图与上级视图的顶部对齐 |
layout_alignParentBottom | 当前视图与上级视图的底部对齐 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@color/black" android:text="Center In Parent" android:textSize="20dp" android:textColor="@color/purple_200"/> <TextView android:id="@+id/tv_center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:background="@color/purple_500" android:text="Center Horizontal" android:textColor="@color/white" android:textSize="20dp"/> <TextView android:id="@+id/tv_center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="Center Vertical" android:textSize="20dp"/> <TextView android:id="@+id/tv_parent_left_bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:text="Parent Left and Bottom" android:textSize="20dp"/> <TextView android:id="@+id/tv_parent_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="Parent Right" android:textSize="20dp"/> <TextView android:id="@+id/tv_center_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/tv_center" android:layout_alignTop="@id/tv_center" android:text="Right to Center" android:textSize="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/tv_center" android:layout_marginBottom="40dp" android:layout_alignLeft="@id/tv_center" android:text="Above Center" android:textSize="20dp"/> </RelativeLayout>
RelativeLayout
4.3.网格布局 GridLayout
https://developer.android.google.cn/reference/android/widget/GridLayout?hl=zh-cn
线性布局不支持多行多列的布局方式,只支持单行或单列的布局方式。若要实现类似表格那样的多行多列形式,可采用网格布局。网格布局默认从左到右,从上到下排列。
主要属性:
- android:columnCount,指定网格的列数
- android:rowCount,指定网格的行数
<?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:columnCount="2" android:rowCount="2"> <TextView android:layout_rowWeight="1" android:layout_columnWeight="1" android:gravity="top|left" android:background="@color/purple_200" android:text="top left" android:textSize="20dp"/> <TextView android:layout_rowWeight="1" android:layout_columnWeight="1" android:gravity="center" android:text="top right" android:textSize="20dp" android:background="@color/purple_500"/> <TextView android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="bottom left" android:textSize="20dp" android:gravity="bottom|center" android:background="@color/teal_200"/> <TextView android:layout_rowWeight="1" android:layout_columnWeight="1" android:text="bottom right" android:textSize="20dp" android:gravity="center|right" android:background="@color/teal_700"/> </GridLayout>
GridLayout
4.4.框架布局 FrameLayout
https://developer.android.google.cn/reference/android/widget/FrameLayout?hl=zh-cn
框架布局中的视图以层叠的方式显示。第一个添加的显示在最底层,最后添加的显示在最顶层,上层视图会覆盖下层视图。
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="center" android:src="@drawable/max" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="40dp" android:background="#4C374A" android:padding="10dp" android:text="Max Karl Ernst Ludwig Planck" android:textColor="#FFFFFF" android:textSize="20sp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|bottom" android:background="#AA000000" android:padding="10dp" android:text="18/July/2022" android:textColor="#FFFFFF" android:textSize="18sp" /> </FrameLayout>
FrameLayout
上面代码构造出来的页面如下图所示。
框架布局下有一些常用的子类:
滚动视图(默认是垂直滚动) ScrollView 水平滚动视图 HorizontalScrollView
https://developer.android.google.cn/reference/android/widget/ScrollView?hl=zh-cn
垂直滚动的layout_width属性值设置为match_parent,layout_height属性值设置为wrap_content
水平滚动layout_width属性值设置为wrap_content,layout_height属性值设置为match_parent
滚动视图节点下面必须只能挂着一个子布局节点,否则会报错。
原创文章,作者:sunnyman218,如若转载,请注明出处:https://blog.ytso.com/tech/275634.html