给大家拜年
2021牛年来临,祝大家体壮如牛,知识汗牛充栋,财运气冲斗牛,钱多如牛毛,爱情象牛郎织女一样浪漫,朋友见您都说:这人真牛!
年末整理
年底了,即将放假了,手上的工作都已经收尾了,今天整理下重新的编写了下,项目中,一个跟随输入法弹出隐藏的悬浮于输入法上方的输入框控件
挽起袖子撸代码
- 构思
想到需要悬浮在输入法上面,想到两种的思路
- 采用popwindow的形式,显示绑定anchorView的,可以设置视图底部的一个固定高度为1dp的进行显示,这样在输入法弹出的时候,同时配置window的是adjust_resize,触碰其他的外部区域消失(
最终采用这种实现方式
) - 创建一个自定义的布局,绑定在根布局上方,在调用的时候进行显示,分配设置两个区域,一个是透明层出发隐藏,一个是控件本身的区域
- 实践
继承PopWindow
- 编写动态悬浮输入框的UI
private lateinit var contentView : RelativeLayout
private lateinit var sendBtn: Button
private lateinit var inputEdit: EditText
private fun createContentView(context: Context) {
//根视图
contentView = RelativeLayout(context).apply {
layoutParams = RelativeLayout.LayoutParams(
MATCH_PARENT,
WRAP_CONTENT
)
}
//中间层视图
val inputLayuot = LinearLayout(context).apply {
layoutParams = RelativeLayout.LayoutParams(
MATCH_PARENT,
ScreenUtils.dip2px(context, 46f)
)
//垂直方向居中
gravity = Gravity.CENTER_VERTICAL
//设置背景
setBackgroundColor(Color.parseColor("#f3f4f6"))
//水平排版
orientation = LinearLayout.HORIZONTAL
//设置内间距
val padding = ScreenUtils.dip2px(context, 8f)
setPadding(padding, 0, padding, 0)
}
//输入框
inputEdit = EditText(context).apply {
//设置输入框背景
setBackgroundResource(R.drawable.float_input_bg_edit)
//内容垂直方向居中
gravity = Gravity.CENTER_VERTICAL
//高度32dp,宽带自适应剩余空间
layoutParams = LinearLayout.LayoutParams(0, ScreenUtils.dip2px(context, 32f), 1f).apply {
//控件垂直方向居中
gravity = Gravity.CENTER_VERTICAL
//右间距8dp
rightMargin = ScreenUtils.dip2px(context, 8f)
}
setPadding(0,0,0,0)
}
//添加输入框
inputLayuot.addView(inputEdit)
//发送按钮
sendBtn = Button(context).apply {
//默认背景
setBackgroundResource(R.drawable.float_input_bg_disable_button)
//固定文按
text = "发送"
//文字居中限时
gravity = Gravity.CENTER
//字体颜色
setTextColor(Color.parseColor("#FFFFFF"))
//布局参数:宽度 60dp 高度 32dp
layoutParams = LinearLayout.LayoutParams(
ScreenUtils.dip2px(context, 60f),
ScreenUtils.dip2px(context, 32f)
).apply {
//按钮控件垂直居中
gravity = Gravity.CENTER_VERTICAL
}
setPadding(0,0,0,0)
}
//添加按钮
inputLayuot.addView(sendBtn)
//添加布局到容器中
contentView.addView(inputLayuot)
}
- 设置内容,配置window的窗口大小,还有属性
constructor(context: Context) : super(context) {
init(context)
}
private fun init(context: Context) {
this.context = context
createContentView(context)
setContentView(contentView)
//宽、高设置
width = MATCH_PARENT
height = WRAP_CONTENT
//可聚焦
isFocusable = true
// 设置SelectPicPopupWindow弹出窗体动画效果
// animationStyle = R.style.showPopAnimation
// 实例化一个ColorDrawable颜色为半透明
val colorDrawable = ColorDrawable(-0x50000000)
setBackgroundDrawable(colorDrawable)
initView(context)
}
3、配置悬浮输入框的属性
注意点:当项目是横屏的时候,很多输入法是满屏,需要禁止输入法全屏
private fun initView(context: Context) {
//文本框的配置
inputEdit.apply {
inputType = EditorInfo.TYPE_CLASS_TEXT
//横屏时禁止输入法全屏
imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
if (TextUtils.isEmpty(inputEdit.text)) {
sendBtn.isEnabled = false
sendBtn.setBackgroundResource(R.drawable.float_input_bg_disable_button)
} else {
sendBtn.isEnabled = true
sendBtn.setBackgroundResource(R.drawable.float_input_bg_enable_button)
}
}
override fun beforeTextChanged(
s: CharSequence?,
start: Int,
count: Int,
after: Int
) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
})
//设置输入法的按钮事件
setOnEditorActionListener(object : TextView.OnEditorActionListener{
override fun onEditorAction(
v: TextView?,
actionId: Int,
event: KeyEvent?
): Boolean {
if (actionId == EditorInfo.IME_ACTION_SEND
|| event != null && event.keyCode == KeyEvent.KEYCODE_ENTER
) {
targetEdit.text = inputEdit.text
dismiss()
return true
}
return false
}
})
}
sendBtn.setOnClickListener {
if (!TextUtils.isEmpty(inputEdit.text.toString().trim { it <= ' ' })) {
// /提交内容
targetEdit.text = inputEdit.text
dismiss()
}
}
}
- 设置绑定目标的输入框,将目标对应的属性设置到悬浮的输入框
fun setTargetEdit(editText: EditText) {
this.targetEdit = editText
inputEdit.text = targetEdit.text
inputEdit.setSelection(targetEdit.length())
inputEdit.inputType = targetEdit.inputType
inputEdit.keyListener = targetEdit.keyListener
}
- 对调用接口
fun show(anchorView: View?) {
//调起输入法
openKeyboard()
//显示悬浮输入框
showAtLocation(
anchorView, Gravity.BOTTOM
or Gravity.CENTER_HORIZONTAL, 0, 0
)
}
private fun openKeyboard() {
val handler = Handler()
if (inputEdit != null) {
inputEdit.isFocusable = true
inputEdit.requestFocus()
}
handler?.postDelayed({
try {
val imm = context
.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(inputEdit, 0)
} catch (e: Exception) {
}
}, 200)
}
- 进一步封装
创建一个类,进行对上述的自定义空间进行调用
class CbyFloatInput {
private lateinit var inputWindow: CbyFloatInputWindow
constructor(activity: Activity) {
initInputWindow(activity)
}
private fun initInputWindow(activity: Activity) {
inputWindow = CbyFloatInputWindow(activity).apply {
isFocusable = true
inputMethodMode = PopupWindow.INPUT_METHOD_NEEDED
softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
}
}
fun show(anchorView: View?, targetEdit: EditText?) {
if (inputWindow != null) {
if (targetEdit != null) {
inputWindow.setTargetEdit(targetEdit)
}
inputWindow.show(anchorView)
}
}
}
- 调用
//声明
private lateinit var floatInput : CbyFloatInput
floatInput = CbyFloatInput(this)
//调用
edit_name.setOnClickListener { floatInput.show(view_point, edit_name) }
edit_id_card.setOnClickListener { floatInput.show(view_point, edit_id_card) }
代码就此撸完了
欢迎大家阅读评论,如果错误欢迎指正