由于最近项目需求,需要一个滑动的刻度尺来选择会员体重,所以自己写了一个选择体重的控件,成品效果就不展示了,下边直接上代码描述基本原理,以及基本的效果:
package view;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.example.administrator.rulerview.R;
/**
* Created by Administrator on 2018/5/19.
*/
public class RulerView extends View {
Paint paint;
int wholeWidth,mCountScale;
private int[] attrArray = {R.attr.min_number,R.attr.max_number,R.attr.ruler_height,R.attr.spacing};
int min_number,max_number,ruler_height,mRuler_width,mRuler_height,spacing;
int len = 40;//刻度的高度
public RulerView(Context context) {
super(context);
initView(null);
}
public RulerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView(attrs);
}
public RulerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RulerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView(attrs);
}
private void initView(AttributeSet attrs) {
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, attrArray);
min_number = typedArray.getInteger(0, 0);
max_number = typedArray.getInteger(attrArray.length-3, 200);
ruler_height = typedArray.getDimensionPixelOffset(attrArray.length-2,40);
spacing = typedArray.getDimensionPixelOffset(attrArray.length-1,5);
typedArray.recycle();
mRuler_width = (max_number-min_number) * spacing;
mRuler_height = ruler_height * 2;
ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(mRuler_width, mRuler_height);
lp.setMargins(15,0,15,0);
this.setLayoutParams(lp);
initPaint();
}
int direction;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
wholeWidth = widthMeasureSpec;
direction = wholeWidth / spacing / 2 + min_number;
super.onMeasure(MeasureSpec.makeMeasureSpec(mRuler_width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(mRuler_height, MeasureSpec.AT_MOST));
}
private void initPaint(){
paint = new Paint();
paint.setColor(Color.GRAY);
paint.setAntiAlias(true);// 抗锯齿
paint.setDither(true);//图像抖动处理
paint.setStyle(Paint.Style.STROKE);
paint.setTextAlign(Paint.Align.CENTER);
}
protected OnScrollListener mScrollListener;
public interface OnScrollListener {
void onScaleScroll(int scale);
}
public void setOnScrollListener(OnScrollListener listener) {
this.mScrollListener = listener;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(0, mRuler_height, mRuler_width, mRuler_height, paint);//画横线
paint.setTextSize(18);
for (int i = 0, j = min_number; i <= max_number - min_number; i++) {
if (i % 10 == 0) {
canvas.drawLine(i * spacing, mRuler_height, i * spacing, mRuler_height-len , paint);
canvas.drawText(j+"", i * spacing, mRuler_height - len-20, paint);
j += 10;
} else {
canvas.drawLine(i * spacing, mRuler_height, i * spacing, mRuler_height - len + 15, paint);
}
}
//滑动的刻度
int tmpCountScale = (int) Math.rint((double) deltaX / (double) spacing); //四舍五入取整
//需要显示的刻度
mCountScale =((max_number-min_number)/2) - tmpCountScale;
if (mScrollListener != null) { //回调方法
mScrollListener.onScaleScroll(mCountScale);
}
}
int deltaX;
private int downX;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int)event.getX();
return true;
case MotionEvent.ACTION_MOVE:
deltaX = (int)event.getX()-downX;
setTranslationX(deltaX);
postInvalidate();
return true;
}
return super.onTouchEvent(event);
}
}
自定义的属性:
<resources>
<attr name="min_number" format="integer"/>
<attr name="max_number" format="integer"/>
<attr name="ruler_height" format="dimension"/>
<attr name="spacing" format="dimension"/>
</resources>
然后是activity里的调用:
RulerView ruler = findViewById(R.id.ruler);
ruler.setOnScrollListener(new RulerView.OnScrollListener() {
@Override
public void onScaleScroll(int scale) {
tv.setText(scale+"");
}
});
基本效果图: