Android中自定义RecyclerView如何实现不固定刻度的刻度尺

发布时间:2020-07-17 16:50:28

来源:亿速云

阅读:116

作者:小猪

这篇文章主要讲解了Android中自定义RecyclerView如何实现不固定刻度的刻度尺,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。

本文实例为大家分享了自定义RecyclerView实现不固定刻度的刻度尺的具体代码,供大家参考,具体内容如下

##不均匀刻度效果图

##等比例刻度效果图

实现功能目前

1、实现类似日期/分类等大小不固定的水平刻度尺效果

2、实现标准刻度尺效果

3、监听RecyclerView滑动时居中条目

4、去掉边缘阴影

定义RecyclerView

public class CenterRecyclerView extends RecyclerView {

//设置RecyclerView的速度

private static final int MAXIMUM_FLING_VELOCITY = 3000;

//画中轴线

private Paint mCenterLinePaint;

private Context context;

private CenterLayoutManager mLayoutManager;

private Paint mTextPaint;

private String text = "";

private String textUnit = "";

private Paint mTextUnitPaint;

private int mWidth;

private int mHeight;

private int mLineStartY;

private int mLineEndY;

private int mTextStartY;

public CenterRecyclerView(@NonNull Context context) {

this(context, null);

}

public CenterRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {

this(context, attrs, -1);

}

public CenterRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context, attrs);

}

private void init(Context context, AttributeSet attrs) {

this.context = context;

initPaint();

}

public void setTypeface(Typeface typeface) {

mTextPaint.setTypeface(typeface);

mTextUnitPaint.setTypeface(typeface);

}

private void initPaint() {

mCenterLinePaint = new Paint();

mCenterLinePaint.setAntiAlias(true);

mCenterLinePaint.setStrokeWidth(ScreenUtil.dip2px(context, 4));

mCenterLinePaint.setTextAlign(Paint.Align.CENTER);

mCenterLinePaint.setColor(0xff6e9fff);

mTextUnitPaint = new Paint();

mTextUnitPaint.setStyle(Paint.Style.FILL);

mTextUnitPaint.setStrokeWidth(ScreenUtil.dip2px(context, 4));

mTextUnitPaint.setTextSize(ScreenUtil.dip2px(context, 15));

mTextUnitPaint.setColor(Color.parseColor("#DD5F00"));

mTextPaint = new Paint();

mTextPaint.setStyle(Paint.Style.FILL);

mTextPaint.setStrokeWidth(ScreenUtil.dip2px(context, 4));

mTextPaint.setTextSize(ScreenUtil.dip2px(context, 60));

mTextPaint.setColor(Color.parseColor("#DD5F00"));

mTextPaint.setTextAlign(Paint.Align.CENTER);

}

@Override

public void addOnScrollListener(@NonNull OnScrollListener listener) {

super.addOnScrollListener(listener);

postInvalidate();

}

@Override

protected void onMeasure(int widthSpec, int heightSpec) {

super.onMeasure(widthSpec, heightSpec);

}

//获取相关参数

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

super.onLayout(changed, l, t, r, b);

mWidth = getWidth();

mHeight = getHeight();

int lineHeight = ScreenUtil.dip2px(context, 58);

mLineStartY = mHeight / 2 - lineHeight / 2;

mLineEndY = mHeight / 2 + lineHeight / 2;

mTextStartY = mHeight / 2 - ScreenUtil.dip2px(context, 55);

}

@Override

public void draw(Canvas c) {

super.draw(c);

Log.d("szjjyh", "draw: " + getWidth());

drawCenterLine(c);

drawText(c);

}

//画线

private void drawCenterLine(Canvas canvas) {

canvas.drawLine(mWidth / 2, mLineStartY, mWidth / 2, mLineEndY, mCenterLinePaint);

}

//画字/画单位

private void drawText(Canvas c) {

c.drawText(text, mWidth / 2, mTextStartY, mTextPaint);

if (textUnit != null && textUnit.length() != 0) {

float textWidth = mTextPaint.measureText(text);

c.drawText(textUnit, (mWidth + textWidth) / 2, mTextStartY, mTextUnitPaint);

}

}

public String getText() {

return text;

}

public void setText(String text) {

if (text == null) {

return;

}

this.text = text;

}

public String getTextUnit() {

return textUnit;

}

public void setTextUnit(String textUnit) {

if (textUnit == null) {

return;

}

this.textUnit = textUnit;

}

@Override

public void setAdapter(@Nullable Adapter adapter) {

super.setAdapter(adapter);

}

@Override

public void setLayoutManager(@Nullable LayoutManager layout) {

super.setLayoutManager(layout);

mLayoutManager = (CenterLayoutManager) layout;

}

@Override

public boolean fling(int velocityX, int velocityY) {

velocityX = solveVelocity(velocityX);

velocityY = solveVelocity(velocityY);

return super.fling(velocityX, velocityY);

}

private int solveVelocity(int velocity) {

if (velocity > 0) {

return Math.min(velocity, MAXIMUM_FLING_VELOCITY);

} else {

return Math.max(velocity, -MAXIMUM_FLING_VELOCITY);

}

}

// @Override

// protected float getLeftFadingEdgeStrength() {

// return 0;

// }

}

定义LinearLayoutManager

public class CenterLayoutManager extends LinearLayoutManager {

public CenterLayoutManager(Context context) {

super(context);

}

public CenterLayoutManager(Context context, int orientation, boolean reverseLayout) {

super(context, orientation, reverseLayout);

}

public CenterLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

}

//计算偏移量自己适配

@Override

public void scrollToPosition(int position) {

scrollToPositionWithOffset(position,-15);

}

@Override

public void scrollToPositionWithOffset(int position, int offset) {

super.scrollToPositionWithOffset(position, offset);

}

@Override

public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {

RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());

smoothScroller.setTargetPosition(position);

startSmoothScroll(smoothScroller);

}

public void smoothScrollToPosition(RecyclerView recyclerView, int position) {

RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());

smoothScroller.setTargetPosition(position);

startSmoothScroll(smoothScroller);

}

private static class CenterSmoothScroller extends LinearSmoothScroller {

CenterSmoothScroller(Context context) {

super(context);

}

//滑动到中间位置

@Override

public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {

return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);

}

//滚动速度设置

@Override

protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {

return 4;

}

@Override

protected int getVerticalSnapPreference() {

return super.getVerticalSnapPreference();

}

}

}

滑动事件监听

public class CenterScrollListener extends RecyclerView.OnScrollListener {

private CenterLayoutManager mLayoutManager;

RecyclerView recyclerView;

private int mPosition;

private double intScrollState;

private int mFirstItemPosition1;

private int mLastItemPosition1;

private boolean is_Stop;

private String TAG = "CenterScrollListener";

private double is_playSound;

public CenterScrollListener(OnItemCenterScrollistner onItemCenterScrollistner) {

this.onItemCenterScrollistner = onItemCenterScrollistner;

}

public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {

init(recyclerView);

intScrollState = newState;

is_Stop = false;

if (intScrollState == RecyclerView.SCROLL_STATE_IDLE) {

Log.e(TAG, "onScrollStateChanged: 11111:"+mPosition);

CeterScroll(0, mPosition);

}

}

public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {

init(recyclerView);

int x = Math.abs(dx);

if (!is_Stop && x <= 1) {

is_Stop = true;

if (dx >= 0) {

mPosition = (mFirstItemPosition1 + mLastItemPosition1) / 2;

View childAt = mLayoutManager.findViewByPosition(mPosition);

if (childAt.getLeft() < ScreenUtil.getScreenWidth(recyclerView.getContext()) / 2) {

mPosition = mPosition + 1;

}

Log.e(TAG, "111111: w:" + childAt.getWidth() + " :l:" +

childAt.getLeft() + " :r:" + childAt.getRight());

} else {

mPosition = (mFirstItemPosition1 + mLastItemPosition1) / 2;

View childAt = mLayoutManager.findViewByPosition(mPosition);

if (childAt.getLeft() > ScreenUtil.getScreenWidth(recyclerView.getContext()) / 2) {

mPosition = mPosition - 1;

}

}

}

CeterScroll(x, mPosition);

}

//事件监听

private void init(@NonNull RecyclerView recyclerView) {

this.recyclerView = recyclerView;

if (mLayoutManager == null) {

mLayoutManager = (CenterLayoutManager) recyclerView.getLayoutManager();

}

int firstItemPosition = mLayoutManager.findFirstVisibleItemPosition();

int lastItemPosition = mLayoutManager.findLastVisibleItemPosition();

mFirstItemPosition1 = mLayoutManager.findFirstCompletelyVisibleItemPosition();

mLastItemPosition1 = mLayoutManager.findLastCompletelyVisibleItemPosition();

mPosition = (mFirstItemPosition1 + mLastItemPosition1) / 2;

if (is_playSound != mPosition) {

is_playSound = mPosition;

int count = mLayoutManager.getItemCount();

// soundpool.play(soundmap.get(1), 1, 1, 0, 0, 1);

if (onItemCenterScrollistner != null) {

//中间条目事件监听

onItemCenterScrollistner.onItemCenterScrollistner(mLastItemPosition1, mPosition,count);

}

}

//目前由于要实现灰色条目当条目间距为10dp,屏幕宽度360时不能继续滑动

if (mPosition <= 18) {

CeterScroll(0, 18);

}

}

//速度变小时自动滚动到中间位置

private void CeterScroll(int dx, int position) {

if ((intScrollState == RecyclerView.SCROLL_STATE_SETTLING || intScrollState

== RecyclerView.SCROLL_STATE_IDLE) && Math.abs(dx) <= 1) {

mLayoutManager.smoothScrollToPosition(recyclerView, position);

}

}

OnItemCenterScrollistner onItemCenterScrollistner;

public void setOnItemCenterScrollistner(OnItemCenterScrollistner onItemCenterScrollistner) {

this.onItemCenterScrollistner = onItemCenterScrollistner;

}

public interface OnItemCenterScrollistner {

void onItemCenterScrollistner(int lastItemPosition1, int position, int count);

}

adpater实现

public class DateAdapter extends BaseRecyclerAdapter {

private static final int layoutId = R.layout.view_item_date;

public DateAdapter(Context context, List datas) {

super(context, datas, layoutId);

}

@Override

protected void bindData(BaseViewHolder holder, CalendarDateBean data, int position) {

if (data.getDay() == 1) {

//R.id.tv_1为线需要居中否则和中轴线不会完全对称 R.id.tv_2为大刻度文字

holder.getView(R.id.tv_1).setScaleX(2F);

holder.setText(R.id.tv_2, data.getMonth() + "月");

holder.getView(R.id.tv_2).setVisibility(View.VISIBLE);

holder.getView(R.id.tv_1).setBackgroundColor(Color.parseColor("#ffffff"));

} else if (data.getDay() ==-1){

holder.getView(R.id.tv_1).setScaleX(1F);

holder.getView(R.id.tv_2).setVisibility(View.GONE);

holder.getView(R.id.tv_1).setBackgroundColor(Color.parseColor("#222222"));

}else {

holder.getView(R.id.tv_1).setScaleX(1F);

holder.getView(R.id.tv_2).setVisibility(View.GONE);

holder.getView(R.id.tv_1).setBackgroundColor(Color.parseColor("#ffffff"));

}

}

}

activity 加载view展示

private void initRecyclerView() {

//此处试配时注意item10dp 宽度360 计算发放 360/10/2得到记得适配

for (int i = 0; i < 18; i++) {

TimeBean timeBean = new TimeBean();

mList.add(timeBean);

}

for (int i = 0; i < 1440; i++) {

int minute = i % 60;

int hour = i / 60;

if (CalendarUtil.getHourTime()==hour&&CalendarUtil.getMinuteTime()==minute){

mPostion = i;

}

TimeBean timeBean = new TimeBean();

timeBean.setHour(hour);

timeBean.setMinute(minute);

timeBean.setTimeDate(CalendarUtil.getHourToMinute(hour,minute));

mList.add(timeBean);

}

for (int i = 0; i < 18; i++) {

TimeBean timeBean = new TimeBean();

// timeBean.setMinute(-1);

mList.add(timeBean);

}

rv_data = findViewById(R.id.rv_data);

mAdapter = new TimeAdapter(this, mList);

rv_data.setAdapter(mAdapter);

//设置字体

rv_data.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/dincond_boldalternate.ttf"));

CenterLayoutManager layoutManager = new CenterLayoutManager(this);

layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

rv_data.setLayoutManager(layoutManager);

rv_data.scrollToPosition(mPostion);

rv_data.addOnScrollListener(new CenterScrollListener((lastItemPosition, position,count) -> {

//更新文本和单位

rv_data.setText(mList.get(position).getTimeDate());

if (mList.get(position).getHour()>12){

rv_data.setTextUnit("PM");

}else {

rv_data.setTextUnit("AM");

}

}));

}

看完上述内容,是不是对Android中自定义RecyclerView如何实现不固定刻度的刻度尺有进一步的了解,如果还想学习更多内容,欢迎关注亿速云行业资讯频道。

android自定义起止时间的时间刻度尺,Android中自定义RecyclerView如何实现不固定刻度的刻度尺...相关推荐

  1. 自定义RecyclerView实现不固定刻度的刻度尺

    ##不均匀刻度效果图 ##等比例刻度效果图 实现功能目前 1.实现类似日期/分类等大小不固定的水平刻度尺效果 2.实现标准刻度尺效果 3.监听RecyclerView滑动时居中条目 4.去掉边缘阴影 ...

  2. php自定义函数全局声明,【phpcms-v9】phpcms-v9中自定义全局函数文件:extention.func.php...

    /** * extention.func.php 用户自定义函数库 * * @copyright(C) 2005-2010 PHPCMS * @licensehttp://www.phpcms.cn/ ...

  3. vue2、vue3中自定义v-model的使用和区别

    在我们的日常开发中,时常需要写一些自定义组件,而其中可能就会使用到v-model,v-model是Vue中的一个指令,用来实现数据的双向绑定,实现数据.视图更新,v-model是一个语法糖,,我们可以 ...

  4. VC中自定义IE浏览器

    VC中自定义IE浏览器 http://www.5xsoft.com/Article.aspx?id=155 本教程提供了自定义浏览器控件的行为和外观的一些方法.你将看到高级的宿主接口, IDocHos ...

  5. android自定义起止时间的时间刻度尺,Android 自定义View篇(六)实现时钟表盘效果...

    前言 Android 自定义 View 是高级进阶不可或缺的内容,日常工作中,经常会遇到产品.UI 设计出花里胡哨的界面.当系统自带的控件不能满足开发需求时,就只能自己动手撸一个效果. 本文就带自定义 ...

  6. Android 自定义带图标Toast,工具方法,Toast自定义显示时间

    带图标Toast工具方法1 样式 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:an ...

  7. Android 系统(201)---Android 自定义View实战系列 :时间轴

    Android 自定义View实战系列 :时间轴 Android开发中,时间轴的 UI需求非常常见,如下图: 本文将结合 自定义View & RecyclerView的知识,手把手教你实现该常 ...

  8. 可以缩放平移的时间刻度尺,方便自定义UI需求。仿萤石云历史录像时间轴

    https://github.com/Liberations/TimeRuler TimeRuler [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijjdgeFo-1 ...

  9. Android 节操视频播放器jiecaovideoplayer自定义播放音频使用:屏蔽全屏按钮,增加倒计时,当前时间/总时间

    一.屏蔽全屏按钮 找到JCVideoPlayerStandard.java文件中的代码: private void fixAudio() {if (SrcType.equalsIgnoreCase(& ...

最新文章

  1. MySQL性能优化之参数配置
  2. python解析xml文件选用模块_python-minidom模块【解析xml】
  3. 独立思考者模型:寻找潜藏在表象背后的真相 探寻真相的方法
  4. 大道至简阅读笔记01
  5. SAP 电商云 Spartacus UI Angular Component 动态创建的单步调试
  6. python vtk_VTK在python环境下的安装和调用
  7. 20155209 2016-2017-2 《Java程序设计》第五周学习总结
  8. 设计模式18_责任链
  9. kubernetes--pod的生命周期管理(PostStart,PreStop)
  10. java文件传输加密_java程序对于文件的加密和解密
  11. 010Editor逆向分析
  12. 致我们终将远离的子女
  13. 嵌入式系统概论-考试总结
  14. 5v供电的数字功放芯片有哪些
  15. photoshop基本的操作
  16. 计算机excel没点保存,【2人回答】电脑突然断电,EXCEL没保存怎么找回已录入的资料?-3D溜溜网...
  17. JVM-调优《常见可视化工具与命令行的使用》
  18. 日语学习的在线资料,朋友推荐,拿来分享
  19. hautoj1262: 魔法宝石
  20. mysql utf8mb4 bin_Mysql的utf8与utf8mb4区别,utf8mb4_bin、utf8mb4_general_ci与utf8mb4_unicode_ci的选择...

热门文章

  1. 常用系统变量 SY-*
  2. 微信小程序 js中遍历list
  3. Java中IO流(3).
  4. 时隔27年,微软IE浏览器正式退出历史舞台,一个时代的结束
  5. pycharm远程连接服务器问题Uploading PyCharm helpers Python Interpreter... Python helpers are not copied yet
  6. webSocket配置wss访问
  7. cppcheck代码检查工具安装与使用技巧
  8. 亚马逊将推出VR购物应用,支持Vive Rift PSVR三大平台
  9. PC实现Win10/原生安卓双系统
  10. 【leetcode】二维子矩阵的和