alexvasilkov / GestureViews

ImageView and FrameLayout with gestures control and position animation
Apache License 2.0
2.37k stars 384 forks source link

Can't scroll on RecyclerView when the item has click listener #160

Open wendrawang opened 4 years ago

wendrawang commented 4 years ago

I cant scroll the specific item in RecyclerView if that item has click listener.

alexvasilkov commented 4 years ago

Too little details, please provide a proper description with examples and explanation how RecyclerView items issue is related to this library.

wendrawang commented 4 years ago

I'm using like this :

<com.alexvasilkov.gestures.views.GestureFrameLayout
        android:id="@+id/moving_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycle_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
</com.alexvasilkov.gestures.views.GestureFrameLayout>

inside the recyclerview adapter, i have specific item that has onClickListener

val header = HeaderViewHolder(layoutView)
if(position == 1) {
      header.reloadBtn.setOnClickListener {}
}

i cant scroll the recycler from that inside specific item that has onclicklistener, but i can click on other item that doesnt has onclicklistener

video sample : (the item that cant scroll is the one that has onclicklistener) sample

alexvasilkov commented 3 years ago

I tried adding RecyclerView with buttons into GestureFrameLayout and it seems to handle both clicks and scrolling (started on a button) just fine.

Note that there was a fix for nested scrolling in the latest version, do you use 2.6.0?

If you still have the issue in v2.6.0 then I'll need exact code (e.g. a sample project) to reproduce it.

luthfi-ali commented 3 years ago

I had the same issue too, using version 2.7.1

alexvasilkov commented 3 years ago

Can you reproduce the issue in the sample app? Or can you modify the sample app in the way that will showcase this issue? I tried it myself and wasn't able to reproduce it, but without understanding what exactly is not working for you I can do little.

luthfi-ali commented 3 years ago

This is my case

I just load a list of simple ImageView with RecyclerView, and I set a click listener to the ImageView and I can't even scroll the list. When I removed the click listener it scrolled just fine. My workaround is to set the click listener to GestureFrameLayout instead of ImageView as I have the same logic for all clicks without needing the image data anyway.

luthfi-ali commented 3 years ago

This is my code, maybe it could help. As I haven't had the time to look at the example.

Activity

<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
    android:id="@+id/refresh"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.alexvasilkov.gestures.views.GestureFrameLayout
        android:id="@+id/zoom_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:listitem="@layout/item_comic_chapter_read" />

    </com.alexvasilkov.gestures.views.GestureFrameLayout>

</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

item layout <ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/image_iv" android:layout_width="match_parent" android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="fitCenter" />

View holder ` public class ChapterReadViewHolder extends RecyclerView.ViewHolder { private final ImageView ivImage;

public ChapterReadViewHolder(View view) {
    super(view);

    ivImage = view.findViewById(R.id.image_iv);
}

public void bindData(ChapterPage data) {
    Glide.with(ivImage)
            .load(data.getImagePath())
            .into(ivImage);

    ivImage.setOnClickListener(v -> Log.d("Test", "Hello"));
}

} `

It's just a simple list actually.

alexvasilkov commented 3 years ago

Yes, thanks, I can reproduce it now, not sure why I didn't see that myself.

I did a quick research and it turns out that if RecyclerView items are clickable then RecyclerView will call requestDisallowInterceptTouchEvent() much later and by that time GestureFrameLayout will already accumulate enough touch scroll to decide to take control over all the touch events.

Nested scrolling is complicated, Google added a lot of logic accross their widgets in the last several years to support it, but before that it wasn't really possible to nest widgets that can scroll in same direction.

The solution now is to partly rewrite this library to implement all the APIs provided by Google to have a smooth nesting scroll. But that is a hell lot of work, so I doubt I will had a time to do that anytime soon.

BTW, can you explain why do you need to nest RecyclerView inside the GestureFrameLayout, what is your use case?

luthfi-ali commented 3 years ago

Hi, thanks for the reply and the research.

I'm building a comic reader app. It's just a list of images but it also needs to be zoomable. I tried it with zoomable feature per ImageView but the user experience looks weird, so I looked at another comic app (ex webtoon) and they were zoomable as a whole. So I'm thinking that it should be the RecyclerView that was zoomed.