Android自定义控件实现icon+文字的多种效果
程序员文章站
2023-12-21 23:02:16
今天给大家带来一个很简单但是很常用的控件buttonextendm,在开发中我们经常会用到图片加文字的组合控件,像这样:
以上图片都是从微信上截取的。(暂时没有找到i...
今天给大家带来一个很简单但是很常用的控件buttonextendm,在开发中我们经常会用到图片加文字的组合控件,像这样:
以上图片都是从微信上截取的。(暂时没有找到icon在下,文字在上的例子)
下面我们通过一个控件来实现上下左右全部的样式,只需改动一个属性值即可改变icon的位置,是不是很方便,先看下demo效果图:
没错上图的三种不同的样式都是通过同一个控件实现的,下面我们看下代码
第一步 自定义属性
在res/values/目录下新建attrs.xml文件,
添加如下属性
<attr name="backcolor" format="color" /> <attr name="backcolorpress" format="color" /> <attr name="textcolor" format="color" /> <attr name="textcolorpress" format="color" /> <declare-styleable name="buttonextendm"> <attr name="backcolor"/> <attr name="backcolorpress"/> <attr name="textcolor"/> <attr name="textcolorpress"/> <attr name="icondrawable" format="reference" /> <attr name="icondrawablepress" format="reference" /> <attr name="text" format="string" /> <attr name="textsize" format="float" /> <attr name="spacing" format="dimension" /> <attr name="style"> <enum name="iconleft" value="0" /> <enum name="iconright" value="1" /> <enum name="iconup" value="2" /> <enum name="iconbottom" value="3" /> </attr> </declare-styleable>
第二步 新建布局文件view_button_extend_m.xml
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <imageview android:id="@+id/iv_icon" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <textview android:id="@+id/tv_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" android:text="@string/button_extend_m_default_text"/> </relativelayout>
第三步 新建buttonextendm.java继承relativelayout
package com.landptf.view; import android.content.context; import android.content.res.colorstatelist; import android.content.res.typedarray; import android.graphics.drawable.drawable; import android.util.attributeset; import android.view.gravity; import android.view.layoutinflater; import android.view.motionevent; import android.view.view; import android.widget.imageview; import android.widget.relativelayout; import android.widget.textview; import com.landptf.r; import com.landptf.util.convertm; /** * created by landptf on 2016/10/31. * 扩展button,支持文字和icon分上下左右四种方式显示 * 默认为左右结构,图片在左,文字在右 */ public class buttonextendm extends relativelayout { /** * 左右结构,图片在左,文字在右 */ public static final int style_icon_left = 0; /** * 左右结构,图片在右,文字在左 */ public static final int style_icon_right = 1; /** * 上下结构,图片在上,文字在下 */ public static final int style_icon_up = 2; /** * 上下结构,图片在下,文字在上 */ public static final int style_icon_down = 3; /** * 定义控件 */ private imageview ivicon; private textview tvcontent; /** * 上下文 */ private context mcontext; /** * view的背景色 */ private int backcolor = 0; /** * view被按下时的背景色 */ private int backcolorpress = 0; /** * icon的背景图片 */ private drawable icondrawable = null; /** * icon被按下时显示的背景图片 */ private drawable icondrawablepress = null; /** * view文字的颜色 */ private colorstatelist textcolor = null; /** * view被按下时文字的颜色 */ private colorstatelist textcolorpress = null; /** * 两个控件之间的间距,默认为8dp */ private int spacing = 8; /** * 两个控件的位置结构 */ private int mstyle = style_icon_left; /** * 标示ontouch方法的返回值,用来解决onclick和ontouch冲突问题 */ private boolean iscost = true; private onclicklistener onclicklistener = null; public interface onclicklistener { void onclick(view v); } /** * 设置view的click事件 * * @param l */ public void setonclicklistener(onclicklistener l) { this.onclicklistener = l; iscost = false; } public buttonextendm(context context) { super(context); mcontext = context; } public buttonextendm(context context, attributeset attrs) { this(context, attrs, 0); } public buttonextendm(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); mcontext = context; init(context, attrs, defstyle); } private void init(context context, attributeset attrs, int defstyle) { //加载布局 layoutinflater.from(context).inflate(r.layout.view_button_extend_m, this, true); //初始化控件 ivicon = (imageview) findviewbyid(r.id.iv_icon); tvcontent = (textview) findviewbyid(r.id.tv_content); setgravity(gravity.center); typedarray a = getcontext().obtainstyledattributes( attrs, r.styleable.buttonextendm, defstyle, 0); if (a != null) { //设置背景色 colorstatelist colorlist = a.getcolorstatelist(r.styleable.buttonextendm_backcolor); if (colorlist != null) { backcolor = colorlist.getcolorforstate(getdrawablestate(), 0); if (backcolor != 0) { setbackgroundcolor(backcolor); } } //记录view被按下时的背景色 colorstatelist colorlistpress = a.getcolorstatelist(r.styleable.buttonextendm_backcolorpress); if (colorlistpress != null) { backcolorpress = colorlistpress.getcolorforstate(getdrawablestate(), 0); } //设置icon icondrawable = a.getdrawable(r.styleable.buttonextendm_icondrawable); if (icondrawable != null) { ivicon.setimagedrawable(icondrawable); } //记录view被按下时的icon的图片 icondrawablepress = a.getdrawable(r.styleable.buttonextendm_icondrawablepress); //设置文字的颜色 textcolor = a.getcolorstatelist(r.styleable.buttonextendm_textcolor); if (textcolor != null) { tvcontent.settextcolor(textcolor); } //记录view被按下时文字的颜色 textcolorpress = a.getcolorstatelist(r.styleable.buttonextendm_textcolorpress); //设置显示的文本内容 string text = a.getstring(r.styleable.buttonextendm_text); if (text != null) { //默认为隐藏的,设置文字后显示出来 tvcontent.setvisibility(visible); tvcontent.settext(text); } //设置文本字体大小 float textsize = a.getfloat(r.styleable.buttonextendm_textsize, 0); if (textsize != 0) { tvcontent.settextsize(textsize); } //设置两个控件之间的间距 spacing = a.getdimensionpixelsize(r.styleable.buttonextendm_spacing, convertm.dp2px(context, 8)); //设置两个控件的位置结构 mstyle = a.getint(r.styleable.buttonextendm_style, 0); seticonstyle(mstyle); a.recycle(); } setontouchlistener(new ontouchlistener() { @override public boolean ontouch(view arg0, motionevent event) { //根据touch事件设置按下抬起的样式 return settouchstyle(event.getaction()); } }); setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { if (onclicklistener != null) { onclicklistener.onclick(v); } } }); } /** * 根据按下或者抬起来改变背景和文字样式 * * @param state * @return iscost */ private boolean settouchstyle(int state) { if (state == motionevent.action_down) { if (backcolorpress != 0) { setbackgroundcolor(backcolorpress); } if (icondrawablepress != null) { ivicon.setimagedrawable(icondrawablepress); } if (textcolorpress != null) { tvcontent.settextcolor(textcolorpress); } } if (state == motionevent.action_up) { if (backcolor != 0) { setbackgroundcolor(backcolor); } if (icondrawable != null) { ivicon.setimagedrawable(icondrawable); } if (textcolor != null) { tvcontent.settextcolor(textcolor); } } return iscost; } /** * 设置图标位置 * 通过重置layoutparams来设置两个控件的摆放位置 * @param style */ public void seticonstyle(int style) { mstyle = style; relativelayout.layoutparams lp; switch (style) { case style_icon_left: lp = new relativelayout.layoutparams(layoutparams.wrap_content, layoutparams.wrap_content); lp.addrule(relativelayout.center_vertical); ivicon.setlayoutparams(lp); lp = new relativelayout.layoutparams(layoutparams.wrap_content, layoutparams.wrap_content); lp.addrule(relativelayout.center_vertical); lp.addrule(relativelayout.right_of, ivicon.getid()); lp.leftmargin = spacing; tvcontent.setlayoutparams(lp); break; case style_icon_right: lp = new relativelayout.layoutparams(layoutparams.wrap_content, layoutparams.wrap_content); lp.addrule(relativelayout.center_vertical); tvcontent.setlayoutparams(lp); lp = new relativelayout.layoutparams(layoutparams.wrap_content, layoutparams.wrap_content); lp.addrule(relativelayout.center_vertical); lp.addrule(relativelayout.right_of, tvcontent.getid()); lp.leftmargin = spacing; ivicon.setlayoutparams(lp); break; case style_icon_up: lp = new relativelayout.layoutparams(layoutparams.wrap_content, layoutparams.wrap_content); lp.addrule(relativelayout.center_horizontal); ivicon.setlayoutparams(lp); lp = new relativelayout.layoutparams(layoutparams.wrap_content, layoutparams.wrap_content); lp.addrule(relativelayout.center_horizontal); lp.addrule(relativelayout.below, ivicon.getid()); lp.leftmargin = spacing; tvcontent.setlayoutparams(lp); break; case style_icon_down: lp = new relativelayout.layoutparams(layoutparams.wrap_content, layoutparams.wrap_content); lp.addrule(relativelayout.center_horizontal); tvcontent.setlayoutparams(lp); lp = new relativelayout.layoutparams(layoutparams.wrap_content, layoutparams.wrap_content); lp.addrule(relativelayout.center_horizontal); lp.addrule(relativelayout.below, tvcontent.getid()); lp.leftmargin = spacing; ivicon.setlayoutparams(lp); break; default: break; } } /** * 设置view的背景色 * * @param backcolor */ public void setbackcolor(int backcolor) { this.backcolor = backcolor; setbackgroundcolor(backcolor); } /** * 设置view被按下时的背景色 * * @param backcolorpress */ public void setbackcolorpress(int backcolorpress) { this.backcolorpress = backcolorpress; } /** * 设置icon的图片 * * @param icondrawable */ public void seticondrawable(drawable icondrawable) { this.icondrawable = icondrawable; ivicon.setimagedrawable(icondrawable); } /** * 设置view被按下时的icon的图片 * * @param icondrawablepress */ public void seticondrawablepress(drawable icondrawablepress) { this.icondrawablepress = icondrawablepress; } /** * 设置文字的颜色 * * @param textcolor */ public void settextcolor(int textcolor) { if (textcolor == 0) return; this.textcolor = colorstatelist.valueof(textcolor); tvcontent.settextcolor(this.textcolor); } /** * 设置view被按下时文字的颜色 * * @param textcolorpress */ public void settextcolorpress(int textcolorpress) { if (textcolorpress == 0) return; this.textcolorpress = colorstatelist.valueof(textcolorpress); } /** * 设置显示的文本内容 * * @param text */ public void settext(charsequence text) { //默认为隐藏的,设置文字后显示出来 tvcontent.setvisibility(visible); tvcontent.settext(text); } /** * 获取显示的文本 * * @return */ public string gettext() { return tvcontent.gettext().tostring(); } /** * 设置文本字体大小 * * @param size */ public void settextsize(float size) { tvcontent.settextsize(size); } /** * 设置两个控件之间的间距 * * @param spacing */ public void setspacing(int spacing) { this.spacing = convertm.dp2px(mcontext, spacing); //设置完成后刷新一下两个控件的结构,避免先执行了seticonstyle后,setspacing不生效 seticonstyle(mstyle); } }
代码注释基本可以看懂具体的实现,接下来主要看下如何使用
在layout里直接引用buttonextendm即可,注意要添加
xmlns:landptf=""
<com.landptf.view.buttonextendm android:id="@+id/bem_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centervertical="true" android:layout_marginleft="8dp" landptf:icondrawable="@drawable/title_back" landptf:icondrawablepress="@drawable/title_back_selected" landptf:textcolor="@android:color/white" landptf:spacing="4dp" landptf:text="返回"/>
这个是实现的菜单栏的返回按钮,左右结构,icon在左为默认样式,注意一下*press的属性,主要是用来设置控件被按下后的效果的。
再来看一个上下结构的
<com.landptf.view.buttonextendm android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" landptf:icondrawable="@drawable/icon_home_page" landptf:text="首页" landptf:style="iconup" />
只需要设置landptf:style即可,同时也可以通过java代码实现
seticonstyle(buttonextendm.style_icon_up)
全部代码已托管到开源中国的码云上,欢迎下载,地址:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。