Android自定义RecyclerView实现不固定刻度的刻度尺
程序员文章站
2022-04-09 16:44:33
本文实例为大家分享了自定义recyclerview实现不固定刻度的刻度尺的具体代码,供大家参考,具体内容如下##不均匀刻度效果图##等比例刻度效果图实现功能目前1、实现类似日期/分类等大小不固定的水平...
本文实例为大家分享了自定义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"); } })); }
实现了基本代码全部写了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。