您的位置:首页 > 移动开发 > Android开发

android SeekBar双滑块

2015-10-20 16:53 405 查看
效果:





实现原理:
1、自定义View,在onDraw(Canvas canvas)中,画出2个Drawable滑动块,2个Drawable滑动条,2个Paint(text)
2、监听onTouchEvent()事件,修改滑块和滑动条的坐标,调用invalidate()来更新界面

使用方法
1、自定义View   SeekBarPressure.class
package xxxxxxxxx

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.math.BigDecimal;
import com.zjcpo.mobileapp.R;

public class SeekBarPressure extends View {
private static final String TAG = "SeekBarPressure";
private static final int CLICK_ON_LOW = 1;      //点击在前滑块上
private static final int CLICK_ON_HIGH = 2;     //点击在后滑块上
private static final int CLICK_IN_LOW_AREA = 3;
private static final int CLICK_IN_HIGH_AREA = 4;
private static final int CLICK_OUT_AREA = 5;
private static final int CLICK_INVAILD = 0;
/*
* private static final int[] PRESSED_STATE_SET = {
* android.R.attr.state_focused, android.R.attr.state_pressed,
* android.R.attr.state_selected, android.R.attr.state_window_focused, };
*/
private static final int[] STATE_NORMAL = {};
private static final int[] STATE_PRESSED = {
android.R.attr.state_pressed, android.R.attr.state_window_focused,
};
private Drawable hasScrollBarBg;        //滑动条滑动后背景图
private Drawable notScrollBarBg;        //滑动条未滑动背景图
private Drawable mThumbLow;         //前滑块
private Drawable mThumbHigh;        //后滑块

private int mScollBarWidth;     //控件宽度=滑动条宽度+滑动块宽度
private int mScollBarHeight;    //滑动条高度

private int mThumbWidth;        //滑动块宽度
private int mThumbHeight;       //滑动块高度

private double mOffsetLow = 0;     //前滑块中心坐标
private double mOffsetHigh = 0;    //后滑块中心坐标
private int mDistance = 0;      //总刻度是固定距离 两边各去掉半个滑块距离

private int mThumbMarginTop = 30;   //滑动块顶部距离上边框距离,也就是距离字体顶部的距离

private int mFlag = CLICK_INVAILD;
private OnSeekBarChangeListener mBarChangeListener;

private double defaultScreenLow = 0;    //默认前滑块位置百分比
private double defaultScreenHigh = 100;  //默认后滑块位置百分比

private boolean isEdit = false;     //输入框是否正在输入

public SeekBarPressure(Context context) {
this(context, null);
}

public SeekBarPressure(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public SeekBarPressure(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//        this.setBackgroundColor(Color.BLACK);

Resources resources = getResources();
notScrollBarBg = resources.getDrawable(R.drawable.seekbarpressure_bg_progress);
hasScrollBarBg = resources.getDrawable(R.drawable.seekbarpressure_bg_normal);
mThumbLow = resources.getDrawable(R.drawable.seekbarpressure_thumb);
mThumbHigh = resources.getDrawable(R.drawable.seekbarpressure_thumb);

mThumbLow.setState(STATE_NORMAL);
mThumbHigh.setState(STATE_NORMAL);

mScollBarWidth = notScrollBarBg.getIntrinsicWidth();
mScollBarHeight = notScrollBarBg.getIntrinsicHeight();

mThumbWidth = mThumbLow.getIntrinsicWidth();
mThumbHeight = mThumbLow.getIntrinsicHeight();

}

//默认执行,计算view的宽高,在onDraw()之前
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
//        int height = measureHeight(heightMeasureSpec);
mScollBarWidth = width;
mOffsetHigh = width - mThumbWidth / 2;
mOffsetLow = mThumbWidth / 2;
mDistance = width - mThumbWidth;

mOffsetLow = formatDouble(defaultScreenLow / 100 * (mDistance ))+ mThumbWidth / 2;
mOffsetHigh = formatDouble(defaultScreenHigh / 100 * (mDistance)) + mThumbWidth / 2;
setMeasuredDimension(width, mThumbHeight + mThumbMarginTop+2);
}

private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
//wrap_content
if (specMode == MeasureSpec.AT_MOST) {
}
//fill_parent或者精确值
else if (specMode == MeasureSpec.EXACTLY) {
}

return specSize;
}

private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int defaultHeight = 100;
//wrap_content
if (specMode == MeasureSpec.AT_MOST) {
}
//fill_parent或者精确值
else if (specMode == MeasureSpec.EXACTLY) {
defaultHeight = specSize;
}

return defaultHeight;
}

protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}

protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

Paint text_Paint = new Paint();
text_Paint.setTextAlign(Paint.Align.CENTER);
text_Paint.setColor(Color.RED);
text_Paint.setTextSize(20);

int aaa = mThumbMarginTop + mThumbHeight / 2 - mScollBarHeight / 2;
int bbb = aaa + mScollBarHeight;

//白色,不会动
notScrollBarBg.setBounds(mThumbWidth / 2, aaa, mScollBarWidth - mThumbWidth / 2, bbb);
notScrollBarBg.draw(canvas);

//蓝色,中间部分会动
hasScrollBarBg.setBounds((int)mOffsetLow, aaa, (int)mOffsetHigh, bbb);
hasScrollBarBg.draw(canvas);

//前滑块
mThumbLow.setBounds((int)(mOffsetLow - mThumbWidth / 2), mThumbMarginTop, (int)(mOffsetLow + mThumbWidth / 2), mThumbHeight + mThumbMarginTop);
mThumbLow.draw(canvas);

//后滑块
mThumbHigh.setBounds((int)(mOffsetHigh - mThumbWidth / 2), mThumbMarginTop, (int)(mOffsetHigh + mThumbWidth / 2), mThumbHeight + mThumbMarginTop);
mThumbHigh.draw(canvas);

double progressLow = formatDouble((mOffsetLow - mThumbWidth / 2) * 100 / mDistance);
double progressHigh = formatDouble((mOffsetHigh - mThumbWidth / 2) * 100 / mDistance);
//            Log.d(TAG, "onDraw-->mOffsetLow: " + mOffsetLow + "  mOffsetHigh: " + mOffsetHigh   + "  progressLow: " + progressLow + "  progressHigh: " + progressHigh);
canvas.drawText((int) progressLow + "", (int)mOffsetLow - 2 - 2, 15, text_Paint);
canvas.drawText((int) progressHigh + "", (int)mOffsetHigh - 2, 15, text_Paint);

if (mBarChangeListener != null) {
if (!isEdit) {
mBarChangeListener.onProgressChanged(this, progressLow, progressHigh);
}

}
}

@Override
public boolean onTouchEvent(MotionEvent e) {
//按下
if (e.getAction() == MotionEvent.ACTION_DOWN) {
if (mBarChangeListener != null) {
mBarChangeListener.onProgressBefore();
isEdit = false;
}
mFlag = getAreaFlag(e);
//            Log.d(TAG, "e.getX: " + e.getX() + "mFlag: " + mFlag);
//            Log.d("ACTION_DOWN", "------------------");
if (mFlag == CLICK_ON_LOW) {
mThumbLow.setState(STATE_PRESSED);
} else if (mFlag == CLICK_ON_HIGH) {
mThumbHigh.setState(STATE_PRESSED);
} else if (mFlag == CLICK_IN_LOW_AREA) {
mThumbLow.setState(STATE_PRESSED);
//如果点击0-mThumbWidth/2坐标
if (e.getX() < 0 || e.getX() <= mThumbWidth/2) {
mOffsetLow = mThumbWidth/2;
} else if (e.getX() > mScollBarWidth - mThumbWidth/2) {
//                    mOffsetLow = mDistance - mDuration;
mOffsetLow = mThumbWidth/2 + mDistance;
} else {
mOffsetLow = formatDouble(e.getX());
//                    if (mOffsetHigh<= mOffsetLow) {
//                        mOffsetHigh = (mOffsetLow + mDuration <= mDistance) ? (mOffsetLow + mDuration)
//                                : mDistance;
//                        mOffsetLow = mOffsetHigh - mDuration;
//                    }
}
} else if (mFlag == CLICK_IN_HIGH_AREA) {
mThumbHigh.setState(STATE_PRESSED);
//                if (e.getX() < mDuration) {
//                    mOffsetHigh = mDuration;
//                    mOffsetLow = mOffsetHigh - mDuration;
//                } else if (e.getX() >= mScollBarWidth - mThumbWidth/2) {
//                    mOffsetHigh = mDistance + mThumbWidth/2;
if(e.getX() >= mScollBarWidth - mThumbWidth/2) {
mOffsetHigh = mDistance + mThumbWidth/2;
} else {
mOffsetHigh = formatDouble(e.getX());
//                    if (mOffsetHigh <= mOffsetLow) {
//                        mOffsetLow = (mOffsetHigh - mDuration >= 0) ? (mOffsetHigh - mDuration) : 0;
//                        mOffsetHigh = mOffsetLow + mDuration;
//                    }
}
}
//设置进度条
refresh();

//移动move
} else if (e.getAction() == MotionEvent.ACTION_MOVE) {
//            Log.d("ACTION_MOVE", "------------------");
if (mFlag == CLICK_ON_LOW) {
if (e.getX() < 0 || e.getX() <= mThumbWidth/2) {
mOffsetLow = mThumbWidth/2;
} else if (e.getX() >= mScollBarWidth - mThumbWidth/2) {
mOffsetLow = mThumbWidth/2 + mDistance;
mOffsetHigh = mOffsetLow;
} else {
mOffsetLow = formatDouble(e.getX());
if (mOffsetHigh - mOffsetLow <= 0) {
mOffsetHigh = (mOffsetLow <= mDistance+mThumbWidth/2) ? (mOffsetLow) : (mDistance+mThumbWidth/2);
}
}
} else if (mFlag == CLICK_ON_HIGH) {
if (e.getX() <  mThumbWidth/2) {
mOffsetHigh = mThumbWidth/2;
mOffsetLow = mThumbWidth/2;
} else if (e.getX() > mScollBarWidth - mThumbWidth/2) {
mOffsetHigh = mThumbWidth/2 + mDistance;
} else {
mOffsetHigh = formatDouble(e.getX());
if (mOffsetHigh - mOffsetLow <= 0) {
mOffsetLow = (mOffsetHigh >= mThumbWidth/2) ? (mOffsetHigh) : mThumbWidth/2;
}
}
}
//设置进度条
refresh();
//抬起
} else if (e.getAction() == MotionEvent.ACTION_UP) {
//            Log.d("ACTION_UP", "------------------");
mThumbLow.setState(STATE_NORMAL);
mThumbHigh.setState(STATE_NORMAL);

if (mBarChangeListener != null) {
mBarChangeListener.onProgressAfter();
}
//这两个for循环 是用来自动对齐刻度的,注释后,就可以自由滑动到任意位置
//            for (int i = 0; i < money.length; i++) {
//            	 if(Math.abs(mOffsetLow-i* ((mScollBarWidth-mThumbWidth)/ (money.length-1)))<=(mScollBarWidth-mThumbWidth)/(money.length-1)/2){
//            		 mprogressLow=i;
//                     mOffsetLow =i* ((mScollBarWidth-mThumbWidth)/(money.length-1));
//                     invalidate();
//                     break;
//                }
//			}
//
//            for (int i = 0; i < money.length; i++) {
//            	  if(Math.abs(mOffsetHigh-i* ((mScollBarWidth-mThumbWidth)/(money.length-1) ))<(mScollBarWidth-mThumbWidth)/(money.length-1)/2){
//            		  mprogressHigh=i;
//                	   mOffsetHigh =i* ((mScollBarWidth-mThumbWidth)/(money.length-1));
//                       invalidate();
//                       break;
//                }
//			}
}
return true;
}

public int getAreaFlag(MotionEvent e) {

int top = mThumbMarginTop;
int bottom = mThumbHeight + mThumbMarginTop;
if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetLow - mThumbWidth / 2) && e.getX() <= mOffsetLow + mThumbWidth / 2) {
return CLICK_ON_LOW;
} else if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetHigh - mThumbWidth / 2) && e.getX() <= (mOffsetHigh + mThumbWidth / 2)) {
return CLICK_ON_HIGH;
} else if (e.getY() >= top
&& e.getY() <= bottom
&& ((e.getX() >= 0 && e.getX() < (mOffsetLow - mThumbWidth / 2)) || ((e.getX() > (mOffsetLow + mThumbWidth / 2))
&& e.getX() <= ((double) mOffsetHigh + mOffsetLow) / 2))) {
return CLICK_IN_LOW_AREA;
} else if (e.getY() >= top
&& e.getY() <= bottom
&& (((e.getX() > ((double) mOffsetHigh + mOffsetLow) / 2) && e.getX() < (mOffsetHigh - mThumbWidth / 2)) || (e
.getX() > (mOffsetHigh + mThumbWidth/2) && e.getX() <= mScollBarWidth))) {
return CLICK_IN_HIGH_AREA;
} else if (!(e.getX() >= 0 && e.getX() <= mScollBarWidth && e.getY() >= top && e.getY() <= bottom)) {
return CLICK_OUT_AREA;
} else {
return CLICK_INVAILD;
}
}

private void refresh() {
invalidate();
}

public void setProgressLow(double  progressLow) {
this.defaultScreenLow = progressLow;
mOffsetLow = formatDouble(progressLow / 100 * (mDistance ))+ mThumbWidth / 2;
isEdit = true;
refresh();
}

public void setProgressHigh(double  progressHigh) {
this.defaultScreenHigh = progressHigh;
mOffsetHigh = formatDouble(progressHigh / 100 * (mDistance)) + mThumbWidth / 2;
isEdit = true;
refresh();
}

public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener) {
this.mBarChangeListener = mListener;
}

//回调函数,在滑动时实时调用,改变输入框的值
public interface OnSeekBarChangeListener {
//滑动前
public void onProgressBefore();

//滑动时
public void onProgressChanged(SeekBarPressure seekBar, double progressLow,
double progressHigh);

//滑动后
public void onProgressAfter();
}

/*    private int formatInt(double value) {
BigDecimal bd = new BigDecimal(value);
BigDecimal bd1 = bd.setScale(0, BigDecimal.ROUND_HALF_UP);
return bd1.intValue();
}*/

public static double formatDouble(double pDouble) {
BigDecimal bd = new BigDecimal(pDouble);
BigDecimal bd1 = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
pDouble = bd1.doubleValue();
return pDouble;
}

}


2、布局调用 xxx.xml
<com.xxx.SeekBarPressure
android:id="@+id/seekBar_tg2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp" />


3、在Activity中实现XxxActivity.class
seekBarPressures = (SeekBarPressure) findViewById(R.id.seekBar_tg2);

seekBarPressures.setOnSeekBarChangeListener(new SeekBarPressure.OnSeekBarChangeListener() {
@Override
public void onProgressBefore() {
isScreen = true;
}

@Override
public void onProgressChanged(SeekBarPressure seekBar, double progressLow, double progressHigh) {

editTexts_min.setText((int) progressLow + "");

editTexts_max.setText((int) progressHigh + "");

}

@Override
public void onProgressAfter() {
isScreen = false;
}
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: