在平时开发android过程中,我们都是直接使用系统自带的UI模板,不知道有没有朋友想过,当你要修改某样东西的时候,是不是大部分都要进行修改呢?这样的话工作量就大了。下面我们以一个标题栏TopBar来为大家讲解如何自定义一个UI模板。看看效果图

首先打开android studio,在res资源目录下的values目录中,新建一个attrs.xml文件,这个文件用来存放自定义的view属性常量,如图

新建好文件后,写入上述代码。代码中定义了一个declare-styleable标签,取名为TopBar。标签内包含了标题栏中的三个控件,左边的back按钮,中间的标题栏,右边的more按钮。

写完属性后,就可以新建一个名为TopBar的java文件了,但是注意,这个文件要继承RelativeLayout类

接下来要做的事情就是把刚才定义的那些属性封装起来,然后加入到view中,下面我直接把代码贴出来,供大家参考。

public class TopBar extends RelativeLayout {
private Button leftButton,rightButton;
private TextView titleTV;
private String titleText,leftText,rightText;
private float titleTextSize;
private int titleTextColor,leftTextColor,rightTextColor;
private Drawable leftBackground,rightBackground;
private LayoutParams titleParams,leftParams,rightParams;
//左右按钮点击事件的接口(接口回调机制)
public interface topbarClickListener{
public void leftClick();
public void rightClick();
}
private topbarClickListener listener;
public void setOnTopbarClickListener(topbarClickListener listener){
this.listener = listener;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public TopBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.TopBar);
titleText = typedArray.getString(R.styleable.TopBar_titleText);
leftText = typedArray.getString(R.styleable.TopBar_leftText);
rightText = typedArray.getString(R.styleable.TopBar_rightText);
titleTextSize = typedArray.getDimension(R.styleable.TopBar_titleTextSize,0);
titleTextColor = typedArray.getColor(R.styleable.TopBar_titleTextColor,0);
leftTextColor = typedArray.getColor(R.styleable.TopBar_leftTextColor,0);
rightTextColor = typedArray.getColor(R.styleable.TopBar_rightTextColor,0);
leftBackground = typedArray.getDrawable(R.styleable.TopBar_leftBackground);
rightBackground = typedArray.getDrawable(R.styleable.TopBar_rightBackground);
//回收
typedArray.recycle();
//设置属性值
titleTV = new TextView(context);
leftButton = new Button(context);
rightButton = new Button(context);
titleTV.setText(titleText);
titleTV.setTextSize(titleTextSize);
titleTV.setTextColor(titleTextColor);
titleTV.setGravity(Gravity.CENTER); //设置标题为居中
leftButton.setText(leftText);
leftButton.setTextColor(leftTextColor);
leftButton.setBackground(leftBackground);
rightButton.setText(rightText);
rightButton.setTextColor(rightTextColor);
rightButton.setBackground(rightBackground);
//设置整个TopBar的背景色
setBackgroundColor(Color.WHITE);
//把控件放入layout中,属性参数(宽,高)
titleParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE); //增加规则(居中)
addView(titleTV,titleParams); //增加到View中
leftParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE); //增加规则(左对齐)
addView(leftButton,leftParams);
rightParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE); //增加规则(右对齐)
addView(rightButton,rightParams);
leftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
listener.leftClick();
}
});
rightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
listener.rightClick();
}
});
}
}

上面的代码中使用了一个接口回调机制,这是一个很好用的机制,android源码中经常会碰到这种,有不会的同学可以参考一下,详细解释可以自行百度。

自定义的java文件已经写好了,接下来就是如何引用的问题。我们都知道在layout目录下的xml文件就是一个页面,在里面写布局时都会引用一段代码

xmlns:android="http://schemas.android.com/apk/res/android"

这句话的意思就是引用android系统的控件,那么我们要用自定义的控件又如何引用呢?其实也是类似的,下面给出主页面activity_main.xml的布局代码

xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_width="wrap_content"
android:layout_height="40dp"
android:id="@+id/topbar"
app:titleText="众校"
app:titleTextSize="5dp"
app:titleTextColor="#000"
app:leftText="back"
app:leftTextColor="#f30"
app:leftBackground="#22f"
app:rightText="more"
app:rightTextColor="#f30"
app:rightBackground="#22f">

可以看到在引用自定义的控件中,所用的属性就是刚才自己在attrs.xml文件中定义的那些属性,到此为止,自定义的TopBar就用到页面上了,下面我们在MainActivity.java文件中给左右两边的按钮添加一个点击事件,以证明自己定义的View时真实可用的

public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//标题栏
TopBar topBar = (TopBar) findViewById(R.id.topbar);
topBar.setOnTopbarClickListener(new TopBar.topbarClickListener() {
@Override
public void leftClick() {
Toast.makeText(MainActivity.this,"点击了back",Toast.LENGTH_SHORT).show();
}
@Override
public void rightClick() {
Toast.makeText(MainActivity.this,"点击了more",Toast.LENGTH_SHORT).show();
}
});
}
}

至此,引用已经结束了,到时候直接修改监听器里面的代码就能控制点击事件了。