【问题标题】:How To Create a Scroll Back To Top Button with RecyclerView如何使用 RecyclerView 创建滚动返回顶部按钮
【发布时间】:2020-06-19 21:50:51
【问题描述】:

我有一个使用 RecyclerView 显示图像的应用,我想显示一个按钮,让用户在向下滚动时返回顶部

类似这样的:

那我该怎么做呢?

fragment_wallpaper.xml

<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
tools:context=".Fragment.ImagesFragmentProject.WallpapersImagesFragment">

<!-- "descendantFocusability" to make the recyclerView not scrolls to the top itself -->
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="blocksDescendants">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView_image_wallpapers"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorBackground"
        android:nestedScrollingEnabled="false"
        />
</RelativeLayout>

WallpaperFragment.java

public class WallpapersImagesFragment extends Fragment implements Picasso.ItemClickListener {

String[] TopImages;
private Picasso adapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_images_wallpapers, container, false);

    // ArrayList for TopImages
    TopImages = new String[]{
            // 1
            "https://i.ibb.co/GWRmtzt/AL-RZAK-0bb3940f-bd1a-458d-8377-d92fbc7aa7df.jpg",
            // 2
            "https://i.ibb.co/Cb4b46W/Allah-Call-upon-me-b680792f-3870-406c-9430-014fa3ced1f2.jpg",
            // 3
            "https://i.ibb.co/WGY5Rtb/Allah-Muhammad-8ac1439d-6295-4082-9748-1a33b1008424.jpg",
            ..............
    };

    // make new object and find the view "GridView" */
    RecyclerView recyclerView = rootView.findViewById(R.id.recyclerView_image_wallpapers);
    // Calculate the items and auto-fit it on the screen
    int mNoOfColumns = HomeImagesFragment.Utility.calculateNoOfColumns(getActivity(), 140);
    recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), mNoOfColumns));
    adapter = new Picasso(getActivity(), TopImages);
    adapter.setClickListener(this);
    recyclerView.setAdapter(adapter);
    // change the adapter at random every specific time{
    Collections.shuffle(Arrays.asList(TopImages));

    return rootView;
}

@Override
public void onItemClick(View view, int position) {
    // get the image
    String image = TopImages[position];
    Intent intent = new Intent(getActivity(), PicassoDisplayWallpaperImage.class);
    intent.putExtra("imageUrl", image);
    // to not repeat the image when click on it many times
    intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    getActivity().startActivity(intent);
}

// Calculate the items and auto-fit it on the screen
public static class Utility {
    public static int calculateNoOfColumns(Context context, float columnWidthDp) { // For example columnWidthdp=180
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        float screenWidthDp = displayMetrics.widthPixels / displayMetrics.density;
        int noOfColumns = (int) (screenWidthDp / columnWidthDp + 0.5); // +0.5 for correct rounding to int.
        return noOfColumns;
    }
}

【问题讨论】:

    标签: java android androidx


    【解决方案1】:

    您可以将FloatingActionButton 添加到RelativeLayout 作为RecyclerView 的同级,将其位置调整到父级的顶部和中心。

    然后将其 backgroundTint 更改为您的灰色(适用于 API-21),低于 API-21,默认情况下采用 colorAccent

    将 Android 资源中的 ic_baseline_arrow_upward_24.xml 添加到可绘制文件夹中,并在 FAB 的 android:src 属性中使用它。

    要滚动到RecyclerView 的顶部,请使用scrollToPosition()smoothScrollToPosition()

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
    //          recyclerView.scrollToPosition(0);
                recyclerView.smoothScrollToPosition(0);
    
            }
        });
    

    布局:

    <androidx.core.widget.NestedScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        tools:context=".Fragment.ImagesFragmentProject.WallpapersImagesFragment">
    
        <!-- "descendantFocusability" to make the recyclerView not scrolls to the top itself -->
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:descendantFocusability="blocksDescendants">
    
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recyclerView_image_wallpapers"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/colorBackground"
                android:nestedScrollingEnabled="false"/>
    
    
            <com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/fab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:background="#6D353232"
                android:backgroundTint="#6D353232"
                android:visibility="gone"
                android:src="@drawable/ic_baseline_arrow_upward_24"
                app:rippleColor="#6D353232" />
    
        </RelativeLayout>
    
    </androidx.core.widget.NestedScrollView>
    

    您可以通过添加自定义 ReyclerView.OnScrollListener 和覆盖 onScrolled()onScrollStateChanged() 方法来控制隐藏/显示 fab 按钮

            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    
                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
    
                    if (dy > 0) { // scrolling down
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                fab.setVisibility(View.GONE);
                            }
                        }, 2000); // delay of 2 seconds before hiding the fab
    
                    } else if (dy < 0) { // scrolling up
    
                        fab.setVisibility(View.VISIBLE);
                    }
                }
    
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) { // No scrolling 
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                fab.setVisibility(View.GONE);
                            }
                        }, 2000); // delay of 2 seconds before hiding the fab 
                    }
    
                }
            });
    

    这是预览

    【讨论】:

    • 这是一个很好的解释,但我有两个问题,第一个按钮“floatingbutton”随着 RecyclerView 滚动,第二个当我使用显示和隐藏按钮代码时它不起作用。
    • 你好@ededede 感谢您的评论.. 你想让 fab 按钮随着 RecyclerView 滚动而滚动吗? ..对于第二个问题它如何不起作用..是否存在运行时错误或其他问题
    • 在使用片段时,有一个小技巧可以将 FloatingActionButton fab = findViewById(R.id.fab); 更改为 FloatingActionButton fab = rootView.findViewById(R.id.fab);
    • 是的,我知道,但是当我向上滚动时,它没有显示按钮 + 当我在 XML 中删除“可见性”时,按钮会随着整个屏幕滚动,而不是像你看到的那样固定.
    • 能不能把android:descendantFocusability="blocksDescendants"去掉一会儿看看
    【解决方案2】:

    是否需要使用RelativeLayout?使用FrameLayoutConstraintLayoutFloatingActionButton,这似乎很简单:

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:descendantFocusability="blocksDescendants">
    
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/scrollUp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top|center"
            android:src="@drawable/up_arrow" <!--This line is where you set the drawable arrow icon you're using-->
            android:layout_margin="20dp" />
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView_image_wallpapers"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorBackground"
            android:nestedScrollingEnabled="false" />
    </FrameLayout>
    

    RecyclerView 有几个用于滚动的辅助方法和接口,请查看所有这些的文档。你要找的是scrollToPosition

    scrollUp.setOnClickListener(new View.OnClickListener() {
        recyclerView.scrollToPosition(0)
        //Position 0 since you want to scroll to the beginning of your list.
        //Might be size of the data list instead of 0, depending on how you set
        //up your recyclerview adapter
    }
    

    您甚至可以让按钮仅在用户向上滚动后可见,否则使用onScrollListener 将其隐藏。只要在视图上注册滚动更改,侦听器就会触发:

    scrollUp.setVisibility(View.GONE)
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    
        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            //dy is the change in the vertical scroll position
            if(dy > 0){
                //scroll down
                scrollUp.setVisibility(View.GONE)
            }
            else if(dy < 0){
                //scroll up
                scrollUp.setVisibility(View.VISIBLE)
            }
         }
    }
    

    【讨论】:

    • 非常感谢您的解释,但是我有一个问题,按钮“浮动按钮”它只是隐藏,向上或向下滚动时不会出现
    猜你喜欢
    • 2019-06-20
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 2016-03-17
    • 1970-01-01
    • 2023-04-02
    • 2019-02-04
    相关资源
    最近更新 更多