素材巴巴 > 程序开发 >

anroid 自定义控件

程序开发 2023-09-17 15:05:04

anroid 自定义控件

@author lisiwen

@createTime 2022/4/11

示例代码地址:https://github.com/NET-lisiwen/UICustomViews/tree/master

文章目录


​ 之前我们学习了Android中一些常用控件和基本布局的用法,不过当时我们并没有关注这些控件的布局的继承结构,现在来看一下

在这里插入图片描述

​ 可以看到我们所用的所有控件都是直接或者间接继承自View的,所用的所有布局都是直接或间接继承自ViewGroup的。View是Android中最基本的一种UI组件,它可以在屏幕上绘制一块矩形区域,并能相应这块区域的各种事件,因此,我们使用的各种控件其实就是在view的基础上又添加了各自特有的功能。而ViewGroup则是一种特使的View,它可以包含很多子View和子ViewGroup,是一个用于放置控件和布局的容器。

​ 这个时候我们就可以思考一下,当系统自带的控件并不能满足我们的需求时,可不可以利用上面的继承结构来创建个自定义的控件呢?答案时肯定的,下面我们就来尝试一下创建自定义控件的两种简单方法。

1.引入布局

​ 如果说使用过iphone,应该知道,iphone应用的界面顶部都有一个标题栏,标题栏上会有一到两个按钮用于其他操作因为iphone没有专门的返回键。现在在很多Android程序喜欢模仿iphone风格,会在界面的顶部也放置一个标题栏。虽然说android给每个activity提供了标题栏的功能,我们这里先决定不使用他,而是创建一个自定义个标题栏。

​ 经过前两节的学习之后,创建一个自定义的标题栏相信已经不是什么难事了,使用LinearLayout布局加入两个Button和一个TextView就好了。可是这样会有一个问题,一般我们一个应用程序可能又很多activity,如果都需要这样的标题栏,那么就是说每个activity中都要写一遍相同的代码,不但会导致大量的代码重复,并且也会比较难以维护。这时我们就需要引入布局的方式来解决这个问题,在layout目录下新建一个title.xml布局,代码如下


 
 
 

​ 可以看到我们在LinearLayout中分别加入了两个Button和一个TextView,左边的Button用于返回,右边的Button可用于保存,中间的TextView可以显示一段标题文本。上面代码中属性大多都是见过的,这个用的一个全新的属性就是android:background,这个就是设置当前标题栏布局的背景色,当然也可以是一张图片,我这里图方便就使用的颜色。

​ 现在标题栏布局已经编写好了,剩下的就是如何在程序中使用这个标题栏了,修改activity_main.xml的代码,如下所示


 
 
 

​ 没错这里使用一个include语句引入刚才的标题栏布局就可以了。然后下边加入一个TextView来显示内容

​ 关键的一步,还需要再MainActivity中将系统自带的标题栏隐藏掉,代码如下所示:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if (getSupportActionBar() != null) {getSupportActionBar().hide();}}
 }
 

​ 这里我们调用了getSupportActionBar()方法来获得ActionBar的实例,然后再调用他的hide()方法将标题栏隐藏起来。运行一下程序 结果如下所示

在这里插入图片描述

​ 使用这种方式,不管有多少布局需要添加标题栏,只需要一行include就可以了

2.创建自定义控件

	引入布局的技巧的确解决了重复编写布局代码的问题,但是如果布局中有一些控件要求能够响应时间,我们还需要在每个Activity中为这些控件单独编写一次时间注册的代码。比如标题栏中的返回按键,其实不管是哪一个Anticity中这个按键的功能都是相同的,即销毁当前Activity,而如果在每个Activity中都需要重新注册一遍返回按钮的点击事件,无疑会增加很多重复代码,这种情况最好是使用自定义控件的方式来解决。
 

​ 新建TitleLayout继承自LinearLayout,让他称为我们自定义标题栏的控件,代码如下

public class TitleLayout extends LinearLayout {public TitleLayout(Context context) {super(context);init(context);}public TitleLayout(Context context, AttributeSet attrs) {this(context);}private void init(Context context) {LayoutInflater.from(context).inflate(R.layout.title, this);}
 }
 

​ 我们在TitleLayout的构造参数中调用init初始化方法,在其中对标题栏的布局进行加载,这时候就要借助LayoutInflater来实现了。通过LayoutInflater的from()方法可以构建出一个LayoutInflater对象,然后调用inflate方法就可以动态加载一个布局文件。inflate()方法接受两个参数,第一个参数是要加载的布局文件的id,这里我们传入R.layout.title,第二个参数就是给加载好的布局再添加一个父布局,这里我们需要指定为TitleLayout,于是直接传入this。

​ 现在自定义控件已经创建好了,接下来我们需要在布局文件中添加这个自定义控件,修改activity_main.xml的代码,如下所示


 
 
 

​ 添加自定义控件和添加普通控件的方式是基本一直的,只不过就是添加自定义控件的时候,要指定完整的包名,包名在这里是不可以省略的。

​ 重新运行程序,你会发现此时的效果和使用引入布局的方式的效果是一样的。

​ 下面我们尝试给标题栏的button添加点击的监听事件,修改TitleLayout中的代码如下所示

public class TitleLayout extends LinearLayout implements View.OnClickListener {public TitleLayout(Context context) {super(context);init(context);}public TitleLayout(Context context, AttributeSet attrs) {this(context);}private void init(Context context) {LayoutInflater.from(context).inflate(R.layout.title, this);findViewById(R.id.backbutton).setOnClickListener(this);findViewById(R.id.savebutton).setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.backbutton:Toast.makeText(getContext(), "click back button", Toast.LENGTH_SHORT).show();if (getContext() instanceof Activity) {((Activity) getContext()).finish();}break;case R.id.savebutton:Toast.makeText(getContext(), "click save button", Toast.LENGTH_SHORT).show();break;default:Toast.makeText(getContext(), "click default button", Toast.LENGTH_SHORT).show();break;}}
 }
 

​ 这里我们分别给返回和保存按钮注册了点击时间,当点击返回按键的时候,会进行一次点击提示,然后销毁将context转为Activity并且调用finish()销毁当前activity,点击保存按钮时,弹出一段文本。

​ 重新运行程序,点击一下保存按钮,效果如图所示

在这里插入图片描述

​ 这样的话,每当我们在一个布局中阴图TitleLayout时,返回按键和编辑按钮的点击事件就已经自动实现好了,就省去了很多重复代码的工作


标签:

上一篇: 网校平台后台 下一篇:
素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。