android 自定义好看的按钮 (Kotlin)

参考文章:(讲解更详细) https://blog.csdn.net/tongzhang1314/article/details/79084538

首先贴上效果图: (加载动画转动快是在模拟器的原因,真机并没有那么快)
在这里插入图片描述

思路:
1. 创建mBtnView类继承Button类,实现第二个构造方法(因为需要在xml中使用)
2. 通过GradientDrawable来定义按钮的背景,如圆角度颜色等值,(GradientDrawable是shape在代码中的使用,不了解可以百度下)
3. 通过ValueAnimator来实现按钮的缩放(由圆角矩形变为圆形的效果)
4. 通过 canvas.drawArc() 方法来画一个圆弧,并通过ValueAnimator来改变画圆弧时候的开始值,再通过invalidate()重绘界面来实现圆弧的转动
PS: 1,2在初始化时定义好就行,3,4放在点击事件中执行

自定义button的源码:

参考:view坐标系:
在这里插入图片描述

package com.example.administrator.mktproject.weight

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.support.annotation.RequiresApi
import android.util.AttributeSet
import android.widget.Button


@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
/**
 * Created by Administrator on 2019/7/30 0030.
 *   GradientDrawable   Canvas
 */
open class SignInBtn(context: Context?, attrs: AttributeSet?) : Button(context, attrs){

    private var mGradientDrawable: GradientDrawable? = null  //设置按钮背景样式
    private var paint : Paint? =null  //画笔
    private var mLeft = 0f  //按钮左边缩放动画的值
    private var mRight = 0f //按钮右边缩放动画的值
    private var start : Float = 0f //圆弧开始动画的值
    private var isdraw : Boolean = false //是否开始绘制圆弧
    private var mValueAnimator2 : ValueAnimator? = null

    /**
     * 初始化块
     */
    init {
        initView()//设置按钮的初始样式
    }


    /**
     * 设置按钮的初始样式
     */
    private fun initView() {
        //初始化画笔
        paint= Paint() // 创建画笔
        paint!!.isAntiAlias = true // 设置画笔抗锯齿(使线条平滑)
        paint!!.color = Color.parseColor("#ffffff") // 设置画笔颜色
        paint!!.strokeWidth = 4f // 设置画笔宽度
        paint!!.style = Paint.Style.STROKE // 设置画笔风格

        //初始化按钮背景样式
        mGradientDrawable = GradientDrawable()  //shape在代码中的使用方式
        mGradientDrawable!!.setColor(Color.argb(100,0,0,255)) //按钮背景颜色
        mGradientDrawable!!.cornerRadius = 130f //按钮圆角度
        background = mGradientDrawable
    }


    /**
     * 开始按钮变成圆形的动画
     */
    open fun mBtnAinim() {
        isEnabled = false //设置动画期间按钮不可点击
        text = "" //设置按钮文字为空
        val mValueAnimator = ValueAnimator.ofInt(width, height) //按钮变形动画,就是把宽度变为和高度一样
        mValueAnimator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {
            override fun onAnimationUpdate(animation: ValueAnimator) {
                val value: Int = animation.animatedValue as Int
                mLeft = (width-value)/2f
                mRight = width-(width-value)/2f
                // setBounds(left,top,right,bottom) 这四个参数值不明白可以参考view坐标系
                mGradientDrawable!!.setBounds(mLeft.toInt(),0,mRight.toInt(),height)
            }
        })
        mValueAnimator.duration = 500 //设置动画时长500毫秒
        mValueAnimator.start()
        mValueAnimator.addListener(object : AnimatorListenerAdapter(){
            override fun onAnimationEnd(animation: Animator?) { //动画结束事件的监听
                super.onAnimationEnd(animation)
                drawArc()//画圆弧 加载圆弧动画
            }
        })
    }


    /**
     * 开始圆弧旋转的动画
     */
    private fun drawArc() {
        isdraw = true  //改变状态 这样onDraw方法就可以画出圆弧
        mValueAnimator2 = ValueAnimator.ofFloat(0f,360f)
        mValueAnimator2!!.addUpdateListener(object :ValueAnimator.AnimatorUpdateListener{
            override fun onAnimationUpdate(animation: ValueAnimator?) {
                start = animation!!.animatedValue as Float
                invalidate() // 重绘view
            }
        })
        mValueAnimator2!!.repeatCount = ValueAnimator.INFINITE // 设置动画无限重复
        mValueAnimator2!!.duration = 500
        mValueAnimator2!!.start()
    }

    /**
     * 结束动画
     */
    open fun endAnim(btnText:String){
        //把btn改为原来样式
        val mValueAnimator = ValueAnimator.ofInt(0,width) //原来按钮的宽度值
        mValueAnimator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {
            override fun onAnimationUpdate(animation: ValueAnimator) {
                val value: Int = animation.animatedValue as Int
                mGradientDrawable!!.setBounds((width-value)/2,0,width-(width-value)/2,height)
            }
        })
        mValueAnimator.duration = 500
        mValueAnimator.start()
        mValueAnimator.addListener(object : AnimatorListenerAdapter(){
            override fun onAnimationEnd(animation: Animator?) {
                super.onAnimationEnd(animation)
                text = btnText // 改变btn字体
                isEnabled = true //设置按钮可点击
            }
        })

        mValueAnimator2!!.end()//停止圆弧旋转
        isdraw = false // 不画弧
        invalidate() //重绘界面
    }

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (isdraw){ //如果按钮动画完成缩放变形在开始画弧,不让按钮缩放时就会画弧,很难看
            val mRectF = RectF(mLeft+10,10f,mRight-10,height-10.toFloat())
                canvas!!.drawArc(mRectF,start,160f,false,paint) //画圆弧
        }

    }
}

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context="com.example.administrator.mktproject.MainActivity">

    <EditText
        android:id="@+id/et"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/btn"
        android:layout_centerInParent="true"
        android:layout_marginBottom="30dp"
        android:background="@drawable/et"
        android:ems="10"
        android:hint="你是不是个弟弟!"
        android:paddingBottom="8dp"
        android:paddingStart="5dp"
        android:paddingTop="8dp" />

    <com.example.administrator.mktproject.weight.SignInBtn
        android:id="@+id/btn"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginBottom="50dp"
        android:textColor="#fff"
        android:text="想好再按!"
        android:textSize="16sp" />
</RelativeLayout>

Activity代码:

package com.example.administrator.mktproject

import android.os.Build
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Looper
import android.os.SystemClock
import android.support.annotation.RequiresApi
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btn.setOnClickListener {

            btn.mBtnAinim()//开始加载动画
            val str = et.text.toString()
            Thread(Runnable {
               Thread.sleep(2000)
                Looper.prepare()
                if (str == "是") {
                    runOnUiThread({
                        btn.endAnim("知道就行!弟弟!")
                    })
                } else {
                    runOnUiThread({
                        btn.endAnim("你就是弟弟!")
                    })
                }
                Looper.loop()
            }).start()



        }
    }
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现 Android Kotlin按钮展示 Spinner 的自定义样式,可以按照以下步骤进行: 1. 在布局文件中添加一个 Button 控件和一个隐藏的 Spinner 控件: ```xml <Button android:id="@+id/btn_spinner" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Select Item"/> <Spinner android:id="@+id/spinner" android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/> ``` 2. 在 Kotlin 代码中设置 Button 的点击事件: ```kotlin btn_spinner.setOnClickListener { spinner.performClick() } ``` 3. 创建一个自定义的 Spinner 样式,例如: ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp"> <ImageView android:id="@+id/img_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher"/> <TextView android:id="@+id/tv_item_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:text="Item Name" android:textSize="16sp"/> </LinearLayout> ``` 4. 创建一个自定义的 Spinner 适配器: ```kotlin class CustomSpinnerAdapter(private val context: Context, private val items: List<String>) : ArrayAdapter<String>(context, 0, items) { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { var view = convertView if (view == null) { view = LayoutInflater.from(context).inflate(R.layout.item_spinner, parent, false) } val tvItemName = view?.findViewById<TextView>(R.id.tv_item_name) tvItemName?.text = items[position] return view!! } override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { var view = convertView if (view == null) { view = LayoutInflater.from(context).inflate(R.layout.item_spinner_dropdown, parent, false) } val tvItemName = view?.findViewById<TextView>(R.id.tv_item_name) tvItemName?.text = items[position] return view!! } } ``` 5. 在 Kotlin 代码中设置 Spinner 的适配器和选择事件: ```kotlin val items = listOf("Item 1", "Item 2", "Item 3") val adapter = CustomSpinnerAdapter(this, items) spinner.adapter = adapter spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { btn_spinner.text = items[position] } override fun onNothingSelected(parent: AdapterView<*>?) { // Do nothing } } ``` 这样就可以实现一个自定义样式的 Spinner,展示在一个 Button 控件上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值