水平RecyclerView内部的水平RecyclerView

时间:2018-08-13 10:02:18

标签: java android android-recyclerview kotlin

我正在尝试在另一个带有水平LinearLayoutManager的RecyclerView中使用带有水平LinearLayoutManager的RecyclerView。整个层次结构如下:RecyclerView,Recycler的子级是ScrollView,其中包含TextView和另一个RecyclerView。为了更好地理解,我希望第一个回收站的工作方式与ViewPager相同,但不完全相同(我不想使用ViewPager)。问题是当我尝试在子回收器上水平滚动时,运动事件被父回收器捕获,导致滚动到下一页而无法滚动子回收器。

MainActivityLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/RVpage"
        android:descendantFocusability="blocksDescendants"
        android:focusableInTouchMode="false"
        android:focusable="false"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setRecycler();
    }

    private void setRecycler() {
        recyclerView=(RecyclerView) findViewById(R.id.RVpage);
        SnapHelper snapHelper = new LinearSnapHelper();
        snapHelper.attachToRecyclerView(recyclerView);
        BigRecyclerAdapter bigRecyclerAdapter=new BigRecyclerAdapter(this);
        recyclerView.setAdapter(bigRecyclerAdapter);

        //recyclerView.setNestedScrollingEnabled(true);


        recyclerView.setLayoutManager(new LinearLayoutManager(
            this, LinearLayoutManager.HORIZONTAL, false)
        );
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                //Toast.makeText(MainActivity.this, "CHANGED BIG", Toast.LENGTH_SHORT).show();
                super.onScrollStateChanged(recyclerView, newState);
            }
        });
    }
}

PageRecycler布局:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView             xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:text="nskjdnaskdn \n sudbadbak
\n sudbadbak
\n sudbadbak
\n sudbadbak
\n sudbadbak\n sudbadbak
v
\n sudbadbak
\n sudbadbak
\n sudbadbak
\n sudbadbak
\n sudbadbak
\n sudbadbak
\n sudbadbak
\n sudbadbak
v
v
\n sudbadbak
\n sudbadbak
v
v
\n sudbadbak
vv
\n sudbadbak
v
v
\n sudbadbak"
        android:textColor="@android:color/black"
        android:textSize="50sp"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:focusableInTouchMode="true"
        android:focusedByDefault="true"
        android:descendantFocusability="afterDescendents"
        android:focusable="true"
        android:padding="20dp" />

    </LinearLayout>

</ScrollView>

在relativeLayout中,我保留了我尝试过的所有内容,从clickable = true到DescendentFocusability。

PageRecycler适配器:

class BigRecyclerAdapter(private val context: MainActivity) :     RecyclerView.Adapter<BigRecyclerAdapter.ViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
        val v = LayoutInflater.from(parent?.context)
            .inflate(R.layout.raw, parent, false)

        return ViewHolder(v)
    }

/* override fun onViewAttachedToWindow(holder: ViewHolder?) {
    var parent = holder?.recycler?.parent


    val DEBUG_TAG_SCROLL = "DEBUG_TAG_SCROLL"
    Log.d(DEBUG_TAG_SCROLL, "NESTED_SCROLL_VALUE: ${holder?.recycler?.hasNestedScrollingParent()}")



    if (holder?.recycler?.parent is RecyclerView) {
        Log.d(DEBUG_TAG_SCROLL, "Good parent")
    }
    super.onViewAttachedToWindow(holder)
}*/

    override fun getItemCount(): Int {
        return 5
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {

        holder?.bind()
//        val DEBUG_TAG_SCROLL = "DEBUG_TAG_SCROLL"
////        Log.d(DEBUG_TAG_SCROLL, "NESTED_SCROLL_VALUE: ${holder?.recycler?.hasNestedScrollingParent()}")
//
//        if(holder?.recycler?.parent is RecyclerView){
//            Log.d(DEBUG_TAG_SCROLL, "Good parent")
//        }
    }


    inner class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
        var recycler: RecyclerView

        init {
            recycler = v.findViewById(R.id.photo) as RecyclerView
        }

        fun bind() {
            recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
                    Toast.makeText(context, "CHANGED SMALL", Toast.LENGTH_SHORT).show()
                    super.onScrollStateChanged(recyclerView, newState)
                }

//            override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
//                super.onScrolled(recyclerView, dx, dy)
//            }
            })

            val smallRecyclerAdapter = SmallRecyclerAdapter(context)
            recycler.adapter = smallRecyclerAdapter
            recycler.layoutManager = LinearLayoutManager(
                    context, LinearLayoutManager.HORIZONTAL, false
            )
            recycler.scrollToPosition(5)
        }
    }
}

原始的PhotoRecycler(子recyclerView):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/photoView"/>

</LinearLayout>

PhotoRecycler适配器:

class SmallRecyclerAdapter(private val context: MainActivity): RecyclerView.Adapter<SmallRecyclerAdapter.ViewHolder>(){
    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
        val v = LayoutInflater.from(parent?.context)
            .inflate(R.layout.raw_small, parent, false)
        // set the view's size, margins, paddings and layout parameters

        return ViewHolder(v)
    }

    override fun getItemCount(): Int {
        return 10
    }

    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
        //TODO here

        var drawableName="p"+((position%4)+1)
        val drawable =  context.getResources().getDrawable(context.getResources()
            .getIdentifier(drawableName, "drawable", context.getPackageName()))
        holder?.imageView?.setImageDrawable(drawable)
    }


    inner class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
        var imageView: ImageView

        init {
            imageView=v.findViewById(R.id.photoView) as ImageView
        }
    }
}

如果您需要更多详细信息,请告诉我,我会更新。

2 个答案:

答案 0 :(得分:0)

我已经在嵌套的 ScrollView 之前实现了,我认为子级滚动视图总是消耗触摸,而父级滚动视图将永远不会监听

这里是方法的作用 onInterceptTouchEvent,用于控制视图是使用触摸还是将触摸传递给父视图。

所以计划是计算滚动方向,我是否到达子ScrollView的滚动结束。

这段代码是2年前编写的,因此如果不赞成使用,请原谅。

public class CustomScrollView extends ScrollView {

private boolean bottomReached = false;
private boolean topReached = true;
private float startTouch = -1;
private float distance = -1;

public CustomScrollView(Context context) {
    super(context);
}

public CustomScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startTouch = ev.getY();
            break;
        case MotionEvent.ACTION_UP:
            startTouch = -1;
            break;
        case MotionEvent.ACTION_MOVE:
            distance = ev.getY() - startTouch;
                if (Math.abs(distance) < 10) {
                    boolean onIntercept = super.onInterceptTouchEvent(ev);
                    return onIntercept;
                } else {
                    if (!bottomReached && !topReached) {
                        return true;
                    } else {
                        if (distance > 0) {
                            // Scrolling Up
                            return bottomReached;
                        } else {
                            // Scrolling Down
                            return topReached;
                        }
                    }
                }
    }
    return super.onInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startTouch = ev.getY();
            break;
        case MotionEvent.ACTION_UP:


            startTouch = -1;
            break;
        case MotionEvent.ACTION_MOVE:
            distance = ev.getY() - startTouch;
    }
    return super.onTouchEvent(ev);
}
}

答案 1 :(得分:-1)

在GitHub上查看此站点及其代码 Nested Recyclerview