美文网首页
鼠年落幕,牛年荣登,年末献上《悬浮输入框》小菜

鼠年落幕,牛年荣登,年末献上《悬浮输入框》小菜

作者: JasonChen8888 | 来源:发表于2021-02-08 15:29 被阅读0次

    给大家拜年

    2021牛年来临,祝大家体壮如牛,知识汗牛充栋,财运气冲斗牛,钱多如牛毛,爱情象牛郎织女一样浪漫,朋友见您都说:这人真牛!

    年末整理

    年底了,即将放假了,手上的工作都已经收尾了,今天整理下重新的编写了下,项目中,一个跟随输入法弹出隐藏的悬浮于输入法上方的输入框控件

    挽起袖子撸代码

    • 构思
      想到需要悬浮在输入法上面,想到两种的思路
    1. 采用popwindow的形式,显示绑定anchorView的,可以设置视图底部的一个固定高度为1dp的进行显示,这样在输入法弹出的时候,同时配置window的是adjust_resize,触碰其他的外部区域消失(最终采用这种实现方式
    2. 创建一个自定义的布局,绑定在根布局上方,在调用的时候进行显示,分配设置两个区域,一个是透明层出发隐藏,一个是控件本身的区域
    • 实践
      继承PopWindow
    1. 编写动态悬浮输入框的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)
        }
    
    1. 设置内容,配置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()
                }
            }
        }
    
    1. 设置绑定目标的输入框,将目标对应的属性设置到悬浮的输入框
    fun setTargetEdit(editText: EditText) {
            this.targetEdit = editText
            inputEdit.text = targetEdit.text
            inputEdit.setSelection(targetEdit.length())
            inputEdit.inputType = targetEdit.inputType
            inputEdit.keyListener = targetEdit.keyListener
        }
    
    1. 对调用接口
       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) }
    

    代码就此撸完了
    欢迎大家阅读评论,如果错误欢迎指正

    相关文章

      网友评论

          本文标题:鼠年落幕,牛年荣登,年末献上《悬浮输入框》小菜

          本文链接:https://www.haomeiwen.com/subject/noexxltx.html