前言:在Android开发中很多时候我们都只有一张图片缺想让做成按钮有点击效果,今天我们就自己定义一个Button并且给他一个点击效果。笔者暂时发现两种图片按钮,
- A.只有一张默认图片的情况下出滤镜效果。
- B.传递两张图片的时候交替出现效果。
我们需要抽象一个父类出来,找出他们两的共同点------按钮在点击的时候切换效果
代码实现新建BtnSwitch类
open abstract class BtnSwitch: ImageView { /** * 选中前的按钮 */ protected var normalImage = 0; /** * 当前选中的状态 */ protected var status:Boolean = false constructor(context: Context):this(context,null) constructor(contex:Context,attrs:AttributeSet?):super(contex,attrs) override fun onTouchEvent(event: MotionEvent?): Boolean { when(event?.action) { /** * 当鼠标点击后 */ MotionEvent.ACTION_DOWN-> { switch(true); } /** * 当鼠标移除或者松开的时候 */ MotionEvent.ACTION_UP,MotionEvent.ACTION_CANCEL-> { if(event?.action==MotionEvent.ACTION_UP) { performClick(); } switch(false); } } return true; } /** * 切换前的状态 */ abstract protected fun switch(boolean:Boolean)
2.定义接口,向访问者表明其功能
interface ISwitchBtn { /** * 切换状态 */ fun setSelected(boolean:Boolean) /** * 返回当前的状态 */ fun getSelectedStatus():Boolean /** * 更具当前的状态自动切换 */ fun setToggle() }
3.开始实现具体类最简单的一张图片的情况添加滤镜ImageButtonFilter
class ImageButtonFilter: BtnSwitch, ISwitchBtn { constructor(context:Context):super(context) constructor(contex:Context,attrs: AttributeSet?):super(contex,attrs) { var typeArray:TypedArray = contex.obtainStyledAttributes(attrs, R.styleable.BtnSwitch) normalImage = typeArray.getResourceId(R.styleable.BtnSwitch_normalStatus,R.mipmap.ic_launcher); setImageResource(normalImage); } /** * 返回当前的状态 */ override fun getSelectedStatus():Boolean { return status; } /** * 切换状态 */ override fun setSelected(boolean:Boolean) { if(status==boolean) { return; } switch(status); } /** * 自动切换 */ override protected fun switch(boolean: Boolean) { status = boolean; if(status) { setFilter(); } else { clearFilter(); } } /* *设置自动切换 */ override fun setToggle() { status=!status; switch(status); } /** * 设置图片的滤镜效果 */ private fun setFilter() { drawable.let { drawable.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY) } } /** * 清除选中效果 */ private fun clearFilter() { drawable.let { drawable.clearColorFilter()} }
4.实现两张图片切换的效果。这个时候和笔者一起考虑一个问题很多时候我们在做这种切换的时候要考虑自动和非自动,非自动的一般是有异步的情况,向网络请求完毕服务器返回OK的情况下我们要展示一个OK的状态,还有一种就是不需要异步点击了立面切换。先定义一个接口,可以传递和随时改变图片
interface ISwitchBtnImage : ISwitchBtn { /* * 设置选中前的图片 */ fun NormalImagedIndex(index:Int) /** * 设置选中后的图片 */ fun SelectImageIndex(index: Int) }
5.开始实现ImageBtnSwitch类
class ImageBtnSwitch: BtnSwitch, ISwitchBtnImage { /** * 切换后的图片 */ private var selectImage = 0; /** * 是否自动切换 */ private var autoSwitch:Boolean = false; constructor(context:Context):super(context) { retrieveAttributes(context,null) } constructor(context: Context,attributeSet: AttributeSet):super(context,attributeSet) { retrieveAttributes(context,attributeSet) } /** * 设置显示的选中图片 */ override fun SelectImageIndex(index:Int) { if(index !=null && index!=0 ) { normalImage = index; } } /** * 设置显示的默认图片 */ override fun NormalImagedIndex(index: Int) { if(index !=null && index!=0 ) { selectImage = index; } } /** * 内部自动切换方法 */ override fun switch(boolean: Boolean) { //如果是自动切换状态 if(autoSwitch) { status = boolean; if(status) { showSelectImgae(); } else { showNormalImgae() } } else { //设置点击效果 if(boolean) { setFilter(); } else { clearFilter(); } } } /** * 设置图片的滤镜效果 */ private fun setFilter() { drawable.let { drawable.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY) } } /** * 切换状态 */ override fun setSelected(boolean:Boolean) { if(status==boolean) { return; } status = boolean; if(status) { showNormalImgae() } else { showSelectImgae(); } } /** * 清除选中效果 */ private fun clearFilter() { drawable.let { drawable.clearColorFilter()} } /** * 返回当前选中状态 */ override fun getSelectedStatus(): Boolean { return status; } /** *设置当前的选中状态 */ override fun setToggle() { status=!status; if(status) { showSelectImgae(); } else { showNormalImgae(); } } /** * 显示默认图片 */ private fun showNormalImgae() { setImageResource(normalImage); } /** * 显示选中后的图片 */ private fun showSelectImgae() { setImageResource(selectImage); } /** * 获取XML 属性 */ private fun retrieveAttributes(context: Context,attributeSet: AttributeSet?) { if(attributeSet==null) { normalImage = R.mipmap.ic_launcher; selectImage = R.mipmap.ic_launcher; } else { val typedArray:TypedArray = context.obtainStyledAttributes(attributeSet, R.styleable.BtnSwitch); normalImage = typedArray.getResourceId(R.styleable.BtnSwitch_normalStatus,R.mipmap.ic_launcher); selectImage = typedArray.getResourceId(R.styleable.BtnSwitch_selectStatus,0); autoSwitch = typedArray.getBoolean(R.styleable.BtnSwitch_autoSwitch,true); typedArray.recycle(); } setImageResource(normalImage); }
最后一步别忘了定义attrs
<!--reference某资源的ID--> <!--自定义按钮切换属性BtnSwitch--> <declare-styleable name="BtnSwitch"> <attr name="normalStatus" format="reference"></attr> <attr name="selectStatus" format="reference"></attr> <attr name="autoSwitch" format="boolean">true</attr> </declare-styleable>
好了自定义Button就完成了,如果对你的项目有帮助或者有什么意见,请留言或者点赞,原创不容易希望支持下,特别是你们在耍国庆我还在 准备找工作的时候。