前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android自定义RecyclerView实现不固定刻度的刻度尺

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

作者头像
砸漏
发布2020-10-16 11:50:20
1.6K0
发布2020-10-16 11:50:20
举报
文章被收录于专栏:恩蓝脚本恩蓝脚本

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

##不均匀刻度效果图

##等比例刻度效果图

实现功能目前

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

定义RecyclerView

代码语言:javascript
复制
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

代码语言:javascript
复制
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();
}
}
}

滑动事件监听

代码语言:javascript
复制
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实现

代码语言:javascript
复制
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展示

代码语言:javascript
复制
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");
}
}));
}

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档