欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-07-06 16:14:48
本文实例为大家分享了自定义recyclerview实现不固定刻度的刻度尺的具体代码,供大家参考,具体内容如下##不均匀刻度效果图##等比例刻度效果图实现功能目前1、实现类似日期/分类等大小不固定的水平...

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

##不均匀刻度效果图

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

##等比例刻度效果图

Android自定义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<calendardatebean> {

 private static final int layoutid = r.layout.view_item_date;

 public dateadapter(context context, list<calendardatebean> 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");
   }
  }));

 }

实现了基本代码全部写了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。