含加号减号 控制 数字的自定义控件
2020-03-03 本文已影响0人
heheworld
维护的项目,因为疫情影响,需要加上体温监控,APP端需要用到设置体温区间的控件
网上搜了一大把,基本都是基于一个线性布局包含三个控件来实现的。
实在是闲来无聊,自己新写了一个,纯天然的自定义控件。。
效果图如下:

手动输入值,所以控件只支持+-号操作,长按的时候也会动的,如果觉得慢的话,可以修改那个sleep间隔。
代码:
布局文件
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.nico.myapplication.AddSubInputView
android:id="@+id/min_temp_view"
android:layout_width="300px"
android:layout_height="60px"
android:textColor="#888888"
android:textSize="16sp"
app:add_icon="@mipmap/temp_plus"
app:default_value="36.2"
app:low="true"
app:sub_icon="@mipmap/temp_sub"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
自定义控件代码
AddSubInputView
package com.nico.myapplication;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
public class AddSubInputView extends View implements Runnable {
private int mViewWidth;
private int mViewHeight;
private Drawable mAddDrawable, mSubDrawable, mBackgroudDrawable;
private int mSubRightEdge, mAddLeftEdge;
private float mDefaultValue = 0.0f;
private float mCurrentValue = 0.0f;
private boolean isLow = true;
private int mTextSize;
private int mTextColor;
LinkedBlockingQueue mTask = new LinkedBlockingQueue();
@Override
public void run() {
if (!mTask.isEmpty()) {
return;
} else {
mTask.add("data");
switch (mCurrentStatus) {
case LEFT:
doOperator(true);
break;
case RIGHT:
doOperator(false);
break;
}
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
mTask.clear();
}
}
private enum STATUS {
LEFT,
CENTER,
RIGHT,
}
private STATUS mCurrentStatus = STATUS.CENTER;
private Executor executors = Executors.newCachedThreadPool();
public AddSubInputView(Context context) {
super(context);
}
public AddSubInputView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(attrs);
}
public AddSubInputView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(attrs);
}
private void initView(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AddSubInputView);
mViewWidth = (int) a.getDimension(R.styleable.AddSubInputView_android_layout_width, 400.0f);
mViewHeight = (int) a.getDimension(R.styleable.AddSubInputView_android_layout_height, 200.0f);
mBackgroudDrawable = a.getDrawable(R.styleable.AddSubInputView_backgroud_icon);
mAddDrawable = a.getDrawable(R.styleable.AddSubInputView_add_icon);
mSubDrawable = a.getDrawable(R.styleable.AddSubInputView_sub_icon);
mTextColor = a.getColor(R.styleable.AddSubInputView_android_textColor, Color.GRAY);
mTextSize = a.getDimensionPixelSize(R.styleable.AddSubInputView_android_textSize, 20);
mDefaultValue = a.getFloat(R.styleable.AddSubInputView_default_value, 36.2f);
isLow = a.getBoolean(R.styleable.AddSubInputView_low, true);
mSubRightEdge = mSubDrawable.getIntrinsicWidth() + 10;
mAddLeftEdge = (mViewWidth - mAddDrawable.getIntrinsicWidth() - 10);
mCurrentValue = mDefaultValue;
a.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
canvas.drawRoundRect(0, 0, mViewWidth, mViewHeight, 10.0f, 10.0f, paint);
int subHeight = mSubDrawable.getIntrinsicHeight();
int subWidth = mSubDrawable.getIntrinsicWidth();
canvas.drawBitmap(((BitmapDrawable) mSubDrawable).getBitmap(), 10, (mViewHeight - subHeight) / 2, paint);
int addWidth = mAddDrawable.getIntrinsicWidth();
int addHeight = mAddDrawable.getIntrinsicHeight();
canvas.drawBitmap(((BitmapDrawable) mAddDrawable).getBitmap(), mViewWidth - addWidth - 10, (mViewHeight - addHeight) / 2, paint);
paint.setTextSize(mTextSize);
paint.setColor(mTextColor);
float txtwidth = paint.measureText(String.valueOf(mCurrentValue));
int centerWidth = (mViewWidth - addWidth - subWidth - 20);
int fontStart = (int) (10 + subWidth + (centerWidth / 2) - (txtwidth / 2));
float baseLineY = mViewHeight / 2 + Math.abs(paint.ascent() + paint.descent()) / 2;
canvas.drawText(String.valueOf(mCurrentValue), fontStart, baseLineY, paint);
paint.reset();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
float posX = event.getX();
switch (action) {
case MotionEvent.ACTION_DOWN:
initStatus(posX);
break;
case MotionEvent.ACTION_MOVE:
dispathClickEvent(posX);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mCurrentStatus = STATUS.CENTER;
break;
}
return true;
}
protected void dispathClickEvent(float rawX) {
if (getCurrentStatus(rawX) == mCurrentStatus) {
executors.execute(this);
}
}
private void initStatus(float rawX) {
mCurrentStatus = getCurrentStatus(rawX);
}
private STATUS getCurrentStatus(float rawX) {
// int centerRightEdge = mViewWidth - mQuartPercent;
if (rawX < mSubRightEdge) {
//减法操作
return STATUS.LEFT;
} else if (rawX > mAddLeftEdge) {
//加法操作
return STATUS.RIGHT;
} else {
return STATUS.CENTER;
}
}
private void doOperator(boolean sub) {
if (sub) {
if (mCurrentValue > 36.2f) {
mCurrentValue -= 0.1f;
}
} else {
if (mCurrentValue < 37.2f) {
mCurrentValue += 0.1f;
}
}
mCurrentValue = (float) (Math.round(mCurrentValue * 10)) / 10;
postInvalidate();
}
public String getCurrentValue() {
return String.valueOf(mCurrentValue);
}
}
属性文件 attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="AddSubInputView">
<attr name="background_color" format="color" />
<attr name="add_icon" format="reference" />
<attr name="sub_icon" format="reference" />
<attr name="backgroud_icon" format="reference" />
<attr name="android:textSize" format="dimension" />
<attr name="android:layout_width" format="dimension" />
<attr name="android:layout_height" format="dimension" />
<attr name="android:textColor" format="color" />
<attr name="default_value" format="float" />
<attr name="low" format="boolean"/>
</declare-styleable>
</resources>
注意点:
- 自定义控件 attrs.xml 需要了解