元宵佳节,希望大家开开心心,新的一年更加顺顺利利!!!
不多说,首先来一个效果看看:
使用场景
公司要求做个视频回放的东西,在一天24小时内,根据刻度时间去定位具体的位置.当然了上面的效果可以用到很多其他地方!!
自定义步骤
基础性的东西就不说了,直接贴上代码,没什么好讲的,都是简单的一些东西!!
public class TimeRule extends View implements View.OnTouchListener {
//最大刻度的长度
private int mMaxScaleHeight;
//中间刻度的长度
private int mMiddleScaleHeight;
//最短刻度的长度
private int mMinScaleHeight;
//最大刻度的高度占控件的高度比例
public float mMaxScaleHeightRatio = 0.4f;
//中间刻度的高度占控件的高度比例
public float mMidScaleHeightRatio = 0.2f;
//最小刻度的高度占控件的高度比例
public float mMinScaleHeightRatio = 0.1f;
private Paint mTopBotLinePaint;
private int windowWidth;
private int windowHeight;
private int viewWidth;
private int viewHeight;
private int mBottomTopLineWidth = 5;
private int mSaleMaxWidth = 2;
private int mSaleMidWidth = 2;
private int mSaleMinWidth = 2;
private Paint mScaleMaxPaint;
private Paint mScaleMidPaint;
private Paint mScaleMinPaint;
//每一个刻度之间的间隔距离
private float itemWidth;
private Paint mTextPaint;
private GestureDetector gestureDetector;
//当前时间值
private int currentM;
//将控件的宽度分为2个小时
private int pcsM;
private boolean isFling = false;
private Paint mMidLinePaint;
public TimeRule(Context context) {
this(context, null);
}
public TimeRule(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TimeRule(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Resources resources = this.getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
float density = dm.density;
windowWidth = dm.widthPixels;
windowHeight = dm.heightPixels;
mTopBotLinePaint = new Paint();
mTopBotLinePaint.setColor(Color.RED);
mTopBotLinePaint.setStyle(Paint.Style.FILL_AND_STROKE);
mTopBotLinePaint.setStrokeWidth(mBottomTopLineWidth);
mScaleMaxPaint = new Paint();
mScaleMaxPaint.setColor(getResources().getColor(R.color.colorPrimary));
mScaleMaxPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mScaleMaxPaint.setStrokeWidth(mSaleMaxWidth);
mScaleMidPaint = new Paint();
mScaleMidPaint.setColor(Color.MAGENTA);
mScaleMidPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mScaleMidPaint.setStrokeWidth(mSaleMidWidth);
mMidLinePaint = new Paint();
mMidLinePaint.setColor(Color.CYAN);
mMidLinePaint.setStyle(Paint.Style.FILL_AND_STROKE);
mMidLinePaint.setStrokeWidth(mSaleMidWidth);
mTextPaint = new Paint();
mTextPaint.setColor(Color.WHITE);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setTextSize(30);
Calendar calendar = Calendar.getInstance();
//当前的小时
int h = calendar.get(Calendar.HOUR_OF_DAY);
//当前的分钟
int m = calendar.get(Calendar.MINUTE);
currentM = h * 60 + m;
gestureDetector = new GestureDetector(new GestureListener());
setOnTouchListener(this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureWidth(int widthMeasureSpec) {
int resultWide = windowWidth;
int widSize = MeasureSpec.getSize(widthMeasureSpec);
int widMode = MeasureSpec.getMode(widthMeasureSpec);
if (widMode == MeasureSpec.EXACTLY) {
resultWide = widSize;
} else if (widMode == MeasureSpec.AT_MOST) {
resultWide = windowWidth;
}
return resultWide;
}
private int measureHeight(int heightMeasureSpec) {
int resultHeight = 200;
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
resultHeight = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
resultHeight = 200;
}
return resultHeight;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w == 0 || h == 0) {
return;
}
viewWidth = w;
viewHeight = h;
//这个地方已经写死了,意思是在一个宽度显示两个小时
itemWidth = (float) viewWidth / (60 * 2);
mMaxScaleHeight = (int) (h * mMaxScaleHeightRatio);
mMiddleScaleHeight = (int) (h * mMidScaleHeightRatio);
mMinScaleHeight = (int) (h * mMinScaleHeightRatio);
pcsM = viewWidth / 60 * 2;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawScaleLine(canvas);
drawTopBottomLine(canvas);
drawMiddleLine(canvas);
}
private void drawScaleLine(Canvas canvas) {
canvas.drawColor(Color.BLACK);
int offest = 0;
//这个是要画出2个小时,超出部分不再画出,所以,一进一出就是2小时
for (int i = currentM - 60; i < currentM + 60; i++) {
//累计X轴的平移
offest += itemWidth;
//如果超出范围的刻度不需要画
if (i < 0 || i > 24 * 60) {
continue;
}
if (i % 60 == 0) {
//画小时
canvas.drawLine(offest, 0, offest, mMaxScaleHeight, mScaleMaxPaint);
canvas.drawLine(offest, viewHeight - 30, offest, viewHeight - 30 - mMaxScaleHeight, mScaleMaxPaint);
int hour = i / 60;
canvas.drawText(hour + "", offest, viewHeight, mTextPaint);
} else {
//画分
canvas.drawLine(offest, 0, offest, mMiddleScaleHeight, mScaleMidPaint);
canvas.drawLine(offest, viewHeight - 30, offest, viewHeight - 30 - mMiddleScaleHeight, mScaleMidPaint);
}
}
}
//画底部线和顶部线
private void drawTopBottomLine(Canvas canvas) {
canvas.drawLine(0, 0 + 3, windowWidth, 0 + 3, mTopBotLinePaint);
canvas.drawLine(0, viewHeight - 30, windowWidth, viewHeight - 30, mTopBotLinePaint);
}
//画中间的那个条线
private void drawMiddleLine(Canvas canvas) {
String minuteStr;
canvas.drawLine(viewWidth / 2 + itemWidth, 3, viewWidth / 2 + itemWidth, viewHeight, mMidLinePaint);
int minute = currentM % 60;
if (minute < 10) {
minuteStr = "0" + minute;
} else {
minuteStr = minute + "";
}
int hour = currentM / 60;
canvas.drawText(hour + ":" + minuteStr, windowWidth / 2, viewHeight/2, mTextPaint);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private class GestureListener implements GestureDetector.OnGestureListener {
private AutoFlingRunable autoFlingRunable;
@Override
public boolean onDown(MotionEvent e) {
if (isFling) {
removeCallbacks(autoFlingRunable);
}
return true;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (Math.abs(distanceX) > pcsM) {
currentM += distanceX / pcsM;
} else if (Math.abs(distanceX) > 2) {
if (distanceX > 0) {
currentM += 1;
} else {
currentM -= 1;
}
}
if (checkTime()) {
invalidate();
}
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (Math.abs(velocityX) > 1000) {
isFling = true;
//滑翔的时候.一步步停下来,利用runable来控制!
autoFlingRunable = new AutoFlingRunable(velocityX);
post(autoFlingRunable);
}
return false;
}
}
private class AutoFlingRunable implements Runnable {
private float velocityX;
public AutoFlingRunable(float velocityX) {
this.velocityX = velocityX;
}
@Override
public void run() {
if (velocityX > 0) {
currentM -= (velocityX / 500);
} else {
currentM -= (velocityX / 500);
}
velocityX /= 1.0666F;
if (checkTime()) {
postDelayed(this, 30);
invalidate();
}
}
}
//检查是否是超出时间范围(0-24)
private boolean checkTime() {
if (currentM <= 0) {
currentM = 0;
invalidate();
return false;
}
if (currentM >= 24 * 60) {
currentM = 24 * 60;
invalidate();
return false;
}
return true;
}
}
后期
已经贴出全部代码,后期准备做个控制显示秒或者分的,同时可以这个控件!为了过元宵就提前这样贴代码了!!都是一些轮子!!