Как прокрутить прокручиваемый контент, загруженный в веб-просмотр, который является одним из элементов RecycleView - PullRequest
0 голосов
/ 04 декабря 2018

Имея RecycleView, он имеет несколько элементов, и один из них - это представление, содержащее WebView.Внутри WebView он загружает html, и есть iframe с содержимым html-таблицы, который можно прокручивать по вертикали (содержащийся div имеет фиксированную высоту, меньшую высоты таблицы).

Кажется, есть проблема сRecycler Считайте, что он не передает событие касания в WebView.

Вот что происходит:

При касании экрана для перетаскивания onInterceptTouchEvent () в recycleView сначала return false at ACTION_DOWN, а затем return true when the event is MotionEvent.ACTION_MOVE,Это return true отправит целевому дочернему представлению MotionEvent.Cancel, и все дальнейшие события будут доставлены в onTouchEvent ()

TestDerivedRecycleView:onInterceptTouchEvent(), return: false     
              event: MotionEvent { action=ACTION_DOWN, actionButton=0... }, this.scrollState: 0

TestDerivedRecycleView:onInterceptTouchEvent(), return: true
              event: MotionEvent { action=ACTION_MOVE, actionButton=0... }, this.scrollState: 1

RecycleView. Поэтому я создал производный RecycleView, который, когда событие является ACTION_MOVEна целевом представлении есть WebView, тогда return false to let WebView handle the drag/move.

Это частично работает.Так как у webView может быть какой-то другой контент, например текстовая область.Если коснуться этой текстовой области, она не будет прокручиваться, поэтому представление рециркуляции не будет прокручиваться.Только если коснуться и перетащить этот элемент таблицы, элемент таблицы будет прокручивать содержимое таблицы.

Желаемое поведение должно происходить при перетаскивании любого элемента в RecyclerView, RecyclerView должен прокручивать его элементы вверх, только при перетаскивании по этой прокручиваемой таблице.элемент, в котором таблица должна прокручивать содержимое, если нижняя часть таблицы не отображается.

Как заставить прокрутку содержимого веб-просмотра работать, когда он является дочерним элементом RecycleView?

class TestDerivedRecycleView : RecyclerView {
    constructor(context: Context) : super(context) {}

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {}


    override fun onTouchEvent(event: MotionEvent): Boolean {

        val ret = super.onTouchEvent(event)

        Log.d("+++", "+++ TestDerivedRecycleView:onTouchEvent(), ret: $ret" +
                "\nevent.action: ${event.action}, " +
                "\nevent: $event" +
                "\nthis: ${this}")

       return ret   
    }


    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {

        val ret = super.onInterceptTouchEvent(event)

        val myCell = findChildViewUnder(event.x, event.y)

        Log.w("+++", "+++ TestDerivedRecycleView:onInterceptTouchEvent(), ret: $ret" +
                "\nmyCell: $myCell"+
                "\n event.action: ${event.action}, this.scrollState: ${this.scrollState}" +
                "\nevent: $event"+
                "\nthis: $this")

        // when the event is ACTION_MOVE and is touched on the WebView then return false to let WebView handle the event
        if (
                (myCell is ArticleWebView) &&
                event.action == MotionEvent.ACTION_MOVE
                && this.scrollState == RecyclerView.SCROLL_STATE_DRAGGING
        ) { 

            Log.e("+++", "+++ TestDerivedRecycleView:onInterceptTouchEvent(), (myCell is WebView) return false")

            return false
        }
        return ret
    }
}

1 Ответ

0 голосов
/ 05 декабря 2018

найти решение, но не идею.

в принципе, проблема в том, что RecycleView перехватывает событие 'move' (его super.onInterceptTouchEvent(event) вернет true), так что Webview получит событие 'cancel' иникаких других последующих событий, которые заставляют элементы в RecyclerView прокручиваться, но веб-просмотр не получает возможности прокручивать его содержимое.

решение состоит в том, чтобы не позволить RecyclerView перехватывать событие 'move'.

Есть и другая проблема с этим подходом, поскольку в WebView html может иметь некоторое содержимое с возможностью прокрутки, а другое - без возможности прокрутки.Если просто позволить веб-просмотру переместить движение, и точка касания находится в некоторой не прокручиваемой области, то перемещение касанием / перетаскиванием не будет иметь эффекта (элемент элемента в RecyclerView также не будет прокручиваться, так как он больше не перехватывал событие).

Таким образом, это частичное исправление заключается в том, чтобы только когда два пальца коснулись веб-просмотра, затем отключить перехват RecyclerView.Таким образом, по крайней мере одним касанием пальца будет продолжаться прокрутка элемента списка, а касанием двумя пальцами будет прокручиваться прокручиваемое содержимое веб-просмотра.

Плохая часть заключается в том, что касание двумя пальцами одной области просмотра без прокрутки не будет иметь эффекта прокрутки.

Если кто-нибудь знает лучшее решение, поделитесь, спасибо!

в Webviewдобавил слушателя:

val listener = OnTouchListener { v, event ->
    var perantViewGroup = v.parent
    when {
        event.actionMasked == MotionEvent.ACTION_DOWN -> mFingersDown = 1
        event.actionMasked == MotionEvent.ACTION_POINTER_DOWN -> mFingersDown++
        event.actionMasked == MotionEvent.ACTION_POINTER_UP -> mFingersDown--
        event.actionMasked == MotionEvent.ACTION_UP -> mFingersDown = 0
    }

    if ((mFingersDown >= 2) && event.actionMasked == MotionEvent.ACTION_MOVE) {
        perantViewGroup.requestDisallowInterceptTouchEvent(true)
    } else if (event.actionMasked == MotionEvent.ACTION_UP) {
        perantViewGroup.requestDisallowInterceptTouchEvent(false)
    }

    false
}
webview.setOnTouchListener(listener)

, а также в RecycleView добавив некоторую помощь, чтобы предотвратить его перехват события 'move'.

class TestDerivedRecycleView : RecyclerView {
    ......

    private var mFingersDown = 0
    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {

        when {
            event.actionMasked == MotionEvent.ACTION_DOWN -> mFingersDown = 1
            event.actionMasked == MotionEvent.ACTION_POINTER_DOWN -> mFingersDown++
            event.actionMasked == MotionEvent.ACTION_POINTER_UP -> mFingersDown--
            event.actionMasked == MotionEvent.ACTION_UP -> mFingersDown = 0
        }
        val touchedCell = findChildViewUnder(event.x, event.y)
        if ((touchedCell is WebView) && (mFingersDown >= 2) && event.actionMasked == MotionEvent.ACTION_MOVE) {
            return false
        }
        return super.onInterceptTouchEvent(event)
    }
}
...