03UI开发-自定义控件
2018-03-17 本文已影响19人
何惧l
我们所使用的控件都是直接或者间接的继承自View
所有的布局都是直接或者间接的继承自ViewGroup
引入布局
虽然Android系统给每个活动提供了标题栏功能,但是在这里我们不使用它,创建一个自己的标题栏
但是,若是在每个布局中都创建也给标题栏,那么就会导致代码的重复,这个时候,先建立一个布局的title.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/weilai">
<Button
android:id="@+id/but_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Back"
android:layout_gravity="left"
android:layout_margin="5dp"/>
<TextView
android:id="@+id/text_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="未来"
android:paddingTop="5dp"
android:gravity="center"
android:textColor="#FFF0F5"
android:textSize="25sp"
android:layout_weight="1"/>
<Button
android:id="@+id/but_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_margin="5dp"
android:text="Edit" />
</LinearLayout>
- android:background="@drawable/weilai":这个属性是背景,可以是颜色或者照片
现在标题栏布局已经完成了,那么剩下的任务就是如何在程序中使用这个标题栏了,修改main_layout.xml中的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/title"/>
</LinearLayout>
这是,只是用一句话就可以把这个标题布局引入过来了
但是别忘了在MainActivity中将系统自带的标题栏隐藏掉
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
actionBar.hide();
}
}
}
-
调用了getSupportActionBar()获取ActionBar的实例,然后把它隐藏起来了
2018-03-16_17-12-18.png
创建自定义控件
引入布局的方式确实解决了重复编写代码的问题,但是如果布局中有一些控件要求能够响应事件,我们还是需要在每个活动中为这些控件单独编写一次事件的注册代码,比如说这个标题栏的返回按钮,在哪一个活动中,这个按钮的功能是相同的,都是销毁当前的活动
- 新建TitleLayout继承自LinearLayout,让它成为标题栏控件
public class TitleLayout extends LinearLayout{
public TitleLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title,this);
}
}
- 首先,重写了LinearLayout中带有两个参数的构造函数,在布局中引入TitleLayout就会调用这个构造函数
- 然后,在构造函数中需要对标题栏布局进行动态加载,这个时候就使用到了LayoutInflater来实现,并通过LayoutInflater.from()方法可以构建出一个LayoutInflater的对象,然后调用inflate()方法就可以动态加载一个布局文件
- inflate()方法可以传递两个参数,第一个就是要加载的文件,第二个就直接this
- 现在自定义控件创建好了,需要在布局文件中添加这个自定义的控件,在activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.md.uilayouttest.TitleLayout
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
- 添加自定义的控件和添加普通的控件一样,只不过在指定的过程中得指明控件的类名
- 此时的效果和使用引入布局方式的效果是一样的
- 为标题栏中的按钮添加注册事件,修改TitleLayout中的代码
public class TitleLayout extends LinearLayout{
public TitleLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title,this);
Button button1 = (Button)findViewById(R.id.but_1);
Button button2 = (Button)findViewById(R.id.but_2);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 获取当前的活动并销毁
((Activity)getContext()).finish();
}
});
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getContext(),"you click Edit",Toast.LENGTH_SHORT).show();
}
});
}
}
getContent()就是获取活动
还是一样的,通过findViewById()找到按钮,注册点击事件,当按第一个按钮的时候销毁当前的活动,按第二个按钮的时候弹出一句话
2018-03-16_17-45-04.png
这样的话,每当我们在一个布局中引入了TitleLayout时,返回键和编辑键点击事件就自动实现好了
- 自己动手写一个
-
第一个页面,点击按钮的时候进入第二个页面
2018-03-16_18-09-28.png -
在第二个页面中,也使用了同样的方式引用,返回键和编辑键自动实现好了
2018-03-16_18-13-11.png
-