引言
前一篇文章Android进阶——自定义View之继承系统控件实现自带删除按钮和设置动画效果的加强型EditText通过去继承EditText实现一个自带删除和抖动动画效果的EditText,这篇同样是继承系统控件,不过是去扩展ViewGroup,相信做过Web或者WinForm的同学都对模板不陌生,虽然Android中并没有这个概念,不过思想我们是可以借鉴的,这也是通过组合系统控件实现自定义View的一大优势,其实就是像一个模板,我们可以应用在我们的APP中,统一去管理他的样式和风格,维护成本也很低。
一、自定义ToolBar概述
虽然Android已经为我们提供了ActionBar和ToolBar,但是有些时候需要客制化的时候还是不能满足具体的业务需求,于是乎我就采用了重写ViewGroup组合系统控件去实现,类似ActionBar和ToolBar的一个小控件。
二、自定义ToolBar的设计思想
1、选择继承RelativeLayout
选择继承RelativeLayout,其实RelativeLayout的布局机制也是有点类似FrameLayout,选择继承RelativeLayout可以在我们的使用的时候更方便简单,不需要再重新布局。
2、实现ToolBar的UI效果
一般来说继承系统控件,大多都是在它的构造方法里做文章,至于添加其他View,也有很多种方式可以通过LayoutInflater.from(context).inflate(layoutid, this, true)映射布局xml或者通过Java代码动态构造再addView添加进去。
private void init(AttributeSet attrs) {
View contentView = LayoutInflater.from(this.context).inflate(R.layout.navtop_layout, this, true);
imageLeft = (ImageView) contentView.findViewById(R.id.id_nav_left);
imageRight = (ImageView) contentView.findViewById(R.id.id_nav_right);
topBg = (RelativeLayout) contentView.findViewById(R.id.rl_top_bg);
textView = (TextView) contentView.findViewById(R.id.id_mid_nav);
initAttr(attrs);
topBg.setBackgroundColor(bcgroundResId);
imageLeft.setOnClickListener(this);
imageRight.setOnClickListener(this);
}
3、把控件的属性成员开放出来用于客制化
/**
* 设置默认的左边按钮的背景图
* @param resouseId
*/
public void setLeftImage(int resouseId) {
imageLeft.setImageResource(resouseId);
}
public void setRightImage(int resouseId) {
imageRight.setImageResource(resouseId);
}
/**
* 设置是否显示左右按钮
* @param left
* @param right
*/
public void setBarImageDisplay(boolean left, boolean right) {
if(left){
imageLeft.setVisibility(VISIBLE);
}else {
imageLeft.setVisibility(GONE);
}
if(right) {
imageRight.setVisibility(VISIBLE);
}else {
imageRight.setVisibility(GONE);
}
}
4、添加人机交互接口
参考ToolBar这个小控件主要操作其实就只需要有:动态显示或隐藏指定View,动态改变显示Title和点击动作。
public void setNavOnClickListener(NavOnClickListener onClickListener) {
navOnClickListener = onClickListener;
}
public interface NavOnClickListener {
void leftOnClickListener();
void rightOnClickListener();
}
三、实现自定义ToolBar
package com.crazymo.views.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.crazymo.views.R;
/**
* auther: Crazy.Mo
* Date: 2016/12/26
* Time:18:08
* Des:
*/
public class NavTopBar extends RelativeLayout implements View.OnClickListener {
private Context context;
private TextView textView;
private ImageView imageRight;
private ImageView imageLeft;
private NavOnClickListener navOnClickListener;
private RelativeLayout topBg;
private int bcgroundResId;
private Drawable leftImgId,rightImgId;
public NavTopBar(Context context) {
super(context);
this.context = context;
}
public NavTopBar(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init(attrs);
}
public NavTopBar(@NonNull Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init(attrs);
}
private void init(AttributeSet attrs) {
View contentView = LayoutInflater.from(this.context).inflate(R.layout.navtop_layout, this, true);
imageLeft = (ImageView) contentView.findViewById(R.id.id_nav_left);
imageRight = (ImageView) contentView.findViewById(R.id.id_nav_right);
topBg = (RelativeLayout) contentView.findViewById(R.id.rl_top_bg);
textView = (TextView) contentView.findViewById(R.id.id_mid_nav);
initAttr(attrs);
//topBg.setBackgroundResource(bcgroundResId);
topBg.setBackgroundColor(bcgroundResId);
imageLeft.setOnClickListener(this);
imageRight.setOnClickListener(this);
}
private void initAttr(AttributeSet attrs){
TypedArray types = context.obtainStyledAttributes(attrs,
R.styleable.nav_top_bar);
try {
bcgroundResId = types.getColor( R.styleable.nav_top_bar_bacgroud_color,getResources().getColor(R.color.blue ));
} finally {
types.recycle(); // TypeArray用完需要recycle
}
}
@Override
public void onClick(View v) {
if (navOnClickListener != null) {
switch (v.getId()) {
case R.id.id_nav_left:
navOnClickListener.leftOnClickListener();
break;
case R.id.id_nav_right:
navOnClickListener.rightOnClickListener();
break;
}
}
}
public void setNavBackground(int resId){
topBg.setBackgroundResource(resId);
}
public void setTitle(String title) {
textView.setText(title);
}
public void setNavOnClickListener(NavOnClickListener onClickListener) {
navOnClickListener = onClickListener;
}
public interface NavOnClickListener {
void leftOnClickListener();
void rightOnClickListener();
}
/**
* 设置默认的左边按钮的背景图
* @param resouseId
*/
public void setLeftImage(int resouseId) {
imageLeft.setImageResource(resouseId);
}
public void setRightImage(int resouseId) {
imageRight.setImageResource(resouseId);
}
/**
* 设置是否显示左右按钮
* @param left
* @param right
*/
public void setBarImageDisplay(boolean left, boolean right) {
if(left){
imageLeft.setVisibility(VISIBLE);
}else {
imageLeft.setVisibility(GONE);
}
if(right) {
imageRight.setVisibility(VISIBLE);
}else {
imageRight.setVisibility(GONE);
}
}
}
四、使用自定义ToolBar
属性attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="nav_top_bar">
<attr name="bacgroud_color" format="reference"/>
</declare-styleable>
</resources>
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:crazymo="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.crazymo.views.MainActivity">
<com.crazymo.views.widget.NavTopBar
android:id="@+id/nav_top_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
crazymo:bacgroud_color="@color/colorPrimary"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/ic_crazymo_logo"/>
</RelativeLayout>
MainActivity
package com.crazymo.views;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.Toast;
import com.crazymo.views.widget.NavTopBar;
/**
* auther: Crazy.Mo
* Date: 2016/12/26
* Time:18:20
* Des:
*/
public class MainActivity extends AppCompatActivity implements NavTopBar.NavOnClickListener{
private NavTopBar navTopBar;
private ImageView leftBtn,rightBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews(){
navTopBar= (NavTopBar) findViewById(R.id.nav_top_main);
navTopBar.setBarImageDisplay(true,true);//设置显示左右按钮
navTopBar.setNavOnClickListener(this);//注册监听
setTitle("ByCrazyMo_");
}
private void setTitle(String title){
navTopBar.setTitle(title);
}
@Override
public void leftOnClickListener() {
Toast.makeText(this,"Clicked on the Left",Toast.LENGTH_LONG).show();
}
@Override
public void rightOnClickListener() {
Toast.makeText(this,"Clicked on the Right",Toast.LENGTH_LONG).show();
}
}
运行结果