1. Custom edit box
Rendering:
The main codes are:
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) } }
It is composed of 3 native controls. The specific code can be downloaded here:
https://download.csdn.net/download/wy313622821/88467564
2. Floating window
Main code:
@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", "Reduce") indenteOrExpand() } } /** Indent or expand **/ 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", "position change") 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 } //Update the position of the floating ball control windowManager.updateViewLayout(view, wl) } else -> { } } return false } } /** Floating window display */ fun show() { windowManager.addView(floatRootView, layoutParams) } /** Floating window removal */ fun remove() { floatRootView?.let { windowManager.removeViewImmediate(it) floatRootView = null } } /** Set all open button monitoring */ fun setOpenAllListener(mListen: () -> Unit) { mAllDoorListen = mListen } }
Please download the detailed code here: https://download.csdn.net/download/wy313622821/88468147