Android(安卓)自定义View(二):创建复合控件
另一个例子:自定义switch按钮
创建复合控件分为三步:
1. 设计属性
2. 实现View
3. 引用View
这里设计一个qq联系人界面的TopBar
其中有三部分组成,左边圆形头像,中间文本,右边按钮,还有个蓝色默认背景
1.设计属性
在Android Studio的res的values中右键新建XML文件qq_topbar_attrs.xml,内容如下
android中通过<declare-styleable>属性声明自定义属性,并通过name设置引用名称
通过属性声明具体的属性,如文字、标题、颜色,并通过format属性指定属性类型
declare-styleable:告诉系统,以下是我们自定义的属性
attr标签为自定义属性
format为所引用资源类型
Reference为drawable中的文件
<?xml version="1.0" encoding="utf-8"?>
第二步:创建自己的View
2.在layout中新建组合控件mytopbat.xml,qq顶部的TopBar
效果:
代码:
<?xml version="1.0" encoding="utf-8"?>
3.新建java类MyTopBar并继承一个布局,此处我们使用LinearLayout
然后系统会提示添加构造方法,这儿有四种构造方法,如下:
其中第一个为一般的控件,不需要自定义属性;而自定义属性需要一个Attrs参数,因此选第二个构造方法。
4.然后在java类中声明控件
//定义需要的控件 private CircleImageView headCImage; //头像 private TextView titleTView; //标题 private Button addButton; //添加
5..其次声明所需要的属性
//声明需要的属性 private Drawable background; private Drawable leftHead; private String title; private String addfriend;
6.之后要做的就是赋值,进行控件和属性的关联
在构造方法中获得在attr.xml中自定义的属性,并把属性值赋值给控件
通过TypedArray获得存储在attr.xml中所定义的属性集,如下
//得到自定义属性TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyTopBar);
其中R.styleable.MyTopBar的MyTopBar即在atts的declare-styleable中的name
7.通过TypedArray,就可以获得自定义的属性的值
其中属性名为styleable的名字加下划线,加自定义属性名,如下:
//获得自定义的属性的值 background = typedArray.getDrawable(R.styleable.MyTopBar_topbar_background); leftHead = typedArray.getDrawable(R.styleable.MyTopBar_topbar_leftHead); title = typedArray.getString(R.styleable.MyTopBar_topbar_title); addfriend = typedArray.getString(R.styleable.MyTopBar_topbar_addfriend);
8.TypedArray使用完要进行回收,避免浪费资源,如下:
//使用TypedArray后,要回收资源 typedArray.recycle();
9.之后需要实例化控件,使用动态加载布局的方法
//动态加载布局 View view = LayoutInflater.from(getContext()).inflate(R.layout.mytopbar,this); //最后实例化控件 initView();
private void initView() { //最后实例化控件 headCImage = (CircleImageView) findViewById(R.id.myview_topbar_head); titleTView = (TextView) findViewById(R.id.myview_topbar_title); addButton = (Button) findViewById(R.id.myview_topbar_addfriend); }
10.有了控件,之后就需要把自定义属性赋值给控件,如下:
//自定义属性赋值给控件 headCImage.setImageDrawable(leftHead); titleTView.setText(title); addButton.setText(addfriend); //设置背景 setBackground(background);
11.最后就是点击事件了,qq顶部Topbar只有头像和添加可以点击,因此,设置两个监听事件
一般有一下三步完成接口回调机制,
(1) 定义接口,在点击接口中设置点击虚函数,头像点击事件,添加点击事件
//定义点击接口 public interface MyTopBarClickListener{ public void headListener(); public void addListener(); }
定义之后需要声明这个借口的私有对象,以便使用
//声明点击接口对象MyTopBarClickListener myTopBarClickListener;
(2) 设置一个监听方法,给调用者,参数为接口类型,如下:
//定义设置点击接口方法 public void setMyTopBarClickListener(MyTopBarClickListener listener){ this.myTopBarClickListener = listener; }
(3) 修改控件点击事件,如下:
private void initEvent() { //头像点击事件 headCImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { myTopBarClickListener.headListener(); } }); //添加按钮点击事件 addButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { myTopBarClickListener.addListener(); } }); }
(4)除了事件的点击接口,我们还可以设置一些共有方法,方便控制,如setText等
//除了事件的点击接口,我们还可以设置一些共有方法,方便控制,如setText等 public void setMyTopBarTitle(String title){ //得到传入的值 this.title = title; //赋值给控件 titleTView.setText(this.title); }
第三步:引用自定义View
1. 添加到布局文件,如下:
这里需要注意,怎么使用我们自定义的属性,很简单类型java的import,首先引入我们的自定义控件,
然后按住ctrl加左键单击android会弹到上方的
android:layout_width="match_parent"
复制这句话,粘贴在下面,并改为app(或自定义),引用第三方包名的时候只需要把末尾的android替换为res-auto即可,如下,
xmlns:app="http://schemas.android.com/apk/res-auto"
不过不要和系统的android一样
效果:
2.在MainActivity中实例化,并重写点击事件,如下
private MyTopBar myTopbarActivity; myTopbarActivity = (MyTopBar) findViewById(R.id.my_topbar); //这样点击头像,标题变为头像,点击添加标题变为添加 myTopbarActivity.setMyTopBarClickListener(new MyTopBar.MyTopBarClickListener() { @Override public void headListener() { Toast.makeText(MyTopbarActivity.this,"头像",Toast.LENGTH_SHORT).show(); myTopbarActivity.setMyTopBarTitle("Click头像"); } @Override public void addListener() { Toast.makeText(MyTopbarActivity.this,"添加",Toast.LENGTH_SHORT).show(); myTopbarActivity.setMyTopBarTitle("Click添加"); } }); }
最后给出MyTopBar.java的代码:
public class MyTopBar extends LinearLayout { //定义需要的控件 private CircleImageView headCImage; //头像 private TextView titleTView; //标题 private Button addButton; //添加 //声明需要的属性 private Drawable background; private Drawable leftHead; private String title; private String addfriend; //声明点击接口对象 MyTopBarClickListener myTopBarClickListener; public MyTopBar(Context context) { super(context); } public MyTopBar(Context context, AttributeSet attrs) { super(context, attrs); initAttrs(attrs); initEvent(); } private void initView() { //最后实例化控件 headCImage = (CircleImageView) findViewById(R.id.myview_topbar_head); titleTView = (TextView) findViewById(R.id.myview_topbar_title); addButton = (Button) findViewById(R.id.myview_topbar_addfriend); } private void initEvent() { //头像点击事件 headCImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { myTopBarClickListener.headListener(); } }); //添加按钮点击事件 addButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { myTopBarClickListener.addListener(); } }); } //进行控件和属性的关联 private void initAttrs(AttributeSet attrs) { //得到自定义属性 TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyTopBar); //获得自定义的属性的值 background = typedArray.getDrawable(R.styleable.MyTopBar_topbar_background); leftHead = typedArray.getDrawable(R.styleable.MyTopBar_topbar_leftHead); title = typedArray.getString(R.styleable.MyTopBar_topbar_title); addfriend = typedArray.getString(R.styleable.MyTopBar_topbar_addfriend); //使用TypedArray后,要回收资源 typedArray.recycle(); //动态加载布局 View view = LayoutInflater.from(getContext()).inflate(R.layout.mytopbar,this); //最后实例化控件 initView(); //自定义属性赋值给控件 headCImage.setImageDrawable(leftHead); titleTView.setText(title); addButton.setText(addfriend); //设置背景 setBackground(background); } //定义点击接口 public interface MyTopBarClickListener{ public void headListener(); public void addListener(); } //定义设置点击接口方法 public void setMyTopBarClickListener(MyTopBarClickListener listener){ this.myTopBarClickListener = listener; } //除了事件的点击接口,我们还可以设置一些共有方法,方便控制,如setText等 public void setMyTopBarTitle(String title){ //得到传入的值 this.title = title; //赋值给控件 titleTView.setText(this.title); }}
更多相关文章
- Android之cardview属性以及阴影处理
- Android(安卓)正 N 边形圆角头像的实现
- Android扩大控件的点击区域
- Android中的4.0新布局控件:Space和GridLayout
- Android(安卓)禁止ViewPager的滑动效果
- Android应用实例(一)之---有道辞典VZ.0
- [Android(安卓)API学习]AppWidget
- 自定义控件(一)
- 【Android】按钮设置字母不全部大写,button set text to lower ca