上篇文章介绍了界面Activity的启动方式和生命周期,本篇将继续介绍在界面Activity中的内容是如何绘制展示给用户的。
在Android系统上运行新创建的界面Activtiy,给用户展示的是空白的。而得益于AndroidStudio的强大模板支持,新创建的界面Activity会自动重写onCreate()方法,并在该方法内自动创建以下两行类似默认代码。
super.onCreate(savedInstanceState)
setContentView(R.layout.xxx)
显然,setContentView()方法就是加载当前界面Activity的绘制内容,而名为R.layout.xxx的参数中的xxx,代指文件名,被称为布局文件。在系列文章首篇有提到res目录是存放应用资源的文件夹,该目录下有个名为layout的目录,就是专门存放布局文件的。
在AndroidStudio中,只要在layout目录下创建布局文件,就可以在java目录下源代码中通过调用R.layout中与布局文件同名的常量来使用,而其中的类名为R的文件,是在java(generate)目录的当前应用包名下自动生成的。
在AndroidStudio中新创建的布局文件默认生成如下模板,该文件符合xml文件格式,其中标签名只能是Android系统定义或我们应用内自定义的控件名,而其属性也只能使用已定义的属性。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</android.support.constraint.ConstraintLayout>
View视图,是Android系统绘制图形的基本单元类,也是系统与用户交互的基本单元类。所有的视图类追踪其父类,都可以追溯到同一个父类android.view.View。
如果直接在布局文件中添加视图使用,那么称这个视图是静态加载的。静态创建视图需要使用大量布局文件,在应用程序打包时占用大量存储空间,但是当应用程序安装之后,Android系统会更加快速的绘制这些视图。
相反地,也可以在源代码文件的当前界面Activity中,直接调用视图类的构造方法创建一个视图,并加载到当前界面中,那么称该视图是动态加载的。动态创建的视图是写入到源代码中,所以应用程序打包时不会占用太多存储空间,只是在应用程序安装运行后,Android系统需要更多时间去解析并绘制这些视图。
上面两种视图加载方式虽然有所差别,但是在不涉及大量视图加载的轻量级应用中差别不是很大。一般界面中的视图都是固定数量的,可以直接静态创建视图的,这样可以借助AndroidStudio的布局预览插件实时预览当前界面布局效果;只有在根据不同数据加载不同视图这种类似的动态改变大量界面时,可能动态加载视图的方式会更方便一些。
视图除了需要创建加载外,还可以修改其属性以便于Android系统区分绘制,同样地,既可以在静态加载时动态设置默认属性值,也可以在源代码中动态设置属性值。
注意:针对同一个属性,动态设置结果会优先覆盖静态属性值。
任何视图在创建加载后,有两个属性值是必须要指定的,那就是表示视图宽度和高度的尺寸,在布局文件中,静态加载的视图必须以标签中的android:layout_width和android:layout_height属性设置;在源代码中,动态加载的视图默认宽度和高度都是LayoutParams.WRAP_CONTENT,表示自适应内容尺寸,也可以调用视图类中的.layoutParams.width和.layoutParams.height变量直接访问或修改。
根据视图负责的任务不同,可大致分为容器类视图、展示类视图、编辑类视图三种类型。
android.widget.LinearLayout,对子视图使用相对位置绘制的相对布局android.widget.RelativeLayout,集合上述两种布局优势更加灵活绘制子视图相对位置的约束布局androidx.constraintlayout.widget.ConstraintLayout等。android.widget.TextView,展示图片的android.widget.ImageView,展示视频的android.widget.VideoView等。android.widget.EditText,允许用户选择时间并展示的android.widget.TimePicker,在用户操作需要提示时展示的android.widget.Toast等。正如上边举例的几个视图,都是在AndroidSDK中定义的视图,称为系统视图。系统视图都位于android.widget包下。
在日常开发中,只需要掌握如何使用系统视图即可。这里以动态加载的方式介绍几个常用视图案例。
首先是界面Activity对应的布局文件,以上文中AndroidStudio自动生成的模板布局文件为例,为了在源代码中获取到这个布局文件的根视图,在根视图<android.support.constraint.ConstraintLayout>标签中增加android:id 属性,属性值以@+id/开头表示新增属性值,可以定义任意值;而如果以@id/开头,只能使用已经定义过的属性值。所有新增的属性,都由AndroidStudio自动存储在前面提到的R文件中,在源代码中可以通过R.id.xxx常量获取,其中xxx即定义的属性值。
android:id="@+id/activity_main_root"
之后便可以在源代码的界面Activity中获取到该视图,并操作该视图例如增加子视图。
val rootLayout = findViewById<ConstraintLayout>(R.id.activity_main_root)
val button1=Button(this)
button1.text="按钮"
button1.id=R.id.button_1
val textView1=TextView(this)
textView1.text="文本展示区"
val layoutParamsButton1 = ConstraintLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
layoutParamsButton1.topMargin = 500
layoutParamsButton1.topToTop=rootLayout.id
layoutParamsButton1.leftToLeft=rootLayout.id
layoutParamsButton1.rightToRight=rootLayout.id
button1.layoutParams=layoutParamsButton1
val layoutParamsTextView1 = ConstraintLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
layoutParamsTextView1.circleConstraint=button1.id
layoutParamsTextView1.circleAngle=30f
layoutParamsTextView1.circleRadius=300
textView1.layoutParams=layoutParamsTextView1
rootLayout.addView(button1)
rootLayout.addView(textView1)
在上边代码中有用到R.id.button1变量,由于其绑定视图并未在布局文件中静态加载,所以该视图对应的id值只能在资源文件中单独声明,可以在res资源目录下新建一个xml格式的资源文件,在其中增加如下代码以创建一个id供上边源代码中使用。
<resources>
<item name="button_1" type="id"></item>
</resources>
最终上述代码的运行效果如下图。

虽然AndroidSDK提供的系统视图可以满足大部分常见场景,但是开发的乐趣在于自由绘制视图及交互。Android系统同样允许开发者自由定义视图以满足他们的特殊爱好需求。想必不需强调也能理解,这种自定义视图只能在定义该视图的所属modle模块中使用,或者在定义了自定义视图的所属modle模块的被依赖子modle模块中使用。对于自定义视图,其相关属性可能因视图而异,但是使用方式与系统视图类似,所以主要掌握如何定义自定义视图。这里以自定义的输入框为例简单说明。
自定义视图首先要在源代码中定义一个视图类,该类必须继承自android.view.View或其子类。在介绍视图分类时可以发现,容器类视图是另外两种视图的父类。所以一般在编辑类视图和展示类视图均不满足自定义视图的需求时,就直接选择容器类视图作为自定义视图的父类,而不是直接继承android.view.View。而如果自定义视图的需求与某个编辑类视图或展示类视图的功能重合,也就可以直接在该视图上修改,那么直接继承这个编辑类视图或展示类视图即可。
在继承视图类之后,Java语言的话,需要重写自定义视图的三个构造方法,而如果应用程序是运行在Android5.0及以上的系统上,还需要重写第四个构造方法。
Android版本号5.0,对应于Android API等级为21,对应Android版本简称为LOLLIPOP
public MyEditText(Context context) {
//动态加载视图时调用该构造方法
this(context, null);
}
public MyEditText(Context context, AttributeSet attrs) {
//静态加载视图时调用该构造方法
this(context, attrs, 0);
}
public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
//确保其他构造方法都最终调用该构造方法
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MyEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
而如果是Kotlin编写的话,只需要重写两个构造方法即可
@JvmOverloads
constructor(context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : super(
context,
attrs,
defStyleAttr
) {
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
constructor(
context: Context?,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) {
}
之后可根据需求重写三个父类方法。
onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int)方法,确保该自定义视图在其父视图的位置。onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)方法,确定该视图在绘制时的尺寸。onDraw(canvas: Canvas)方法,将该视图中的属性信息绘制到屏幕上。如果上述过程都没有问题,就可以像加载系统视图一样的加载自定义视图了。但是自定义视图往往也需要新增一些属性控制,如果简单的在该视图类中增加一些getter、setter方法以访问相关属性,这样就可以在源代码中像使用系统视图一样的动态加载自定义视图了。但是如果想在布局文件中静态加载视图,这就需要重写上述代码中的三参构造方法中了。
静态设置属性值,首先就要先创建固定的属性名,在res/values资源目录中创建xml格式的资源文件,并在其中定义属性值如下所示
<declare-styleable name="StyleMyEditText">
<attr name="myDefaultText" format="string" />
</declare-styleable>
之后在上述重写构造方法中获取这些属性值并赋予其实际意义即可。
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.StyleMyEditText)
val defaultText = typedArray.getString(R.styleable.StyleMyEditText_myDefaultText)
setText(defaultText)
typedArray.recycle() //回收代码不能少,否则容易内存泄漏
如此,就可以在静态加载自定义视图的布局文件中正常设置其属性值了。
<com.kotlin.helloword.MyEditText
android:layout_width="200dp"
android:layout_height="100dp"
app:myDefaultText="默认显示内容"
/>
自定义属性值通过app域使用,android域只能设置Android系统提供的固定属性值
内容有限,视图的简单使用先大致这些,详情案例可参考后续视频内容。而视图作为系统与用户交互的基本单元,其使用功能更加多元,下一章将继续介绍视图间的动画与交互。
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于