首先,要写一个toolbar,十分简单,在xml文件定义几个控件组合在一起,用include就能简单复用,但是今天这里来讲下自定义组合控件,目的很明显,就是降低布局文件和activity的耦合。
话不多说,直接帖代码:
"1.0" encoding="utf-8"?>
"MyToolBar">
"titlename" format="string"/>
"titlesize" format="dimension"/>
"titlecolor" format="color"/>
"leftbg" format="reference"/>
"righttext" format="string"/>
"rightsize" format="dimension"/>
"rightcolor" format="color"/>
这里我在values文件夹下新建一个叫做attrs的xml文件
标签告诉系统这是我们自己定义的属性,
标签是我们定义属性的名字,format属性 定义值的类型
package com.customtoolbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
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 z on 2017/6/20.
*/
public class Toolbar extends RelativeLayout{
//标题栏所包含的三个控件
private Button leftbutton ;
private TextView title,righttext;
//标题中心文字的属性
private String titlename;
private float titlesize;
private int titlecolor;
//左边按钮的属性
private Drawable leftbg;
//右边文字的属性
private String rightname;
private float rightsize;
private int rightcolor;
private LayoutParams leftParams;
private LayoutParams titleParams;
private LayoutParams rightParams;
public Toolbar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.MyToolBar);
//获取xml文件中的属性值
titlename=typedArray.getString(R.styleable.MyToolBar_titlename);
titlesize=typedArray.getDimension(R.styleable.MyToolBar_titlesize,0);
titlecolor=typedArray.getColor(R.styleable.MyToolBar_titlecolor,0);
leftbg=typedArray.getDrawable(R.styleable.MyToolBar_leftbg);
rightname=typedArray.getString(R.styleable.MyToolBar_righttext);
rightsize=typedArray.getDimension(R.styleable.MyToolBar_rightsize,0);
rightcolor=typedArray.getInt(R.styleable.MyToolBar_rightcolor,0);
//回收,避免浪费资源以及未知的缓存错误
typedArray.recycle();
//实例化控件
leftbutton=new Button(context);
title=new TextView(context);
righttext=new TextView(context);
//属性赋给定义的控件
title.setText(titlename);
title.setTextSize(titlesize);
title.setTextColor(titlecolor);
title.setGravity(Gravity.CENTER);
leftbutton.setBackground(leftbg);
righttext.setText(rightname);
righttext.setTextSize(rightsize);
righttext.setTextColor(rightcolor);
setBackgroundColor(Color.parseColor("#63B8FF"));
//定义子控件在父容器中的位置
leftParams=new LayoutParams(100, 100);
leftParams.setMarginStart(20);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
leftParams.addRule(RelativeLayout.CENTER_VERTICAL);
addView(leftbutton,leftParams);
titleParams=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT);
addView(title,titleParams);
rightParams=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rightParams.setMarginEnd(20);
rightParams.addRule(RelativeLayout.CENTER_VERTICAL);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
addView(righttext,rightParams);
//给左边的按钮设置点击事件
leftbutton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//执行回调方法
leftButtonListener.LeftBtnOnclick();
}
});
}
private LeftButtonListener leftButtonListener;
public void setOnToolbarclickListener (LeftButtonListener listener) {
leftButtonListener=listener;
}
public interface LeftButtonListener
{
void LeftBtnOnclick();
}
}
这里是自定义的核心代码,用typedarray类存储我们xml文件中定义的属性,然后通过各种get方法,取出你xml文件中定义的值,再将这些属性值附给我们自定义控件的各个子控件。
那么点击事件该怎么处理呢?我们不能在自定义控件中写死他的执行方法,这样十分不合理,这时候我们就想到了接口回调。
定义一个LeftButtonListener,里面有待实现方法LeftBtnOnclick() 在activity中实现这个方法。
当我们点击这个按钮的时候,执行LeftBtnOnclick() ,具体执行代码,自己在activity中定义。
package com.customtoolbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Toolbar myToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myToolbar= (Toolbar) findViewById(R.id.mytoolbar);
myToolbar.setOnToolbarclickListener(new Toolbar.LeftButtonListener() {
@Override
public void LeftBtnOnclick() {
Toast.makeText(MainActivity.this,"你点击了左边按钮",Toast.LENGTH_SHORT).show();
}
});
}
}
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.customtoolbar.MainActivity">
"match_parent"
android:layout_height="50dp"
android:id="@+id/mytoolbar"
custom:titlename="标题"
custom:titlesize="10sp"
custom:titlecolor="#ffffff"
custom:leftbg="@mipmap/ic_launcher"
custom:righttext="右键"
custom:rightsize="6sp"
custom:rightcolor="#000"
>
布局文件中给我们之前自定义属性赋值,这里有一点很重要,就是命名空间,例如要使用android:要用到
xmlns:android="http://schemas.android.com/apk/res/android"
同理
xmlns:custom="http://schemas.android.com/apk/res-auto"
我们讲前面的名字改成自定义名字,到时候就用这个名字来调用,后面改成res-auto让他自动搜寻
最后我们来看下演示效果:
总结:
这种方法看似会复杂不少,但是其实条理很清晰,并且能有效的降低布局和activity间的耦合,让代码更易维护,谢谢。