class Counter : LinearLayout {
//通过 this 调用到三参构造中进行统一处理
constructor(context: Context?) : this(context, null)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
//TODO...
}
}
private lateinit var tvPlus: TextView
private lateinit var tvMinus: TextView
private lateinit var etValue: EditText
//初始化控件
private fun initView(context: Context?) {
if (context != null) {
val view = LayoutInflater.from(context).inflate(R.layout.layout_counter, this)
tvPlus = view.findViewById(R.id.tvPlus)
tvMinus = view.findViewById(R.id.tvMinus)
etValue = view.findViewById(R.id.etValue)
}
//简写
// context?.let {
// val view = LayoutInflater.from(context).inflate(R.layout.layout_counter, this).run {
// tvPlus = findViewById(R.id.tvPlus)
// tvMinus = findViewById(R.id.tvMinus)
// etValue = findViewById(R.id.etValue)
// }
// }
}
private var mCounter = 0
//获取计数
fun getCounter(): Int = mCounter
//设置计数
fun setCounter(value: Int) {
mCounter = value
updateCounter()
}
//更新计数
private fun updateCounter() {
etValue.setText(mCounter.toString())
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
handleEvents()
}
//处理点击事件
private fun handleEvents() {
tvPlus.setOnClickListener {
mCounter++
updateCounter()
}
tvMinus.setOnClickListener {
mCounter--
updateCounter()
}
}
private var mOnCounterChangeListener: OnCounterChangeListener? = null
//暴露接口
interface OnCounterChangeListener {
fun onCounterChange(value: Int)
}
//设置计数变动监听器
fun setOnCounterChangeListener(listener: OnCounterChangeListener) {
mOnCounterChangeListener = listener
}
private fun updateCounter() {
//监听器不为null就调用回调方法
mOnCounterChangeListener?.onCounterChange(mCounter)
}
values文件夹右键→New→Values Resource File→命名attrs。
//属性(保持public因为要暴露getter/setter供UI中代码调用)
var min: Int = 0
var max: Int = 0
var step: Int = 0
var disable: Boolean = false
var defaultValue: Int = 0
//调用setter的时候要赋值给mCounter并更新
set(value) {
field = value
mCounter = value
updateCounter()
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
initAttrs(context, attrs)
}
//初始化属性
private fun initAttrs(context: Context?, attrs: AttributeSet?) {
if (context != null && attrs != null) {
val attributes = context.obtainStyledAttributes(attrs, R.styleable.Counter)
min= attributes.getInt(R.styleable.Counter_min, 0)
max= attributes.getInt(R.styleable.Counter_max, 0)
step= attributes.getInt(R.styleable.Counter_step, 0)
disable = attributes.getBoolean(R.styleable.Counter_disable, false)
defaultValue = attributes.getInt(R.styleable.Counter_disable, 0)
mCounter = defaultValue //获取了默认值就设置给mCounter,更新动作放在initView()中
attributes.recycle()
}
//简写
// context?.obtainStyledAttributes(attrs, R.styleable.Counter)?.run {
// min= getInt(R.styleable.Counter_min, 0)
// max= getInt(R.styleable.Counter_max, 0)
// step = getInt(R.styleable.Counter_step, 0)
// disable = getBoolean(R.styleable.Counter_disable, false)
// defaultValue = getInt(R.styleable.Counter_disable, 0)
// recycle()
// }
}
private fun initView(context: Context?) {
if (context != null) {
//...
//将属性中设置的值更新到控件上
updateCounter()
tvPlus.isEnabled = mEnable
tvMinus.isEnabled = mEnable
}
}
private fun handleEvents() {
tvPlus.setOnClickListener {
//按下后就不是最小值,解除tvMinus按钮禁用
tvMinus.isEnabled = true
//步进不为1的时候,要考虑值溢出的情况
mCounter += mStep
//如果计数大于等于最大值就设为最大值,并禁用按钮
if (mCounter >= mMax) {
mCounter = mMax
tvPlus.isEnabled = false
}
updateCounter()
}
tvMinus.setOnClickListener {
tvPlus.isEnabled = true
mCounter -= mStep
if (mCounter <= mMin) {
mCounter = mMin
tvMinus.isEnabled = false
}
updateCounter()
}
}
根布局添加命名空间(只需要输入app,IDE会自动补全)。