作者: Jooyer, 时间: 2018.09.08
Github地址,欢迎点赞,fork
一般APP 都使用自己写的 Toolbar , 使用系统情况比较少,本次自定义其实是组合控件而已,虽然有很多大佬有类似控件,有些时候不一定完全满足自己的需要.
本次代码简单,我就直接贴源码,如果还有不清楚的,可以留言或者看github
只需要一个类 + 两个 XML 文件即可,即拷即用
接下来我们依次讲解:
- CustomToolbar
- 两个 XML 文件
- 属性及默认值
首先,看看 CustomToolbar
package cn.molue.jooyer.toolbar
import android.content.Context
import android.support.v4.content.ContextCompat
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
/**
* Desc: 自定义 Toolbar ,格式如下:
*
* Author: Jooyer
* Date: 2018-08-08
* Time: 17:13
*/
class CustomToolbar(context: Context, attr: AttributeSet, defStyleAttr: Int)
: RelativeLayout(context, attr, defStyleAttr) {
/**
* 最左侧图标,默认显示
*/
private lateinit var iv_left_icon_menu: ImageView
/**
* 最左侧文本
*/
private lateinit var tv_left_name_menu: TextView
/**
* 中间文本
*/
private lateinit var tv_center_title_menu: TextView
/**
* 最右侧文本
*/
private lateinit var tv_right_name_menu: TextView
/**
* 最右侧图标,默认显示
*/
private lateinit var iv_right_icon_menu: ImageView
/**
* 底部分割线
*/
private lateinit var view_bottom_divider_menu: View
constructor(context: Context, attr: AttributeSet) : this(context, attr, 0)
init {
initView()
parseAttrs(context, attr)
}
private fun initView() {
val parent = LayoutInflater.from(context).inflate(R.layout.toolbar_custom, this,true)
iv_left_icon_menu = parent.findViewById(R.id.iv_left_icon_menu)
tv_left_name_menu = parent.findViewById(R.id.tv_left_name_menu)
tv_center_title_menu = parent.findViewById(R.id.tv_center_title_menu)
tv_right_name_menu = parent.findViewById(R.id.tv_right_name_menu)
iv_right_icon_menu = parent.findViewById(R.id.iv_right_icon_menu)
view_bottom_divider_menu = parent.findViewById(R.id.view_bottom_divider_menu)
}
private fun parseAttrs(context: Context, attr: AttributeSet) {
val arr = context.obtainStyledAttributes(attr, R.styleable.CustomToolbar)
val leftImageVisible = arr.getBoolean(R.styleable.CustomToolbar_ct_left_image_visible, true)
val leftImageDrawable = arr.getDrawable(R.styleable.CustomToolbar_ct_left_image_drawable)
val leftImageWidth = arr.getDimension(R.styleable.CustomToolbar_ct_left_image_width, dp2px(20F)).toInt()
val leftImageHeight = arr.getDimension(R.styleable.CustomToolbar_ct_left_image_height, dp2px(20F)).toInt()
val leftImagePadding = arr.getDimension(R.styleable.CustomToolbar_ct_left_image_padding, dp2px(3F)).toInt()
val leftImageLeftMargin = arr.getDimension(R.styleable.CustomToolbar_ct_left_image_left_margin, dp2px(0F)).toInt()
val leftTextVisible = arr.getBoolean(R.styleable.CustomToolbar_ct_left_text_visible, false)
val leftTextInfo = arr.getText(R.styleable.CustomToolbar_ct_left_text_info)
val leftTextSize = arr.getInteger(R.styleable.CustomToolbar_ct_left_text_size, 15).toFloat()
val leftTextLeftMargin = arr.getDimension(R.styleable.CustomToolbar_ct_left_text_left_margin, dp2px(20F)).toInt()
val leftTextColor = arr.getColor(R.styleable.CustomToolbar_ct_left_text_color,
ContextCompat.getColor(context, R.color.color_111111))
val centerTextInfo = arr.getText(R.styleable.CustomToolbar_ct_center_text_info)
val centerTextSize = arr.getInteger(R.styleable.CustomToolbar_ct_center_text_size, 15).toFloat()
val centerTextColor = arr.getColor(R.styleable.CustomToolbar_ct_center_text_color,
ContextCompat.getColor(context, R.color.color_111111))
val rightImageVisible = arr.getBoolean(R.styleable.CustomToolbar_ct_right_image_visible, true)
val rightImageDrawable = arr.getDrawable(R.styleable.CustomToolbar_ct_right_image_drawable)
val rightImageWidth = arr.getDimension(R.styleable.CustomToolbar_ct_right_image_width, dp2px(20F)).toInt()
val rightImageHeight = arr.getDimension(R.styleable.CustomToolbar_ct_right_image_height, dp2px(20F)).toInt()
val rightImagePadding = arr.getDimension(R.styleable.CustomToolbar_ct_right_image_padding, dp2px(5F)).toInt()
val rightImageRightMargin = arr.getDimension(R.styleable.CustomToolbar_ct_right_image_right_margin, dp2px(20F)).toInt()
val rightTextVisible = arr.getBoolean(R.styleable.CustomToolbar_ct_right_text_visible, false)
val rightTextInfo = arr.getText(R.styleable.CustomToolbar_ct_right_text_info)
val rightTextSize = arr.getInteger(R.styleable.CustomToolbar_ct_right_text_size, 15).toFloat()
val rightTextRightMargin = arr.getDimension(R.styleable.CustomToolbar_ct_right_text_right_margin, dp2px(20F)).toInt()
val rightTextColor = arr.getColor(R.styleable.CustomToolbar_ct_right_text_color,
ContextCompat.getColor(context, R.color.color_111111))
val bottomDividerVisible = arr.getBoolean(R.styleable.CustomToolbar_ct_bottom_divider_visible, false)
val bottomDividerColor = arr.getColor(R.styleable.CustomToolbar_ct_bottom_divider_color,
ContextCompat.getColor(context, R.color.color_EEEEEE))
val backgroundColor = arr.getColor(R.styleable.CustomToolbar_ct_background_color,
ContextCompat.getColor(context, R.color.color_FE632E))
iv_left_icon_menu.visibility = if (leftImageVisible) View.VISIBLE else View.GONE
if (null != leftImageDrawable) {
iv_left_icon_menu.setImageDrawable(leftImageDrawable)
}
val leftImageLp: RelativeLayout.LayoutParams = iv_left_icon_menu.layoutParams as LayoutParams
leftImageLp.width = leftImageWidth
leftImageLp.height = leftImageHeight
leftImageLp.leftMargin = leftImageLeftMargin
iv_left_icon_menu.setPadding(leftImagePadding, leftImagePadding, leftImagePadding, leftImagePadding)
iv_left_icon_menu.layoutParams = leftImageLp
tv_left_name_menu.visibility = if (leftTextVisible) View.VISIBLE else View.GONE
if (!TextUtils.isEmpty(leftTextInfo)) {
tv_left_name_menu.text = leftTextInfo
tv_left_name_menu.setTextSize(TypedValue.COMPLEX_UNIT_DIP, leftTextSize)
tv_left_name_menu.setTextColor(leftTextColor)
}
val leftTextLp: RelativeLayout.LayoutParams = tv_left_name_menu.layoutParams as LayoutParams
leftTextLp.leftMargin = leftTextLeftMargin
tv_left_name_menu.layoutParams = leftTextLp
if (!TextUtils.isEmpty(centerTextInfo)) {
tv_center_title_menu.text = centerTextInfo
tv_center_title_menu.setTextSize(TypedValue.COMPLEX_UNIT_DIP, centerTextSize)
tv_center_title_menu.setTextColor(centerTextColor)
}
iv_right_icon_menu.visibility = if (rightImageVisible) View.VISIBLE else View.GONE
if (null != rightImageDrawable) {
iv_right_icon_menu.setImageDrawable(rightImageDrawable)
}
val rightImageLp: RelativeLayout.LayoutParams = iv_right_icon_menu.layoutParams as LayoutParams
rightImageLp.width = rightImageWidth
rightImageLp.height = rightImageHeight
rightImageLp.rightMargin = rightImageRightMargin
iv_right_icon_menu.setPadding(rightImagePadding, rightImagePadding, rightImagePadding, rightImagePadding)
iv_right_icon_menu.layoutParams = rightImageLp
tv_right_name_menu.visibility = if (rightTextVisible) View.VISIBLE else View.GONE
if (!TextUtils.isEmpty(rightTextInfo)) {
tv_right_name_menu.text = rightTextInfo
tv_right_name_menu.setTextSize(TypedValue.COMPLEX_UNIT_DIP, rightTextSize)
tv_right_name_menu.setTextColor(rightTextColor)
}
val rightTextLp: RelativeLayout.LayoutParams = tv_right_name_menu.layoutParams as LayoutParams
rightTextLp.rightMargin = rightTextRightMargin
tv_right_name_menu.layoutParams = rightTextLp
view_bottom_divider_menu.visibility = if (bottomDividerVisible) View.VISIBLE else View.GONE
view_bottom_divider_menu.setBackgroundColor(bottomDividerColor)
setBackgroundColor(backgroundColor)
arr.recycle()
}
public fun setLeftImageListener(listener: View.OnClickListener) {
iv_left_icon_menu.setOnClickListener(listener)
}
public fun setRightImageListener(listener: View.OnClickListener) {
iv_right_icon_menu.setOnClickListener(listener)
}
public fun setRightTextListener(listener: View.OnClickListener) {
tv_right_name_menu.setOnClickListener(listener)
}
public fun setCenterText(text: String) {
tv_center_title_menu.text = text
}
private fun dp2px(def: Float): Float {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, def, context.resources.displayMetrics)
}
}
复制代码
来看看自定义的属性(xml文件)
里面就是一大堆自定义的属性,具体含义往下看
复制代码
属性虽然有些多,但是大都都见名知意. 这里还是要看下其布局文件,虽然 so easy
再来看看其布局(xml文件)
xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/height_50"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_left_icon_menu"
android:layout_width="@dimen/width_45"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:src="@mipmap/icon_black_back" />
<TextView
android:id="@+id/tv_left_name_menu"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:textColor="@color/color_111111"
android:textSize="@dimen/text_size_15"
tools:text="宝贝头像" />
<TextView
android:id="@+id/tv_center_title_menu"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_marginEnd="@dimen/padding_20"
android:gravity="center_vertical"
android:textColor="@color/color_111111"
android:textSize="@dimen/text_size_18"
android:textStyle="bold"
tools:text="请填写" />
<TextView
android:id="@+id/tv_right_name_menu"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/padding_20"
android:gravity="center_vertical"
android:textColor="@color/color_111111"
android:textSize="@dimen/text_size_15"
tools:text="请填写" />
<ImageView
android:id="@+id/iv_right_icon_menu"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/padding_20" />
<View
android:id="@+id/view_bottom_divider_menu"
android:layout_width="match_parent"
android:layout_height="@dimen/divider_2"
android:layout_alignParentBottom="true"
android:background="@color/color_EEEEEE" />
RelativeLayout>
复制代码
最后来看看在 Activity 布局中的用法
xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="cn.molue.jooyer.toolbar.MainActivity"
>
<cn.molue.jooyer.toolbar.CustomToolbar
android:id="@+id/ct_tool_bar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/padding_6"
android:layout_marginBottom="@dimen/padding_6"
app:ct_center_text_info="左边图片,右边文本"
app:ct_right_text_info="清空"
app:ct_right_text_right_margin="@dimen/padding_5"
app:ct_right_text_visible="true"
/>
<cn.molue.jooyer.toolbar.CustomToolbar
android:id="@+id/ct_tool_bar2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/padding_6"
android:layout_marginBottom="@dimen/padding_6"
app:ct_center_text_info="左边图片,右边图片"
app:ct_right_image_drawable="@mipmap/icon_black_back"
app:ct_right_image_right_margin="@dimen/padding_5"
/>
<cn.molue.jooyer.toolbar.CustomToolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/padding_6"
android:layout_marginBottom="@dimen/padding_6"
app:ct_center_text_info="左边文本,右边文本"
app:ct_left_image_visible="false"
app:ct_left_text_info="返回"
app:ct_left_text_left_margin="@dimen/padding_5"
app:ct_left_text_visible="true"
app:ct_right_image_right_margin="@dimen/padding_5"
app:ct_right_text_info="清空"
app:ct_right_text_right_margin="@dimen/padding_5"
app:ct_right_text_visible="true"
/>
<cn.molue.jooyer.toolbar.CustomToolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/padding_6"
android:layout_marginBottom="@dimen/padding_6"
app:ct_center_text_info="左边文本,右边图片"
app:ct_left_image_visible="false"
app:ct_left_text_info="返回"
app:ct_left_text_left_margin="@dimen/padding_5"
app:ct_left_text_visible="true"
app:ct_right_image_drawable="@mipmap/icon_black_back"
app:ct_right_image_right_margin="@dimen/padding_5"
/>
<cn.molue.jooyer.toolbar.CustomToolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/padding_6"
android:layout_marginBottom="@dimen/padding_6"
app:ct_background_color="@color/colorAccent"
app:ct_center_text_info="改变背景色"
app:ct_left_image_visible="false"
app:ct_left_text_info="返回"
app:ct_left_text_left_margin="@dimen/padding_5"
app:ct_left_text_visible="true"
app:ct_right_image_drawable="@mipmap/icon_black_back"
app:ct_right_image_right_margin="@dimen/padding_5"
/>
LinearLayout>
复制代码
这个就不解释了,最后看看 Activity中的操作
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ct_tool_bar1.setLeftImageListener(View.OnClickListener {
Toast.makeText(this@MainActivity,"点击了左侧图片",Toast.LENGTH_SHORT).show()
})
ct_tool_bar1.setRightTextListener(View.OnClickListener {
Toast.makeText(this@MainActivity,"点击了右侧文字",Toast.LENGTH_SHORT).show()
})
ct_tool_bar2.setRightImageListener(View.OnClickListener {
Toast.makeText(this@MainActivity,"点击了右侧图片",Toast.LENGTH_SHORT).show()
})
}
}
复制代码
最后讲解下属性和默认值
"ct_left_text_visible" format="boolean"/> // 默认是false
"ct_left_text_info" format="reference|string"/>
"ct_left_text_size" format="dimension|integer"/> // 默认是15dp
"ct_left_text_color" format="color|reference"/> // 默认颜色是 #111111
"ct_left_text_left_margin" format="dimension|integer"/> // 默认是20dp
"ct_left_image_visible" format="boolean"/> // 默认是 true
"ct_left_image_drawable" format="reference"/> // 给了个黑色箭头
"ct_left_image_width" format="dimension|integer"/> // 默认20dp
"ct_left_image_height" format="dimension|integer"/> // 默认20dp
"ct_left_image_padding" format="dimension|integer"/> // 默认3dp
"ct_left_image_left_margin" format="dimension|integer"/> // 默认为 0
"ct_center_text_info" format="reference|string"/>
"ct_center_text_size" format="dimension|integer"/> // 默认15dp
"ct_center_text_color" format="color|reference"/> // 默认#111111
"ct_right_text_visible" format="boolean"/> // 默认false
"ct_right_text_info" format="reference|string"/>
"ct_right_text_size" format="dimension|integer"/> // 默认15dp
"ct_right_text_color" format="color|reference"/> // 默认#111111
"ct_right_text_right_margin" format="dimension|integer"/> // 默认20dp
"ct_right_image_visible" format="boolean"/> // 默认是true
"ct_right_image_drawable" format="reference"/>
"ct_right_image_width" format="dimension|integer"/> // 默认20dp
"ct_right_image_height" format="dimension|integer"/> // 默认20dp
"ct_right_image_padding" format="dimension|integer"/> // 默认5dp
"ct_right_image_right_margin" format="dimension|integer"/> // 默认20dp
"ct_bottom_divider_visible" format="boolean"/> // 默认false
"ct_bottom_divider_color" format="color|reference"/> // 默认#EEEEEE
"ct_background_color" format="color|reference"/> // 默认#FE632E
复制代码
注意,如果不是使用默认属性,比如左侧不是图片,而是文字,记得隐藏图片,同时显示文字
当然,这些属性也可以在 CustomToolbar 中定义方法,在代码里动态设置,这个就没有写,主要是懒,大家需要什么加入什么就好了!