固定高度的嵌套垂直 RecycleView(滚动问题)

Nested Vertical RecycleView of fixed height (Scroll issue)

我设计了这个布局布局,其中我有一个 NestdScrollView,其中包含 3 个 RecycleViews。在每个 RecycleView 项目上单击会出现另一个 NestedRecycleView 出现在 ScrollView 高度 200dp 内。 NestedRecycleView 滚动不起作用。图像中有超过 4 个 "list items" 但只显示了 4 个,它不可滚动。当我滚动父 NestdScrollView 滚动时。

Someone commented about this being bad design, if anyone has a idea how to approach this kindly share your ideas also.

RecycleView 适配器

  public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

        private List<String> mData;
        private LayoutInflater mInflater;
        private ItemClickListener mClickListener;
        private Context context;

        // data is passed into the constructor
        MyRecyclerViewAdapter(Context context, List<String> data) {
            this.mInflater = LayoutInflater.from(context);
            this.mData = data;
            this.context=context;
        }

        // inflates the row layout from xml when needed
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = mInflater.inflate(R.layout.list_item_text, parent, false);
            return new ViewHolder(view);
        }

        // binds the data to the TextView in each row
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            String animal = mData.get(position);
            holder.myTextView.setText(animal);
        }

        // total number of rows
        @Override
        public int getItemCount() {
            return mData.size();
        }


        // stores and recycles views as they are scrolled off screen
        public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
            TextView myTextView;
            RecyclerView recyclerViewNested;
            ScrollView nestedScrollViewRecycleView;

            ViewHolder(View itemView) {
                super(itemView);
                myTextView = itemView.findViewById(R.id.text_view);
                recyclerViewNested = itemView.findViewById(R.id.recycle_view_nested);
                nestedScrollViewRecycleView= itemView.findViewById(R.id.nested_scrollview_in_recycleview);
                myTextView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        ArrayList<String> list12 = new ArrayList<String>(
                                Arrays.asList("list item", "list item", "list item","list item","list item", "list item", "list item","list item","list item", "list item", "list item","list item","list item", "list item", "list item","list item","list item", "list item", "list item","list item"));
                        nestedScrollViewRecycleView.setVisibility(View.VISIBLE);

                        MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(context, list12);
                        LinearLayoutManager layoutManager = new LinearLayoutManager(context, recyclerViewNested.VERTICAL, false);
                        recyclerViewNested.setLayoutManager(layoutManager);
                        recyclerViewNested.setAdapter(adapter);


                    }
                });
                //itemView.setOnClickListener(this);
            }

            @Override
            public void onClick(View view) {
                if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
            }
        }

        // convenience method for getting data at click position
        String getItem(int id) {
            return mData.get(id);
        }

        // allows clicks events to be caught
        void setClickListener(ItemClickListener itemClickListener) {
            this.mClickListener = itemClickListener;
        }

        // parent activity will implement this method to respond to click events
        public interface ItemClickListener {
            void onItemClick(View view, int position);
        }
    }

MainActivity

public class MainActivity extends AppCompatActivity {

    public static final int SWIPE_THRESHOLD = 100;
    public static final int SWIPE_VELOCITY_THRESHOLD = 100;
    private static final String TAG = "MainActivity";

    ArrayList<String> list2;
    NestedScrollView NestedScroll1;
    ConstraintLayout constraintLayout;
    RecyclerView recyclerView1;
    //vars

 private boolean mSwiping = false;
    private float mDownX = 0;
    private float xCoOrdinate;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView1 = findViewById(R.id.firstColumn);
        RecyclerView recyclerView2 = findViewById(R.id.secondColumn);
        RecyclerView recyclerView3 = findViewById(R.id.thirdColumn);
        NestedScroll1 = findViewById(R.id.scrollview_nested);

        ArrayList<String> list12 = new ArrayList<String>(
                Arrays.asList("A", "column1", "test1", "1", "2", "3", "1", "2", "3", "1", "2", "3", "1", "2", "3", "1", "2", "3", "2", "3", "1", "2", "3", "1", "2", "3", "1", "2", "3", "1", "2", "3"));
        list2 = new ArrayList<String>(
                Arrays.asList("B", "column3", "test3", "111", "211", "311", "111", "211", "311", "111", "211", "311", "111", "211", "311", "111", "211", "311", "311", "111", "211", "311", "111", "211", "311", "111", "211", "311"));


        // set up the RecyclerView
        MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(this, list12);

        configRecyclerView(recyclerView1, adapter);
        configRecyclerView(recyclerView2, adapter);
        configRecyclerView(recyclerView3, adapter);


    recyclerView2.addOnItemTouchListener(getOnItemTouchListener());
    recyclerView3.addOnItemTouchListener(getOnItemTouchListener());

    }

    private void configRecyclerView(RecyclerView recyclerView, MyRecyclerViewAdapter adapter) {
        LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(), recyclerView.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);
    }



private RecyclerView.OnItemTouchListener getOnItemTouchListener() {
        return new RecyclerView.OnItemTouchListener() {
            @SuppressLint("LongLogTag")
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) {
                Log.d("TableView OnswipeTouchListener: ", " recycleViewOdds item onInterceptTouchEvent");

                switch (ev.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        mDownX = ev.getX();
                        mSwiping = false;

                        //coordinate for moving
                        xCoOrdinate = constraintLayout.getX() - ev.getRawX();

                        break;
                    case MotionEvent.ACTION_CANCEL:
                        //return true;
                    case MotionEvent.ACTION_UP:
                        if (mSwiping) {

                            /// this return true block touch event
                            Log.d("TableView OnswipeTouchListener:", "Recycle view odds OnItemTouchListener: you swiped!");
                            return true;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        float xMove = ev.getX();
                        float xDelta = Math.abs(xMove - mDownX);

                        if (xDelta > 5) {
                            mSwiping = true;
                            // this one also
                            return true;
                        }
                        break;
                }

                return false;
            }

            private Rect rect;

            @SuppressLint("LongLogTag")
            @Override
            public void onTouchEvent(RecyclerView rv, MotionEvent event) {

                int limitLeft = constraintLayout.getLeft();
                int limitRight = constraintLayout.getRight();


                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:

                        break;
                    case MotionEvent.ACTION_MOVE:
                        //   Log.d("OnSwipeTouchListener Class", "recycleViewOdds action move");

                        //Restrict move to constraintLayout width
                        // Log.d("Recycleview TouchListener windowwidth: ", limitLeft + ", " + limitRight);

                        float range = event.getRawX() + xCoOrdinate;

                        if (Math.abs(range) > limitLeft - 350 && Math.abs(range) < limitRight - 250) {
                            //constraintLayout.scrollTo((int) (event.getRawX() + xCoOrdinate),0);
                            constraintLayout.animate().x(event.getRawX() + xCoOrdinate).setDuration(0).start();
                            constraintLayout.setAlpha(0.7f);
                        }

                        break;
                    case MotionEvent.ACTION_UP:
                        Log.d("TableView OnswipeTouchListener:", "recycleViewOdds action up");
                        constraintLayout.animate().alpha(1).translationX(0).translationY(0);

                        break;

                    case MotionEvent.ACTION_CANCEL:
                        constraintLayout.animate().alpha(1).translationX(0).translationY(0);

                        Log.d("TableView OnswipeTouchListener:", "recycleViewOdds action cancel");
                        break;
                }
            }


            @SuppressLint("LongLogTag")
            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
                Log.e("TableView OnswipeTouchListener:", "recycleViewOdds item touch intercept disallow request");

            }
        };
    }

}

activity_main.xml

<androidx.core.widget.NestedScrollView
    android:id="@+id/scrollview_nested"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:text="Hello World!"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/firstColumn"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_centerHorizontal="true"
            android:nestedScrollingEnabled="false"
            app:layout_constraintEnd_toStartOf="@id/secondColumn"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />


        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/secondColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            app:layout_constraintEnd_toStartOf="@id/thirdColumn"
            app:layout_constraintLeft_toRightOf="@id/firstColumn"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/thirdColumn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintLeft_toRightOf="@id/secondColumn"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

list_item_text.xml

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

    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:layout_marginBottom="8dp"/>
    <ScrollView
        android:id="@+id/nested_scrollview_in_recycleview"
        android:layout_width="match_parent"
        android:visibility="gone"
        android:background="@color/colorAccent"
        android:layout_height="200dp">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycle_view_nested"
            android:layout_width="match_parent"
            android:nestedScrollingEnabled="false"
            android:layout_height="wrap_content"/>

    </ScrollView>

</LinearLayout>

我的建议是 "list_item_text",在这个里面,你封装了一个滚动视图和回收器视图,我假设这些项目的数量会非常少,大约 5-10 个,并且大部分会在屏幕,所以不会有任何性能问题如果我们通过迭代循环直接在父布局中动态添加 LinearLayout,这种方法的唯一缺点是屏幕外的视图将被加载到内存中(这不在回收站视图中),但考虑到您的项目数量,这是可以接受的,您的大部分项目将在屏幕上可见,并且显然这将节省 Recyclerview 填充、渲染等的额外开销。希望它能解决你的触摸问题。

recyclerView.setNestedScrollingEnabled(false); 添加到所有 RecyclerView 并检查是否解决了滚动问题。

activity_main.xml
请在所有 RecyclerView 标签中添加 android:nestedScrollingEnabled="true"...


list_item_text.xml
请在 ScrollView Tag
中添加 android:fillViewport="true" 然后在 RecyclerView 标签中将 android:layout_height="wrap_content" 更改为 android:layout_height="0dp"...