闲来没事,做个小东西玩玩~
网上的例子有一些,不过一天不装逼,我就难受,所以决定自己搞!这个垂直刻度尺可以滑动,可以配合硬件根据结果展示在刻度尺上,话不多少,先看效果吧~
是不是还可以?
上代码:
public class HeightTestRule extends View {
private static final int Max = 225;//中间显示刻度不超过225cm,比姚明高的不接受,哈哈
private static final int Limit_Y = 240;
protected Scroller mScroller;//靠它控制滑动
protected float mDownMotionY;
protected float mLastMotionY;
protected float mTotalMotionY;
protected static final int INVALID_POINTER = -1;
protected int mActivePointerId = INVALID_POINTER;
int indicateHeight;//刻度的高度 一般1dp即可
int indicateGap;//刻度之间的间距
int verticalLineWidth;
Paint mPaint = new Paint();
private Bitmap longBitmap, shortBitmap;//长刻度,短刻度
private RuleChangeListener ruleChangeListener;//scrollY改变会触发
public HeightTestRule(Context context, AttributeSet attrs) {
super(context, attrs);
//流畅度提升,开启硬件加速
setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
init();
}
public interface RuleChangeListener {
void onChange(int level);
}
public void setRuleChangeListener(RuleChangeListener ruleChangeListener) {
this.ruleChangeListener = ruleChangeListener;
}
//滚动到指定刻度
public void scroll(int height) {
if (height <= Max) {
if (!isMoving()) {
int finalY = Max * (indicateHeight + indicateGap) - indicateHeight;
int deltaY = finalY - getScrollY() - height * (indicateGap + indicateHeight);
mScroller.startScroll(0, getScrollY(), 0, deltaY, 500);
invalidate();
}
} else {
Toast.makeText(getContext(), "身高不能大于" + Max + "cm", Toast.LENGTH_SHORT).show();
}
}
//是否在滚动,在滚动就不处理,否则滚动到指定位置
public boolean isMoving() {
return mScroller.computeScrollOffset();
}
//回到原点
public void reset() {
int finalY = Max * (indicateHeight + indicateGap) - indicateHeight;
mScroller.startScroll(0, getScrollY(), 0, finalY - getScrollY(), 500);
invalidate();
}
void init() {
indicateGap = getResources().getDimensionPixelSize(R.dimen.indicate_gap);
indicateHeight = getResources().getDimensionPixelSize(R.dimen.indicate_height);
verticalLineWidth = getResources().getDimensionPixelSize(R.dimen.vertical_line_width);
mScroller = new Scroller(getContext(), new ScrollInterpolator());
mPaint.setStrokeWidth(verticalLineWidth);
mPaint.setColor(getResources().getColor(R.color.indicateColor));
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
longBitmap = createLongLine();
shortBitmap = createshortLine();
//开始滚动到原点
int finalY = Max * (indicateHeight + indicateGap) - indicateHeight;
scrollTo(0, finalY);
}
private static class ScrollInterpolator implements Interpolator {
public ScrollInterpolator() {
}
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1;
}
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
// Don't bother scrolling if the page does not need to be moved
if (getScrollX() != mScroller.getCurrX() || getScrollY() != mScroller.getCurrY()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
}
invalidate();
}
}
private Bitmap createLongLine() {
View view = LayoutInflater.from(getContext()).inflate(R.layout.line_long, null);
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
return bitmap;
}
//根据布局直接生成bitmap,就是这么懒
private Bitmap createshortLine() {
View view = LayoutInflater.from(getContext()).inflate(R.layout.line_short, null);
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
return bitmap;
}
private Bitmap createLabel(int scrollY) {
TextView view = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.indicate_label, null);
int count = (int) (scrollY / indicateHeight);
view.setText(String.valueOf(count));
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
return bitmap;
}
@Override
protected void onDraw(Canvas canvas) {
int height = Limit_Y * (indicateGap + indicateHeight);
//画竖线
canvas.save();
canvas.translate(getScrollX(), getScrollY());
canvas.drawLine(0, 0, 0, height, mPaint);
canvas.restore();
int count = height / indicateGap;
//画刻度
for (int i = count - 1; i >= 0; i--) {
canvas.save();
canvas.translate(getScrollX(), 0);
canvas.translate(0, (Limit_Y - i) * indicateHeight + (Limit_Y - i - 1) * indicateGap);
if (i % 10 == 0) {
canvas.drawBitmap(longBitmap, 0, 0, mPaint);
//画label
Bitmap label = createLabel(i * indicateHeight);
canvas.save();
canvas.translate(longBitmap.getWidth() * 2, -(label.getHeight() - indicateHeight) / 2);
canvas.drawBitmap(label, 0, 0, mPaint);
canvas.restore();
} else {
canvas.drawBitmap(shortBitmap, 0, 0, mPaint);
}
canvas.restore();
}
}
@Override
public void scrollTo(int x, int y) {
//最多不超过
if (y >= 0 && y + getHeight() <= (indicateGap + indicateHeight) * 254) {
super.scrollTo(x, y);
}
if (ruleChangeListener != null) {
int scrollY = getScrollY();
int finalY = Max * (indicateHeight + indicateGap) - indicateHeight;
int level = (finalY - scrollY) / (indicateHeight + indicateGap);
ruleChangeListener.onChange(level);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
mDownMotionY = mLastMotionY = ev.getY();
mTotalMotionY = 0;
mActivePointerId = ev.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float y = ev.getY(pointerIndex);
final float deltaY = mLastMotionY - y;
mTotalMotionY += Math.abs(deltaY);
if (Math.abs(deltaY) >= 1.0f) {
scrollBy(0, (int) deltaY);
mLastMotionY = y;
} else {
awakenScrollBars();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//Do nothing
break;
}
return true;
}
}
理解起来很简单,我就不再解释了,有问题的可以留言,源码下载地址:
http://download.csdn.net/detail/rocketlong/9685539