Android: how to check if a View inside of ScrollView is visible?

后端 未结 14 2030
自闭症患者
自闭症患者 2020-11-22 16:42

I have a ScrollView which holds a series of Views. I would like to be able to determine if a view is currently visible (if any part of it is curre

14条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-22 17:31

    I ended up implementing a combination of two of the Java answers ( @bill-mote https://stackoverflow.com/a/12428154/3686125 and @denys-vasylenko https://stackoverflow.com/a/25528434/3686125 ) in my project as a set of Kotlin extensions, which support either standard vertial ScrollView or HorizontalScrollView controls.

    I just tossed these in a Kotlin file named Extensions.kt, no class, just methods.

    I used these to determine which item to snap to when a user stops scrolling in various scrollviews in my project:

    fun View.isPartiallyOrFullyVisible(horizontalScrollView: HorizontalScrollView) : Boolean {
        val scrollBounds = Rect()
        horizontalScrollView.getHitRect(scrollBounds)
        return getLocalVisibleRect(scrollBounds)
    }
    
    fun View.isPartiallyOrFullyVisible(scrollView: ScrollView) : Boolean {
        val scrollBounds = Rect()
        scrollView.getHitRect(scrollBounds)
        return getLocalVisibleRect(scrollBounds)
    }
    
    fun View.isFullyVisible(horizontalScrollView: HorizontalScrollView) : Boolean {
        val scrollBounds = Rect()
        horizontalScrollView.getDrawingRect(scrollBounds)
        val left = x
        val right = left + width
        return scrollBounds.left < left && scrollBounds.right > right
    }
    
    fun View.isFullyVisible(scrollView: ScrollView) : Boolean {
        val scrollBounds = Rect()
        scrollView.getDrawingRect(scrollBounds)
        val top = y
        val bottom = top + height
        return scrollBounds.top < top && scrollBounds.bottom > bottom
    }
    
    fun View.isPartiallyVisible(horizontalScrollView: HorizontalScrollView) : Boolean = isPartiallyOrFullyVisible(horizontalScrollView) && !isFullyVisible(horizontalScrollView)
    fun View.isPartiallyVisible(scrollView: ScrollView) : Boolean = isPartiallyOrFullyVisible(scrollView) && !isFullyVisible(scrollView)
    

    Example usage, iterating through scrollview's LinearLayout children and logging outputs:

    val linearLayoutChild: LinearLayout = getChildAt(0) as LinearLayout
    val scrollView = findViewById(R.id.scroll_view) //Replace with your scrollview control or synthetic accessor
    for (i in 0 until linearLayoutChild.childCount) {
        with (linearLayoutChild.getChildAt(i)) {
            Log.d("ScrollView", "child$i left=$left width=$width isPartiallyOrFullyVisible=${isPartiallyOrFullyVisible(scrollView)} isFullyVisible=${isFullyVisible(scrollView)} isPartiallyVisible=${isPartiallyVisible(scrollView)}")
        }
    }
    

提交回复
热议问题