RecyclerView自定义滚动条和样式

最近想给RecyclerView弄一个自定义样式的滚动条,而我在这里使用的是RecyclerView,看了好多网上的自定义滚动条都是用这个控件那个控件的,我这里采用的是自己写的样式,不需要任何控件,主要是通过Translation设置平移动画来实现,废话不多说直接上代码
效果图
在这里插入图片描述
这里用shape写的灰色背景,然后再里面套用一个View也就是图中橙色部分,然后显示了一个滚动条的样式,这里样式有点简陋,如果需要更好看的样式可以自己自定义更好看的样式。
滚动条xml代码

   <FrameLayout
		android:layout_gravity="center"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content">
			<View
				 android:layout_width="102dp"
				 android:layout_height="5dp"
				 android:background="@drawable/horizontal_track"/>
			<View
				 android:id="@+id/main_line"
				 android:layout_width="30dp"
				 android:layout_height="3dp"
				 android:layout_marginLeft="1dp"
				 android:layout_marginRight="1dp"
				 android:background="@drawable/horizontal_thumb"
				 android:layout_gravity="center_vertical"/>
      </FrameLayout>


第一个view为背景用的一个灰色的shape写的xml背景,第二个为橙色滚动条 实现滚动的代码

  float endX = 0;
   	//这里的mRvHx是需要绑定滚动条的RecyclerView
     mRvHx.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
    
                }
    
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
    
                    //整体的总宽度,注意是整体,包括在显示区域之外的。
                    int range = mRvHx.computeHorizontalScrollRange();
                    float density = getScreenDensity();
                    //计算出溢出部分的宽度,即屏幕外剩下的宽度
                    float maxEndX = range + (10 * density) + 5 - ScreenUtils.getScreenWidth(MainActivity.this);
                    //滑动的距离
                    endX += dx;
                    //计算比例
                    float proportion = endX / maxEndX;
    
                    //计算滚动条宽度
                    int transMaxRange = ((ViewGroup) mLine.getParent()).getWidth() - mLine.getWidth();
                    //设置滚动条移动
                    mLine.setTranslationX(transMaxRange * proportion);
                }
    
            });
public float getScreenDensity() {
        WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        if (wm != null) {
            wm.getDefaultDisplay().getMetrics(dm);
        }
        int width = dm.widthPixels;// 屏幕宽度(像素)
        int height = dm.heightPixels; // 屏幕高度(像素)
        float density = dm.density;//屏幕密度(0.75 / 1.0 / 1.5)
        int densityDpi = dm.densityDpi;//屏幕密度dpi(120 / 160 / 240)
        return density;
    }

工具类代码

public class ScreenUtils {

    private ScreenUtils() {
        throw new UnsupportedOperationException("cannot be instantiated");
    }

    /**
     * 获得屏幕宽度
     *
     * @param context
     * @return
     */
    public static int getScreenWidth(Context context) {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.widthPixels;
    }

    /**
     * 获得屏幕高度
     *
     * @param context
     * @return
     */
    public static int getScreenHeight(Context context) {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.heightPixels;
    }

    /**
     * 获得状态栏的高度
     *
     * @param context
     * @return
     */
    public static int getStatusHeight(Context context) {

        int statusHeight = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            int height = Integer.parseInt(clazz.getField("status_bar_height")
                    .get(object).toString());
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;
    }


    //获取虚拟按键的高度
    public static int getNavigationBarHeight(Context context) {
        int result = 0;
        if (hasNavBar(context)) {
            Resources res = context.getResources();
            int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
            if (resourceId > 0) {
                result = res.getDimensionPixelSize(resourceId);
            }
        }
        return result;
    }

    /**
     * 检查是否存在虚拟按键栏
     *
     * @param context
     * @return
     */
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public static boolean hasNavBar(Context context) {
        Resources res = context.getResources();
        int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");
        if (resourceId != 0) {
            boolean hasNav = res.getBoolean(resourceId);
            // check override flag
            String sNavBarOverride = getNavBarOverride();
            if ("1".equals(sNavBarOverride)) {
                hasNav = false;
            } else if ("0".equals(sNavBarOverride)) {
                hasNav = true;
            }
            return hasNav;
        } else { // fallback
            return !ViewConfiguration.get(context).hasPermanentMenuKey();
        }
    }

    /**
     * 判断虚拟按键栏是否重写
     *
     * @return
     */
    private static String getNavBarOverride() {
        String sNavBarOverride = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                Class c = Class.forName("android.os.SystemProperties");
                Method m = c.getDeclaredMethod("get", String.class);
                m.setAccessible(true);
                sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
            } catch (Throwable e) {
            }
        }
        return sNavBarOverride;
    }


    /**
     * 获取当前屏幕截图,包含状态栏
     *
     * @param activity
     * @return
     */
    public static Bitmap snapShotWithStatusBar(Activity activity) {
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        int width = getScreenWidth(activity);
        int height = getScreenHeight(activity);
        Bitmap bp = null;
        bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
        view.destroyDrawingCache();
        return bp;
    }

    /**
     * 获取当前屏幕截图,不包含状态栏
     *
     * @param activity
     * @return
     */
    public static Bitmap snapShotWithoutStatusBar(Activity activity) {
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        Rect frame = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;

        int width = getScreenWidth(activity);
        int height = getScreenHeight(activity);
        Bitmap bp = null;
        bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
                - statusBarHeight);
        view.destroyDrawingCache();
        return bp;

    }

}

需要注意的是这里的mRvHx是你需要设置自定义滚动条的RecyclerView,当你这里监听RecyclerView滚动时你自定义的这个view也会根据rv自动滚动,你可以随意将滚动条设置为横向还是纵向,如果是纵向只需要修改一下动画的平移方向即可,即将setTranslationX改成setTranslationY,另外再调试一下看看是否运动方向反了,如有疑问欢迎评论和反馈,谢谢大家

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
要实现 RecyclerView 滚动条高度自定义,你可以考虑使用一个自定义滚动条 View,然后通过监听 RecyclerView 的滚动事件来控制滚动条的位置和高度。 首先,你需要在 RecyclerView 的布局文件中添加一个自定义滚动条 View,例如: ```xml <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.example.customscrollbar.CustomScrollBar android:id="@+id/custom_scroll_bar" android:layout_width="10dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:layout_marginRight="10dp" /> </RelativeLayout> ``` 其中,CustomScrollBar 是自定义滚动条 View,它的宽度可以根据需求自行设置。 然后,在 RecyclerView 的代码中,你需要监听 RecyclerView 的滚动事件,计算滚动条的位置和高度,然后更新 CustomScrollBar 的位置和高度。例如: ```java recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // 计算当前可见的 item 数量 int visibleItemCount = recyclerView.getLayoutManager().getChildCount(); // 计算所有 item 的数量 int totalItemCount = recyclerView.getLayoutManager().getItemCount(); // 计算第一个可见的 item 的位置 int firstVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); // 计算滚动条的高度 int scrollBarHeight = (int) ((float) visibleItemCount / (float) totalItemCount * recyclerView.getHeight()); // 计算滚动条的位置 int scrollBarTop = (int) ((float) firstVisibleItemPosition / (float) totalItemCount * recyclerView.getHeight()); // 更新滚动条的位置和高度 customScrollBar.setScrollBarTop(scrollBarTop); customScrollBar.setScrollBarHeight(scrollBarHeight); } }); ``` 在这段代码中,我们使用了 RecyclerView 的 LayoutManager 中的方法来计算当前可见的 item 数量、所有 item 的数量和第一个可见的 item 的位置,然后根据这些数据计算出滚动条的位置和高度,最后更新 CustomScrollBar 的位置和高度。 最后,你需要在 CustomScrollBar 中实现 setScrollBarTop() 和 setScrollBarHeight() 方法,用于设置滚动条的位置和高度。例如: ```java public void setScrollBarTop(int top) { setY(top); } public void setScrollBarHeight(int height) { getLayoutParams().height = height; requestLayout(); } ``` 这样,你就可以实现 RecyclerView 滚动条高度自定义的效果了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值