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<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");

}

}));

}

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

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

以上是 Android自定义RecyclerView实现不固定刻度的刻度尺 的全部内容, 来源链接: utcz.com/p/242870.html

回到顶部