普通Android系统中提供的状态选择控件有Switch,但是其只能提供两种状态的选择,今天我们可以通过仿照SeekBar控件进行选择器的最终效果如下图,通过拖动灰色圆形按钮实现选择不同的状态:
具体代码如下:
/**
* Created by MG_ZXC on 2018/7/6.
*/
public class StateSeekBar extends RelativeLayout implements View.OnTouchListener {
private float downX;
private TextView mTv;
private ImageView mCir;
private int myParentGiveWidth;
private int myParentGiveHeight;
private int mViewWidth;
private int mViewHeight;
private int mTvHeight;
private int mTvWidth;
private int mCirHeight;
private int mCirWidth;
private int STATECOUNT=5;
private int PROGRESS=100;
private int spaceX;
private OnStateSeekChangeListener onStateSeekChangeListener;
public StateSeekBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setGravity(CENTER_VERTICAL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//先测量孩子
//测量每个子控件的宽度和高度,只有先测量孩子,那么在后面才能得到孩子的宽、高 childView.getMeasuredWidth();
mCir = ((ImageView) getChildAt(0));
mTv = ((TextView) getChildAt(1));
mTv.setOnTouchListener(this);
measureChild(mCir, widthMeasureSpec, heightMeasureSpec);
measureChild(mTv, widthMeasureSpec, heightMeasureSpec);
//获得宽高的测量模式
int widthMeasureSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMeasureSpecMode = MeasureSpec.getMode(heightMeasureSpec);
//获得测量值
myParentGiveWidth = MeasureSpec.getSize(widthMeasureSpec);
myParentGiveHeight = MeasureSpec.getSize(heightMeasureSpec);
//测量viewgroup
setMeasuredDimension(myParentGiveWidth, getChildAt(0).getMeasuredHeight());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//获取当前View的宽高
mViewWidth = w;//720
mViewHeight = h;//110
mTvHeight = mTv.getMeasuredHeight();
mTvWidth = mTv.getMeasuredWidth();
mCirHeight = mCir.getMeasuredHeight();
mCirWidth = mCir.getMeasuredWidth();
spaceX = PROGRESS / STATECOUNT;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//super.onLayout(changed, l, t, r, b);
mCir.layout(0, 0, mCir.getMeasuredWidth(), mCir.getMeasuredHeight());
mTv.layout(0, 0, mTv.getMeasuredWidth(), mTv.getMeasuredHeight());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
float xDistance = event.getX() - downX;
int mTvLeft = mTv.getLeft() + ((int) xDistance);
int mTvRight = mTv.getRight() + ((int) xDistance);
//判断向左还是向右滑动
if (mTvLeft <= 0) {
mTv.layout(0, 0, mTvWidth, mTvHeight);
mCir.layout(0, 0, mTvWidth, mCirHeight);
mTvLeft = 0;
} else if (mTvLeft >= mViewWidth - mTvWidth) {
mTv.layout(mViewWidth - mTvWidth, 0, mViewWidth, mTvHeight);
mCir.layout(0, 0, mViewWidth, mCirHeight);
mTvLeft = mViewWidth - mTvWidth;
} else {
mTv.layout(mTvLeft, 0, mTvRight, mTvHeight);
mCir.layout(0, 0, mTvRight, mCirHeight);
}
checkState(mTvLeft);//判断当前的滑块状态 一共
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return true;
}
int preState = SeekState.NOT_SELECT;
private void checkState(float preProgress) {
int progress = (int) ((preProgress / (((float) mViewWidth) - ((float) mTvWidth))) * 100);
int currentState = checkCurrentState(progress);
if (onStateSeekChangeListener != null) {
onStateSeekChangeListener.onSeeking(((int) preProgress));
}
if (preState != currentState) {
//状态改变
preState = currentState;
if (onStateSeekChangeListener != null) {
onStateSeekChangeListener.onStateChange(currentState);
}
checkTexIndicator(currentState);
}
}
//改变圆形的文字
private void checkTexIndicator(int currentState) {
if (currentState== SeekState.NOT_SELECT) {
mTv.setText("0");
}else if (currentState==SeekState.IMPOSSIBLE){
mTv.setText("1");
}else if(currentState==SeekState.NOT_SURE){
mTv.setText("2");
}else if (currentState==SeekState.TRY){
mTv.setText("3");
}else {
mTv.setText("4");
}
}
private int checkCurrentState(float preProgress) {
if (preProgress >= 0 && preProgress < spaceX) {
return SeekState.NOT_SELECT;
} else if (preProgress >= spaceX && preProgress < spaceX * 2) {
return SeekState.IMPOSSIBLE;
} else if (preProgress >= spaceX * 2 && preProgress < spaceX * 3) {
return SeekState.NOT_SURE;
} else if (preProgress >= spaceX * 3 && preProgress < spaceX * 4) {
return SeekState.TRY;
} else {
return SeekState.COMPLATE;
}
}
public void setOnStateSeekChangeListener(OnStateSeekChangeListener mOnStateSeekChangeListener) {
onStateSeekChangeListener = mOnStateSeekChangeListener;
}
public int getProgress(){
return getChildAt(0).getLeft();
}
//设置进度状态
public void setStateProgress(int progress) {
getChildAt(1).layout(progress, 0, progress+mTvWidth, mTvHeight);
getChildAt(0).layout(0, 0, progress+mTvWidth, mCirHeight);
}
//设置文字状态
public void setState(int state) {
((TextView) getChildAt(1)).setText((state-1)+"");
}
}
引用的布局文件:
<learn.mind.ui.StateSeekBar
android:id="@+id/tickseekbar"
android:layout_below="@id/tv_evaluateStra"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/stateseekbar">
<!---->
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/state_bar_circle" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/text_bg"
android:gravity="center"
android:text="0"
android:textColor="@android:color/white"
android:textSize="18sp" />
</learn.mind.ui.StateSeekBar>
stateseekbar:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners android:radius="44dp" />
<solid android:color="#3b8ebe" />
</shape>
其中state_bar_circle:为 .9图当拉动滑块的时候,能够保持纵向不变形
text_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#afc6df" />
<corners android:radius="10dp" />
</shape>