先上效果图:
image.png
自定义输入框:
class CellEditText : LinearLayout {
/**
* 输入的内容
*/
var inputNumber: StringBuilder = StringBuilder("")
/**
* 输入监听器
*/
private var mOnInputListener: OnInputListener? = null
constructor(context: Context?) : super(context) {
init()
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
init()
}
private fun init() {
val view = View.inflate(context, R.layout.cell_edit, null)
addView(view, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
}
/**
* 输入文本
*/
fun setText(str: String) {
Log.d("inputNumber", "str:" + str + " length:" + inputNumber.length)
when (inputNumber.length) {
0 -> {
inputNumber.append(str)
tv_pay1.text = str
}
1 -> {
inputNumber.append(str)
tv_pay2.text = str
}
2 -> {
inputNumber.append(str)
tv_pay3.text = str
}
3 -> {
inputNumber.append(str)
tv_pay4.text = str
}
4 -> {
inputNumber.append(str)
tv_pay5.text = str
}
5 -> {
inputNumber.append(str)
tv_pay6.text = str
if (mOnInputListener != null) {
mOnInputListener!!.onFinished(inputNumber.toString())
}
}
}
}
/**
* 回退按钮动作
*/
fun delete() {
when (inputNumber.length) {
0 -> {
}
1 -> {
inputNumber.replace(0, 1, "")
tv_pay1.text = ""
}
2 -> {
inputNumber.replace(1, 2, "")
tv_pay2.text = ""
}
3 -> {
inputNumber.replace(2, 3, "")
tv_pay3.text = ""
}
4 -> {
inputNumber.replace(3, 4, "")
tv_pay4.text = ""
}
5 -> {
inputNumber.replace(4, 5, "")
tv_pay5.text = ""
}
6 -> {
inputNumber.replace(5, 6, "")
tv_pay6.text = ""
}
}
Log.d("inputNumber", "length:" + inputNumber.length)
Toast.makeText(context, inputNumber, Toast.LENGTH_SHORT).show()
}
/**
* 暴露的输入接口
*/
fun setOnInputListener(listener: OnInputListener) {
mOnInputListener = listener
}
interface OnInputListener {
fun onFinished(str: String)
}
}
输入框布局xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_pay1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/cell_edit"
android:gravity="center"
android:textColor="#0000ff"
android:textSize="26sp"
tools:text="1"
android:layout_marginLeft="20dp"
/>
<TextView
android:id="@+id/tv_pay2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/cell_edit"
android:gravity="center"
android:textColor="#0000ff"
android:layout_marginLeft="20dp"
android:textSize="26sp"
tools:text="1" />
<TextView
android:id="@+id/tv_pay3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/cell_edit"
android:gravity="center"
android:textColor="#0000ff"
android:layout_marginLeft="20dp"
android:textSize="26sp"
tools:text="1" />
<TextView
android:id="@+id/tv_pay4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/cell_edit"
android:gravity="center"
android:textColor="#0000ff"
android:layout_marginLeft="20dp"
android:textSize="26sp"
tools:text="1" />
<TextView
android:id="@+id/tv_pay5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/cell_edit"
android:layout_marginLeft="20dp"
android:gravity="center"
android:textColor="#0000ff"
android:textSize="26sp"
tools:text="1" />
<TextView
android:id="@+id/tv_pay6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="20dp"
android:background="@drawable/cell_edit"
android:gravity="center"
android:textColor="#0000ff"
android:textSize="26sp"
android:layout_marginRight="20dp"
tools:text="1" />
</LinearLayout>
自定义键盘:
class Keyboard : RelativeLayout {
var mAdapter: MyAdapter? = null
val keys = arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "0", "完成")
companion object {
const val TYPE_COMMON = 996
const val TYPE_DELET = 965
}
constructor(context: Context) : super(context) {
init()
}
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) {
init()
}
constructor(context: Context, attributeSet: AttributeSet, style: Int) : super(context, attributeSet, style) {
init()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val widthMode = View.MeasureSpec.getMode(widthMeasureSpec)
val widthSize = View.MeasureSpec.getSize(widthMeasureSpec)
// 获取高-测量规则的模式和大小
val heightMode = View.MeasureSpec.getMode(heightMeasureSpec)
val heightSize = View.MeasureSpec.getSize(heightMeasureSpec)
// 设置wrap_content的默认宽 / 高值
// 默认宽/高的设定并无固定依据,根据需要灵活设置
// 类似TextView,ImageView等针对wrap_content均在onMeasure()对设置默认宽 / 高值有特殊处理,具体读者可以自行查看
val mWidth = 400
val mHeight = 400
// 当布局参数设置为wrap_content时,设置默认值
if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(mWidth, mHeight)
// 宽 / 高任意一个布局参数为= wrap_content时,都设置默认值
} else if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(mWidth, heightSize)
} else if (layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(widthSize, mHeight)
}
}
private fun init() {
val view = View.inflate(context, R.layout.layout_keyboard, null)
addView(view, LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
mAdapter = MyAdapter()
recycler_view.layoutManager = GridLayoutManager(context, 3)
recycler_view.addItemDecoration(DefaultItemDecoration(context))
recycler_view.adapter = mAdapter
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
inner class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {
override fun onCreateViewHolder(p0: ViewGroup, viewType: Int): MyViewHolder {
when (viewType) {
TYPE_COMMON -> {
val itemView = View.inflate(context, R.layout.common_key, null)
return MyViewHolder(itemView)
}
TYPE_DELET -> {
val itemView = View.inflate(context, R.layout.delete_key, null)
return MyViewHolder(itemView)
}
}
return MyViewHolder(View(context))
}
override fun getItemCount(): Int {
return keys.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
when (holder.itemViewType) {
TYPE_COMMON -> {
holder.itemView.findViewById<TextView>(R.id.tv_key).text = keys[position]
holder.itemView.findViewById<View>(R.id.tv_key).setOnClickListener {
if (mOnItemClickListener != null) {
mOnItemClickListener!!.onItemClick(position)
}
}
}
TYPE_DELET -> {
holder.itemView.findViewById<View>(R.id.ll_delete).setOnClickListener {
mOnItemClickListener!!.onItemClick(position)
}
}
}
}
override fun getItemViewType(position: Int): Int {
return if (position == 9) {
TYPE_DELET
} else {
TYPE_COMMON
}
}
}
interface OnItemClickListener {
fun onItemClick(position: Int)
}
private var mOnItemClickListener: OnItemClickListener? = null
fun setOnItemClickListener(listener: OnItemClickListener) {
this.mOnItemClickListener = listener
}
}
输入框监听键盘:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
cell_edit.setOnInputListener(object : CellEditText.OnInputListener {
override fun onFinished(str: String) {
Toast.makeText(this@MainActivity, "onFinish:$str", Toast.LENGTH_SHORT).show()
}
})
keyboard.setOnItemClickListener(object : Keyboard.OnItemClickListener {
override fun onItemClick(position: Int) {
when (position) {
9 -> {//回退
cell_edit.delete()
}
11 -> {//完成
Toast.makeText(this@MainActivity, cell_edit.inputNumber, Toast.LENGTH_SHORT).show()
}
else -> {
val value = keyboard.keys[position]
cell_edit.setText(value)
}
}
}
})
}
}
需要注意的坑:
自定义keyboard的wrap_content属性会失效,建议把Item的高度写死为X dp,一共有4层,所以将keyboard的高度设置为4X
项目地址:https://github.com/po1arbear/CellEditText
网友评论