好久没写了,发一个项目中用到的
支持单点,长按的 加减器效果如如下
定义如下
private final int NUMBER_MIN = 0;//最小值
private final int NUMBER_MAX = 100;//最大值
private FrameLayout mFrameLayoutReduce;//减号
private FrameLayout mFrameLayoutAdd;//加号
private ImageView ivReduce;//减号图标
private ImageView ivAdd;//加号图标
private TextView tvNumber;//中间的文字
private int number;//当前数字
private boolean isStop;//是否停止
private int longTime = 120;//长按的间隔
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
private OnNumberChangeListener mOnNumberChangeListener;//监听器
初始化如下
public HorizontalNumberPicker(Context context) {
super(context);
initView();
}
public HorizontalNumberPicker(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
/**
* 这里之所以要使用FrameLayout包在ImageView外面是为了不改变ImageView大小的前提下增大触摸范围
*/
private void initView() {
setGravity(Gravity.CENTER);
mFrameLayoutReduce = new FrameLayout(getContext());
mFrameLayoutAdd = new FrameLayout(getContext());
mFrameLayoutReduce.setOnClickListener(this);
mFrameLayoutReduce.setOnLongClickListener(this);
mFrameLayoutReduce.setOnTouchListener(this);
mFrameLayoutAdd.setOnClickListener(this);
mFrameLayoutAdd.setOnLongClickListener(this);
mFrameLayoutAdd.setOnTouchListener(this);
ivReduce = new ImageView(getContext());
ivAdd = new ImageView(getContext());
tvNumber = new TextView(getContext());
ivReduce.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
ivReduce.setImageResource(R.mipmap.joinus_iv_reduce);
ivAdd.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
ivAdd.setImageResource(R.mipmap.joinus_iv_add);
tvNumber.setGravity(Gravity.CENTER);
tvNumber.setTextColor(getResources().getColor(R.color.line_gray));
tvNumber.setTextSize(20);
tvNumber.setText("0");
int padding = DipPxUtil.dip2px(getContext(), 4);
tvNumber.setPadding(padding, 0, padding, 0);
LinearLayout.LayoutParams frameParams = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT);
frameParams.weight = 1;
LayoutParams tvParams = new LayoutParams((int) tvNumber.getPaint().measureText(String.valueOf(NUMBER_MAX)) + 2 * padding, LayoutParams.MATCH_PARENT);//计算最大值需要多长的宽度
addView(mFrameLayoutReduce, frameParams);
addView(tvNumber, tvParams);
addView(mFrameLayoutAdd, frameParams);
FrameLayout.LayoutParams ivParamsReduce = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
ivParamsReduce.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;//往右
mFrameLayoutReduce.addView(ivReduce, ivParamsReduce);
FrameLayout.LayoutParams ivParamsAdd = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
ivParamsAdd.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT;//往左
mFrameLayoutAdd.addView(ivAdd, ivParamsAdd);
}
onMeasure
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthMeasure = widthMeasureSpec;
int heightMeasure = heightMeasureSpec;
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
if (widthMode != MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) { //width,height均为wrap_content下的默认宽高
int width = DipPxUtil.dip2px(getContext(), 80) + paddingLeft + paddingRight;
int height = DipPxUtil.dip2px(getContext(), 30) + paddingTop + paddingBottom;
widthMeasure = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
heightMeasure = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
} else if (widthMode != MeasureSpec.EXACTLY) {
int width = DipPxUtil.dip2px(getContext(), 80) + paddingLeft + paddingRight;
widthMeasure = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
} else if (heightMode != MeasureSpec.EXACTLY) {
int height = DipPxUtil.dip2px(getContext(), 30) + paddingTop + paddingBottom;
heightMeasure = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasure, heightMeasure);
}
处理
/**
*处理单击
*/
@Override
public void onClick(View v) {
if (v == mFrameLayoutAdd) {
number++;
} else if (v == mFrameLayoutReduce) {
number--;
}
setNumber(number);
}
/**
*处理长按,这里是按得越久速度越快
*/
@Override
public boolean onLongClick(final View v) {
new Thread(new Runnable() {
@Override
public void run() {
while (!isStop) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (v == mFrameLayoutAdd) {
number++;
} else if (v == mFrameLayoutReduce) {
number--;
}
setNumber(number);
longTime = longTime < 30 ? 30 : longTime - 8;
}
}, longTime);
try {
Thread.sleep(longTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
return true;
}
/**
*处理长按后松开手机后,恢复速度
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isStop = false;
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
isStop = true;
longTime = 120;
break;
}
return false;
}
/**
*检查
*/
private void CheckNumber() {
if (number < NUMBER_MIN) {
number = NUMBER_MIN;
} else if (number > NUMBER_MAX) {
number = NUMBER_MAX;
}
}
public int getNumber() {
return number;
}
/**
*设置数字
*/
public void setNumber(int number) {
this.number = number;
CheckNumber();
tvNumber.setText(String.valueOf(this.number));
if (this.number == 0) {
tvNumber.setTextColor(getResources().getColor(R.color.line_gray));
} else {
tvNumber.setTextColor(getResources().getColor(R.color.joinus_main_text_gold));
}
if (mOnNumberChangeListener != null) {
mOnNumberChangeListener.onNumber(this, this.number);
}
}
/**
*数字变化的监听
*/
public interface OnNumberChangeListener {
void onNumber(HorizontalNumberPicker numberPicker, int number);
}
public OnNumberChangeListener getOnNumberChangeListener() {
return mOnNumberChangeListener;
}
public void setOnNumberChangeListener(OnNumberChangeListener onNumberChangeListener) {
mOnNumberChangeListener = onNumberChangeListener;
}