首页 > 解决方案 > 在 RecyclerView 的滚动上滚动 ImageView

问题描述

我的要求是ImageViewRecyclerview. 当Recyclerview向上滚动时,ImageView将向右移动,直到列表到达末尾,反之亦然。

我已经尝试过,但面对的复杂性很少,任何建议和参考都会非常有帮助。或者任何逻辑也将不胜感激。

我现在面临的问题是无法处理addOnScrollListener中的值

在 github 中分享我的代码:Github Link

MainActivity 代码: 分享几行代码:

 public class MainActivity extends AppCompatActivity implements View.OnClickListener, ClickEventLisener {

        HorizontalScrollView v_scroll;
        Button btn_left, btn_right;
        int pos = 0;
        int temppos = 0;
        int initialpos = 0;
        RecyclerView rv_recycler;
        UserApapter adapter;
        List<Users> user = new ArrayList<>();
        Context mContext;
        boolean isFirsttime = true;
        ImageView iv_image;
        String imageurl = "https://www.isometrix.com/wp-content/uploads/2017/03/featured-images-about.jpg";
        int screenwidth = 0, imagewidth = 0;
        int scroolby_val = 0;

        @SuppressLint("ClickableViewAccessibility")
        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mContext = this;

            iv_image = findViewById(R.id.iv_image);
            v_scroll = findViewById(R.id.v_scroll);
            btn_left = findViewById(R.id.btn_left);
            btn_right = findViewById(R.id.btn_right);
            rv_recycler = findViewById(R.id.rv_recycler);
            btn_left.setOnClickListener(this);
            btn_right.setOnClickListener(this);

            v_scroll.setOnTouchListener(new View.OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    return true;
                }
            });

            filllist();
            getScreenSize();
            setupimage();
            getleftscroll();
            // when scrolled to the leftmost position the variables are initialized
            v_scroll.setOnScrollChangeListener(new View.OnScrollChangeListener() {

                @Override
                public void onScrollChange(View view, int i, int i1, int i2, int i3) {
                    initialpos = i;
                    if (i == 0) {
                        temppos = 0;
                    } else {
                    }
                }
            });

            ///not able to understand how to handle the values
            //handling the scroll
            rv_recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    getleftscroll();
                    if (dy > 0) {
                        temppos = temppos + scroolby_val;
                        v_scroll.scrollTo(temppos, 0);
                        Log.d("Scroll", "ScrollUp");
                        Log.d("temppos", "" + temppos);
                    } else {
                        if (initialpos != 0) {
                            temppos = temppos - scroolby_val;
                            v_scroll.scrollTo(temppos, 0);
                            Log.d("temppos1", "" + temppos);
                            Log.d("Scroll", "ScrollDown");
                        }
                    }
                }

                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);

                    if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
                        // Do something
                    } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                        // Do something
                    } else {
                        // Do something
                    }
                }
            });


        }

        private void getScreenSize() {
            DisplayMetrics displayMetrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
            int height = displayMetrics.heightPixels;
            int width = displayMetrics.widthPixels;
            Log.d("ScreenWidth", "" + width);
            screenwidth = width;
        }

        private void setupimage() {
            Glide.with(mContext)
                    .asBitmap()
                    .load(imageurl)
                    .into(new SimpleTarget<Bitmap>() {
                        @Override
                        public void onResourceReady(Bitmap bitmap, Transition<? super Bitmap> transition) {
                            int w = bitmap.getWidth();
                            int h = bitmap.getHeight();
                            Log.d("ImageWitdh", "" + w);
                            iv_image.setImageBitmap(bitmap);
                            imagewidth = w;
                        }
                    });


        }

/*
    Logic I have implemented:calculated Imagewidth and screenwidth. Then minus it (imagewidth > screenwidth) and then divide it by the number of values in the array.
    if the value is 0 then scrolling it by 1 per scroll or if the returned value is 3 then scrolling it by 3. 
    IOS team have done this way and working good for them but I am facing a minor issue here.
*/
        private void getleftscroll() {
            imagewidth = 2000;
            if (imagewidth > screenwidth) {
                int leftoutscreen = imagewidth - screenwidth;
                scroolby_val = leftoutscreen / user.size();
                if (scroolby_val == 0) {
                    scroolby_val = 1;
                }
                // temppos = 0;
                Log.d("scroolby_val", "" + scroolby_val);
            }

        }


        ///button is just for demo purpose///
        @Override
        public void onClick(View v) {
            if (v == btn_left) {
                if (initialpos != 0) {
                    temppos = temppos - pos--;
                    v_scroll.scrollTo(temppos, 0);
                    Log.d("temppos", "" + temppos);
                }
            } else if (v == btn_right) {
                temppos = temppos + pos++;
                v_scroll.scrollTo(temppos, -temppos);
                Log.d("temppos", "" + temppos);
            }
        }


        private void filllist() {
            user.clear();
            for (int i = 0; i <= 300; i++) {
                user.add(new Users(String.valueOf(i + 1), "name " + i));
            }
            inflateadapter();
        }

        private void inflateadapter() {
            RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
            adapter = new UserApapter(this, R.layout.row_users, user, this);
            rv_recycler.setLayoutManager(mLayoutManager);
            rv_recycler.setAdapter(adapter);
        }


        @Override
        public void Currentposition(int position) {
            Log.d("Currentposition", "" + position);
            if (position == user.size() - 1) {
                if (scroolby_val == 1) {
                    Log.d("scroolby_val", "" + scroolby_val);
                    Log.d("Inside", "Inside");
                    // v_scroll.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
                    // temppos = 1;
                }
            } else if (position == 0) {
                temppos = 0;
            }
            pos = position;
        }

        @Override
        public void ClickEventLisener(View view, int position) {
            Toast.makeText(mContext, "" + position, Toast.LENGTH_SHORT).show();
        }
    }

标签: androidimageandroid-recyclerviewscrollview

解决方案


您可能需要考虑的几件事-

  1. 不要直接使用 onScrolled 回调中的 dy 值来设置 v_scroll 的滚动。应该有一个逻辑将回收器视图的滚动状态映射到 v_scroll 中所需的滚动。

  2. 根本不要使用 dy。设置 v_scroll 滚动的逻辑应基于列表中的项目数以及其中的第一个/最后一个可见子项。(RecyclerView 提供了获取它的方法。)您可以从 onScrolled 回调运行该逻辑。


推荐阅读