效果图:

主要的代码为:
- class EditLayout @JvmOverloads constructor(
- context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
- ) : ConstraintLayout(context, attrs, defStyleAttr) {
- private var editTitle: String
- private var editContent: String
- private var editType: Int
- private var isMust: Boolean
- private var tvLabelEdit: TextView
- private var ivMustEdit: ImageView
- private var etEdit: EditText
- private var editable: Boolean
-
- init {
- LayoutInflater.from(context).inflate(R.layout.layout_edit, this)
- tvLabelEdit = findViewById(R.id.tv_label_edit)
- ivMustEdit = findViewById(R.id.iv_must_edit)
- etEdit = findViewById(R.id.et_edit)
-
- val typedArray = context.obtainStyledAttributes(attrs, R.styleable.EditLayout)
- editTitle = typedArray.getString(R.styleable.EditLayout_editTitle) ?: ""
- editContent = typedArray.getString(R.styleable.EditLayout_editContent) ?: ""
- editType = typedArray.getInt(R.styleable.EditLayout_editType, 1)
- editable = typedArray.getBoolean(R.styleable.EditLayout_editable, true)
- isMust = typedArray.getBoolean(R.styleable.EditLayout_isMust, false)
-
- typedArray.recycle();
- applyLabel()
- applyIv()
- applyEdit()
- }
-
- private fun applyLabel() {
- tvLabelEdit.text = editTitle
- etEdit.setText(editContent)
- }
-
- private fun applyIv() {
- ivMustEdit.visibility = if (isMust) View.VISIBLE else View.GONE
- }
-
- private fun applyEdit() {
- etEdit.inputType = when (editType) {
- 1 -> InputType.TYPE_CLASS_TEXT
- 2 -> InputType.TYPE_CLASS_NUMBER
- else -> InputType.TYPE_CLASS_TEXT
- }
- etEdit.isEnabled = editable
- }
-
- fun getEditText(): EditText {
- return etEdit
- }
-
- fun getInputText(): String {
- return etEdit.text.toString()
- }
-
- fun setInputText(input: String) {
- etEdit.setText(input)
- }
- }
使用3个原生控件组合而成,具体的代码可以到这里下载:
https://download.csdn.net/download/wy313622821/88467564

主要的代码:
- @SuppressLint("ClickableViewAccessibility")
- class FloatWindow(private val mContext: Context) : LifecycleService() {
- private var floatRootView: View? = null
- private val mBinding: WindowFloatBinding by lazy {
- DataBindingUtil.inflate(LayoutInflater.from(mContext), R.layout.window_float, null, false)
- }
- private val windowManager: WindowManager by lazy {
- mContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
- }
- private val layoutParams: WindowManager.LayoutParams by lazy {
- WindowManager.LayoutParams().apply {
- width = WindowManager.LayoutParams.WRAP_CONTENT
- height = WindowManager.LayoutParams.WRAP_CONTENT
- flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- gravity = Gravity.END
-
- type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
- } else {
- WindowManager.LayoutParams.TYPE_PHONE
- }
- }
- }
- private var mAllDoorListen: () -> Unit = {}
-
- init {
- floatRootView = mBinding.root
- floatRootView?.setOnTouchListener(ItemViewTouchListener(layoutParams, windowManager))
- floatRootView?.setBackgroundColor(Color.TRANSPARENT)
-
- val outMetrics = DisplayMetrics()
- windowManager.defaultDisplay.getMetrics(outMetrics)
-
- layoutParams.format = PixelFormat.TRANSPARENT
- mBinding.tvOpenDoorAll.setOnClickListener {
- }
- mBinding.clLeft.setOnClickListener {
- Log.e("TAG", "缩小")
- indenteOrExpand()
- }
-
- }
-
- /** 缩进或者展开 **/
- private fun indenteOrExpand() {
- mBinding.llContentOperate.let {
- if (it.visibility == View.GONE) {
- it.visibility = View.VISIBLE
- mBinding.ivIndenteExpand.setImageResource(R.mipmap.ic_indentation_float)
- } else {
- it.visibility = View.GONE
- mBinding.ivIndenteExpand.setImageResource(R.mipmap.ic_expand_float)
- }
- }
- }
-
- inner class ItemViewTouchListener(
- private val wl: WindowManager.LayoutParams,
- private val windowManager: WindowManager
- ) : View.OnTouchListener {
- // private var x = 0
- private var y = 0
- override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
- Log.e("TAG", "位置改变")
- when (motionEvent.action) {
- MotionEvent.ACTION_DOWN -> {
- // x = motionEvent.rawX.toInt()
- y = motionEvent.rawY.toInt()
-
- }
- MotionEvent.ACTION_MOVE -> {
- // val nowX = motionEvent.rawX.toInt()
- val nowY = motionEvent.rawY.toInt()
- // val movedX = nowX - x
- val movedY = nowY - y
- // x = nowX
- y = nowY
- wl.apply {
- // x += movedX
- y += movedY
- }
- //更新悬浮球控件位置
- windowManager.updateViewLayout(view, wl)
- }
- else -> {
-
- }
- }
- return false
- }
- }
-
- /** 悬浮窗显示 */
- fun show() {
- windowManager.addView(floatRootView, layoutParams)
- }
-
- /** 悬浮窗移除 */
- fun remove() {
- floatRootView?.let {
- windowManager.removeViewImmediate(it)
- floatRootView = null
- }
- }
-
- /** 设置全部开启按钮监听 */
- fun setOpenAllListener(mListen: () -> Unit) {
- mAllDoorListen = mListen
- }
- }
详细的代码请到这里下载:https://download.csdn.net/download/wy313622821/88468147