c-an
c-an

Reputation: 4080

How to get view with x and y position on Android

I am trying to get view in dispatchTouchEvent().

However, this only passes MotionEvent. It has x and y position. But, it doesn't pass view itself.

I can get view with currentFocus. However, this gets view after having a focus. And when you touch EditText and then Outside of EdiText, EditText still has the focus. So, currentFocus will be the same EditText.

What I am trying to do is closing keyboard when I touch non-EditText. And showing keybaord when I touch EditText. But when I touch EditText A and then EditText B, it shouldn't be blinking(hiding and showing again)

What I was trying is:

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        var view = currentFocus
        if (view == null) {
            view = View(this@BaseActivity)
        }

        ev?.let {
            val isInRange = isRegionOfInterest(view, ev)

            if(!isInRange){
                hideKeyboard()
                currentFocus?.clearFocus()
            }
        }
        return super.dispatchTouchEvent(ev)
}

But this doesn't seem to be the right way. It'd be great if I can get a view with X and Y positon. Do you know any way to do that?

Upvotes: 0

Views: 270

Answers (1)

c-an
c-an

Reputation: 4080

This is what I did:

    private fun isHidableArea(x: Float?, y: Float?): Boolean {
        var result = true

        if (x == null || y == null) return result

        val rootView = (findViewById<View>(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup
        val interestViewList = rootView.findInterestViewListByPosition(x, y)

        loop@ for (v in interestViewList) {
            if (v is EditText) {
                result = false
                break@loop
            }
        }
        return result
    }

    private fun View.findInterestViewListByPosition(x: Float, y: Float): ArrayList<View> {
        val childViewList = this.getAllChildren()
        val interestViewList = ArrayList<View>()

        for (it in childViewList) {
            if (isRegionOfInterest(it, x, y)) {
                interestViewList.add(it)
            }
        }
        return interestViewList
    }

    private fun View.getAllChildren(): List<View> {
        val result = ArrayList<View>()
        if (this !is ViewGroup) {
            result.add(this)
        } else {
            for (index in 0 until this.childCount) {
                val child = this.getChildAt(index)
                result.addAll(child.getAllChildren())
            }
        }
        return result
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        if (isHidableArea(ev.x, ev.y)) {
            hideKeyboard()
        }
        return super.dispatchTouchEvent(ev)
    }

    private fun isRegionOfInterest(view: View, x: Float, y: Float): Boolean {
        return x in view.x - 0..(view.x + view.width) && y in view.y - 0..view.y + view.height
    }

This gets all the child view and compare the position.

Upvotes: 0

Related Questions