该文章笔记代码是从慕课网自定义view课程中学习到的,有兴趣的同学可以学习一下
我们需要实现的自定义view的样式
1508123594281.jpg
看似简单其实,两个button,一个textview,但是其实用自定义都是需要我们在class中挨个添加的而且,这个耦合性低,更好当作一个应用的标题工具类进行扩展
第一步
创建一个自定义view的视图,我们需要把命名空间需要自己定义的属性给定义好
1508122866605.jpg
- 在res/values/文件夹下创建attrs.xml文件,用来自定义属性
- 需要声明 declare-styleable 属性名,这是我们自定义的一些属性名,在这里要注意一下format为属性格式,reference与color一起定义的话可以引用drawable下的图片或者十六进制的颜色格式。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Topbar">
<attr name="title" format="string" />
<attr name="titleTextSize" format="dimension" />
<attr name="titleTextColor" format="color" />
<attr name="leftTextColor" format="color" />
<attr name="leftBackground" format="reference|color" />
<attr name="leftText" format="string" />
<attr name="rightTextColor" format="color" />
<attr name="rightBackground" format="reference|color" />
<attr name="rightText" format="string" />
</declare-styleable>
</resources>
- 自定义一个类继承自RelativeLayout,用相对布局进行实现,当然线性布局也可以
package com.yinhao.myui;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by yinhao on 2017/10/13.
*/
public class Topbar extends RelativeLayout {
private Button leftButton, rightButton;
private TextView tvTitle;
private int leftTextColor;
private Drawable leftBackground;
private String leftText;
private int rightTextColor;
private Drawable rightBackground;
private String rightText;
private int titleTextColor;
private float titleTextSize;
private String title;
private LayoutParams leftParams, rightParams, titleParams;
private TopbarClickListener listener;
public Topbar(Context context) {
this(context, null);
}
public Topbar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Topbar(final Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Topbar);
leftTextColor = ta.getColor(R.styleable.Topbar_leftTextColor, 0);
leftBackground = ta.getDrawable(R.styleable.Topbar_leftBackground);
leftText = ta.getString(R.styleable.Topbar_leftText);
rightTextColor = ta.getColor(R.styleable.Topbar_rightTextColor, 0);
rightBackground = ta.getDrawable(R.styleable.Topbar_rightBackground);
rightText = ta.getString(R.styleable.Topbar_rightText);
titleTextSize = ta.getDimension(R.styleable.Topbar_titleTextSize, 0);
titleTextColor = ta.getColor(R.styleable.Topbar_titleTextColor, 0);
title = ta.getString(R.styleable.Topbar_title);
ta.recycle();//回收,避免浪费资源,避免因为缓存引起的一些错误
leftButton = new Button(context);
rightButton = new Button(context);
tvTitle = new TextView(context);
leftButton.setTextColor(leftTextColor);
leftButton.setBackground(leftBackground);
leftButton.setText(leftText);
rightButton.setTextColor(rightTextColor);
rightButton.setBackground(rightBackground);
rightButton.setText(rightText);
tvTitle.setTextColor(titleTextColor);
tvTitle.setTextSize(titleTextSize);
tvTitle.setText(title);
tvTitle.setGravity(Gravity.CENTER);
setBackgroundColor(0xfff59563);
leftParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
addView(leftButton, leftParams);
rightParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
addView(rightButton, rightParams);
titleParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE);
addView(tvTitle, titleParams);
leftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.leftClick();
}
});
rightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.rightClick();
}
});
}
public interface TopbarClickListener {
void leftClick();
void rightClick();
}
public void setOnTopbarClickListener(TopbarClickListener listener) {
this.listener = listener;
}
}
-
我们来分步解释一下代码,在我写的attrs.xml文件中,定义了9个自定义的属性,分别是左边右边按钮的名字,背景和文字颜色。中间是标题名称,文字大小以及颜色。
-
我们应该如何在类中引用呢?context类中有一个方法obtainStyledAttributes,调用context.obtainStyledAttributes方法返回一个TypedArray类,我们自定义的属性集都在这个类中,参数是我们开始定义的declare-styleable的name值
-
接着我们就可以调用ta.getXXX的方法把每个单独的自定义属性取出来,这时候的格式是declare-styleable的name值加上每个单独的自定义的值。有些参数为两个参数,第二个为默认值,我们填0即可。
-
接着我们将自定义的button通过一些我们常用的Button或者TextView的一些方法将从TypedArray中取出来的值进行绑定。
-
那么现在还差一步,我们只是定义了颜色,可是在哪里声明控件呢?控件的大小怎么办,别急,我们一步步来
-
控制大小和控件所在的位置,我们需要new一个继承自RelativeLayout的LayoutParams,通过ViewGroup下的LayoutParams设置宽高,接着我们要调用RelativeLayout下特有的方法,通过addRule方法这三个控件相对于布局中的哪个位置,第二个参数为RelativeLayout特有的TRUE值,并非boolean的那种true值。最后通过addView方法将设置好的参数和控件放到咱们的主类里,也就是相对布局里面
-
如果我们想实现点击方法,我们可以直接写一个setOnClickListener内置的方法去调用,我们也可以一个接口,通过接口,我们降低耦合性,在以后每个不同的activity或者fragment中,自己再进行修改
-
最后,我们就需要在xml中声明控件了,把Topbar的全类名复制下来,这里要留意下,我们需要自定义一个命名空间,不然会出现找不到属性名的问题。在这里,我定义了一个叫custom的名字。把命名空间最后一个android改成res-auto,如果你用的是eclipse开发项目,可以使用Topbar的全类名。
这样,我们定义的自定义标头就算是完成了。
网友评论