如何在范围搜索条中设置两个拇指之间的范围?
下面是我的范围搜索栏类.在我的情况下,两个拇指之间的差异是3.如果两个拇指差异是3,拇指是不能重叠的.如何设置拇指之间的范围?
这是我用过的课程
public class RangeSeekbar<T extends Number> extends ImageVIEw { private final Paint paint = new Paint(Paint.ANTI_AliAS_FLAG); private final Bitmap thumbImage = BitmapFactory.decodeResource(getResources(),R.drawable.seekcircle_blue); private final Bitmap thumbpressedImage = BitmapFactory.decodeResource(getResources(),R.drawable.seekcircle_red); private final float thumbWIDth = thumbImage.getWIDth(); private final float thumbHalfWIDth = 0.5f * thumbWIDth; private final float thumbHalfheight = 0.5f * thumbImage.getHeight(); private final float lineHeight = 0.8f * thumbHalfheight; private final float padding = thumbHalfWIDth; private final T absoluteMinValue,absoluteMaxValue; private final NumberType numberType; private final double absoluteMinValuePrim,absoluteMaxValuePrim; private double normalizedMinValue = 0d; private double normalizedMaxValue = 1d; private Thumb pressedThumb = null; private boolean notifyWhileDragging = false; private OnRangeSeekbarchangelistener<T> Listener; /** * Default color of a {@link RangeSeekbar},#FF33B5E5. This is also kNown as "Ice Cream SanDWich" blue. */ public static final int DEFAulT_color = color.argb(0xFF,0); /** * An invalID pointer ID. */ public static final int INVALID_POINTER_ID = 255; // Localized constants from MotionEvent for compatibility // with API < 8 "Froyo". public static final int ACTION_POINTER_UP = 0x6,ACTION_POINTER_INDEX_MASK = 0x0000ff00,ACTION_POINTER_INDEX_SHIFT = 8; private float mDownMotionX; private int mActivePointerID = INVALID_POINTER_ID; /** * On touch,this offset plus the scaled value from the position of the touch will form the progress value. Usually 0. */ float mtouchProgressOffset; private int mScaledtouchSlop; private boolean mIsDragging; /** * Creates a new RangeSeekbar. * * @param absoluteMinValue * The minimum value of the selectable range. * @param absoluteMaxValue * The maximum value of the selectable range. * @param context * @throws IllegalArgumentException * Will be thrown if min/max value type is not one of Long,Double,Integer,float,Short,Byte or BigDecimal. */ public RangeSeekbar(T absoluteMinValue,T absoluteMaxValue,Context context) throws IllegalArgumentException { super(context); this.absoluteMinValue = absoluteMinValue; this.absoluteMaxValue = absoluteMaxValue; absoluteMinValuePrim = absoluteMinValue.doubleValue(); absoluteMaxValuePrim = absoluteMaxValue.doubleValue(); numberType = NumberType.fromNumber(absoluteMinValue); // make RangeSeekbar focusable. This solves focus handling issues in case EditText Widgets are being used along with the RangeSeekbar within ScollVIEws. setFocusable(true); setFocusableIntouchMode(true); init(); } private final voID init() { mScaledtouchSlop = VIEwConfiguration.get(getContext()).getScaledtouchSlop(); } public boolean isnotifyWhileDragging() { return notifyWhileDragging; } /** * Should the Widget notify the Listener callback while the user is still dragging a thumb? Default is false. * * @param flag */ public voID setNotifyWhileDragging(boolean flag) { this.notifyWhileDragging = flag; } /** * Returns the absolute minimum value of the range that has been set at construction time. * * @return The absolute minimum value of the range. */ public T getabsoluteMinValue() { return absoluteMinValue; } /** * Returns the absolute maximum value of the range that has been set at construction time. * * @return The absolute maximum value of the range. */ public T getabsoluteMaxValue() { return absoluteMaxValue; } /** * Returns the currently selected min value. * * @return The currently selected min value. */ public T getSelectedMinValue() { return normalizedTovalue(normalizedMinValue); } /** * Sets the currently selected minimum value. The Widget will be invalIDated and redrawn. * * @param value * The Number value to set the minimum value to. Will be clamped to given absolute minimum/maximum range. */ public voID setSelectedMinValue(T value) { // in case absoluteMinValue == absoluteMaxValue,avoID division by zero when normalizing. if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) { setnormalizedMinValue(0d); } else { setnormalizedMinValue(valuetonormalized(value)); } } /** * Returns the currently selected max value. * * @return The currently selected max value. */ public T getSelectedMaxValue() { return normalizedTovalue(normalizedMaxValue); } /** * Sets the currently selected maximum value. The Widget will be invalIDated and redrawn. * * @param value * The Number value to set the maximum value to. Will be clamped to given absolute minimum/maximum range. */ public voID setSelectedMaxValue(T value) { // in case absoluteMinValue == absoluteMaxValue,avoID division by zero when normalizing. if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) { setnormalizedMaxValue(1d); } else { setnormalizedMaxValue(valuetonormalized(value)); } } /** * Registers given Listener callback to notify about changed selected values. * * @param Listener * The Listener to notify about changed selected values. */ public voID setonRangeSeekbarchangelistener(OnRangeSeekbarchangelistener<T> Listener) { this.Listener = Listener; } /** * Handles thumb selection and movement. NotifIEs Listener callback on certain events. */ @OverrIDe public boolean ontouchEvent(MotionEvent event) { if (!isEnabled()) return false; int pointerIndex; final int action = event.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: // Remember where the motion event started mActivePointerID = event.getPointerID(event.getPointerCount() - 1); pointerIndex = event.findPointerIndex(mActivePointerID); mDownMotionX = event.getX(pointerIndex); pressedThumb = evalpressedThumb(mDownMotionX); // Only handle thumb presses. if (pressedThumb == null) return super.ontouchEvent(event); setpressed(true); invalIDate(); onStartTrackingtouch(); tracktouchEvent(event); attemptClaimDrag(); break; case MotionEvent.ACTION_MOVE: if (pressedThumb != null) { if (mIsDragging) { tracktouchEvent(event); } else { // Scroll to follow the motion event pointerIndex = event.findPointerIndex(mActivePointerID); final float x = event.getX(pointerIndex); if (Math.abs(x - mDownMotionX) > mScaledtouchSlop) { setpressed(true); invalIDate(); onStartTrackingtouch(); tracktouchEvent(event); attemptClaimDrag(); } } if (Listener != null) { Listener.onRangeSeekbarValuesChanged(this,getSelectedMinValue(),getSelectedMaxValue()); } } break; case MotionEvent.ACTION_UP: if (mIsDragging) { tracktouchEvent(event); onStopTrackingtouch(); setpressed(false); } else { // touch up when we never crossed the touch slop threshold // should be interpreted as a tap-seek to that location. onStartTrackingtouch(); tracktouchEvent(event); onStopTrackingtouch(); } pressedThumb = null; invalIDate(); if (Listener != null) { Listener.onRangeSeekbarValuesChanged(this,getSelectedMaxValue()); } break; case MotionEvent.ACTION_POINTER_DOWN: { final int index = event.getPointerCount() - 1; // final int index = ev.getActionIndex(); mDownMotionX = event.getX(index); mActivePointerID = event.getPointerID(index); invalIDate(); break; } case MotionEvent.ACTION_POINTER_UP: onSecondaryPointerUp(event); invalIDate(); break; case MotionEvent.ACTION_CANCEL: if (mIsDragging) { onStopTrackingtouch(); setpressed(false); } invalIDate(); // see above explanation break; } return true; } private final voID onSecondaryPointerUp(MotionEvent ev) { final int pointerIndex = (ev.getAction() & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT; final int pointerID = ev.getPointerID(pointerIndex); if (pointerID == mActivePointerID) { // This was our active pointer going up. Choose // a new active pointer and adjust accordingly. // Todo: Make this decision more intelligent. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mDownMotionX = ev.getX(newPointerIndex); mActivePointerID = ev.getPointerID(newPointerIndex); } } private final voID tracktouchEvent(MotionEvent event) { final int pointerIndex = event.findPointerIndex(mActivePointerID); final float x = event.getX(pointerIndex); if (Thumb.MIN.equals(pressedThumb)) { setnormalizedMinValue(screenTonormalized(x)); } else if (Thumb.MAX.equals(pressedThumb)) { setnormalizedMaxValue(screenTonormalized(x)); } } /** * TrIEs to claim the user's drag motion,and requests disallowing any ancestors from stealing events in the drag. */ private voID attemptClaimDrag() { if (getParent() != null) { getParent().requestdisallowIntercepttouchEvent(true); } } /** * This is called when the user has started touching this Widget. */ voID onStartTrackingtouch() { mIsDragging = true; } /** * This is called when the user either releases his touch or the touch is canceled. */ voID onStopTrackingtouch() { mIsDragging = false; } /** * Ensures correct size of the Widget. */ @OverrIDe protected synchronized voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) { int wIDth = 200; if (MeasureSpec.UnspecIFIED != MeasureSpec.getMode(wIDthMeasureSpec)) { wIDth = MeasureSpec.getSize(wIDthMeasureSpec); } int height = thumbImage.getHeight(); if (MeasureSpec.UnspecIFIED != MeasureSpec.getMode(heightmeasureSpec)) { height = Math.min(height,MeasureSpec.getSize(heightmeasureSpec)); } setMeasuredDimension(wIDth,height); } /** * Draws the Widget on the given canvas. */ @OverrIDe protected synchronized voID onDraw(Canvas canvas) { super.onDraw(canvas); // draw seek bar background line final RectF rect = new RectF(padding,0.5f * (getHeight() - lineHeight),getWIDth() - padding,0.5f * (getHeight() + lineHeight)); paint.setStyle(Style.FILL); paint.setcolor(color.GRAY); paint.setAntiAlias(true); canvas.drawRect(rect,paint); // draw seek bar active range line rect.left = normalizedToScreen(normalizedMinValue); rect.right = normalizedToScreen(normalizedMaxValue); // orange color paint.setcolor(DEFAulT_color); canvas.drawRect(rect,paint); // draw minimum thumb drawThumb(normalizedToScreen(normalizedMinValue),Thumb.MIN.equals(pressedThumb),canvas); // draw maximum thumb drawThumb_max(normalizedToScreen(normalizedMaxValue),Thumb.MAX.equals(pressedThumb),canvas); } /** * OverrIDden to save instance state when device orIEntation changes. This method is called automatically if you assign an ID to the RangeSeekbar Widget using the {@link #setID(int)} method. Other members of this class than the normalized min and max values don't need to be saved. */ @OverrIDe protected Parcelable onSaveInstanceState() { final Bundle bundle = new Bundle(); bundle.putParcelable("SUPER",super.onSaveInstanceState()); bundle.putDouble("MIN",normalizedMinValue); bundle.putDouble("MAX",normalizedMaxValue); return bundle; } /** * OverrIDden to restore instance state when device orIEntation changes. This method is called automatically if you assign an ID to the RangeSeekbar Widget using the {@link #setID(int)} method. */ @OverrIDe protected voID onRestoreInstanceState(Parcelable parcel) { final Bundle bundle = (Bundle) parcel; super.onRestoreInstanceState(bundle.getParcelable("SUPER")); normalizedMinValue = bundle.getDouble("MIN"); normalizedMaxValue = bundle.getDouble("MAX"); } /** * Draws the "normal" resp. "pressed" thumb image on specifIEd x-coordinate. * * @param screenCoord * The x-coordinate in screen space where to draw the image. * @param pressed * Is the thumb currently in "pressed" state? * @param canvas * The canvas to draw upon. */ private voID drawThumb(float screenCoord,boolean pressed,Canvas canvas) { canvas.drawBitmap(pressed ? thumbImage : thumbImage,screenCoord - thumbHalfWIDth,(float) ((0.5f * getHeight()) - thumbHalfheight),paint); } private voID drawThumb_max(float screenCoord,Canvas canvas) { canvas.drawBitmap(pressed ? thumbpressedImage : thumbpressedImage,paint); } /** * DecIDes which (if any) thumb is touched by the given x-coordinate. * * @param touchX * The x-coordinate of a touch event in screen space. * @return The pressed thumb or null if none has been touched. */ private Thumb evalpressedThumb(float touchX) { Thumb result = null; boolean minThumbpressed = isInThumbRange(touchX,normalizedMinValue); boolean maxThumbpressed = isInThumbRange(touchX,normalizedMaxValue); if (minThumbpressed && maxThumbpressed) { // if both thumbs are pressed (they lIE on top of each other),choose the one with more room to drag. this avoIDs "stalling" the thumbs in a corner,not being able to drag them apart anymore. result = (touchX / getWIDth() > 0.5f) ? Thumb.MIN : Thumb.MAX; } else if (minThumbpressed) { result = Thumb.MIN; } else if (maxThumbpressed) { result = Thumb.MAX; } return result; } /** * DecIDes if given x-coordinate in screen space needs to be interpreted as "within" the normalized thumb x-coordinate. * * @param touchX * The x-coordinate in screen space to check. * @param normalizedThumbValue * The normalized x-coordinate of the thumb to check. * @return true if x-coordinate is in thumb range,false otherwise. */ private boolean isInThumbRange(float touchX,double normalizedThumbValue) { return Math.abs(touchX - normalizedToScreen(normalizedThumbValue)) <= thumbHalfWIDth; } /** * Sets normalized min value to value so that 0 <= value <= normalized max value <= 1. The VIEw will get invalIDated when calling this method. * * @param value * The new normalized min value to set. */ public voID setnormalizedMinValue(double value) { normalizedMinValue = Math.max(0d,Math.min(1d,Math.min(value,normalizedMaxValue))); invalIDate(); } /** * Sets normalized max value to value so that 0 <= normalized min value <= value <= 1. The VIEw will get invalIDated when calling this method. * * @param value * The new normalized max value to set. */ public voID setnormalizedMaxValue(double value) { normalizedMaxValue = Math.max(0d,Math.max(value,normalizedMinValue))); invalIDate(); } /** * Converts a normalized value to a Number object in the value space between absolute minimum and maximum. * * @param normalized * @return */ @SuppressWarnings("unchecked") private T normalizedTovalue(double normalized) { return (T) numberType.toNumber(absoluteMinValuePrim + normalized * (absoluteMaxValuePrim - absoluteMinValuePrim)); } /** * Converts the given Number value to a normalized double. * * @param value * The Number value to normalize. * @return The normalized double. */ private double valuetonormalized(T value) { if (0 == absoluteMaxValuePrim - absoluteMinValuePrim) { // prevent division by zero,simply return 0. return 0d; } return (value.doubleValue() - absoluteMinValuePrim) / (absoluteMaxValuePrim - absoluteMinValuePrim); } /** * Converts a normalized value into screen space. * * @param normalizedCoord * The normalized value to convert. * @return The converted value in screen space. */ private float normalizedToScreen(double normalizedCoord) { return (float) (padding + normalizedCoord * (getWIDth() - 2 * padding)); } /** * Converts screen space x-coordinates into normalized values. * * @param screenCoord * The x-coordinate in screen space to convert. * @return The normalized value. */ private double screenTonormalized(float screenCoord) { int wIDth = getWIDth(); if (wIDth <= 2 * padding) { // prevent division by zero,simply return 0. return 0d; } else { double result = (screenCoord - padding) / (wIDth - 2 * padding); return Math.min(1d,Math.max(0d,result)); } } /** * Callback Listener interface to notify about changed range values. * * @author Stephan Tittel ([email protected]) * * @param <T> * The Number type the RangeSeekbar has been declared with. */ public interface OnRangeSeekbarchangelistener<T> { public voID onRangeSeekbarValuesChanged(RangeSeekbar<?> bar,T minValue,T maxValue); } /** * Thumb constants (min and max). */ private static enum Thumb { MIN,MAX }; /** * Utility enumaration used to convert between Numbers and doubles. * * @author Stephan Tittel ([email protected]) * */ private static enum NumberType { LONG,DOUBLE,INTEGER,float,SHORT,BYTE,BIG_DECIMAL; public static <E extends Number> NumberType fromNumber(E value) throws IllegalArgumentException { if (value instanceof Long) { return LONG; } if (value instanceof Double) { return DOUBLE; } if (value instanceof Integer) { return INTEGER; } if (value instanceof float) { return float; } if (value instanceof Short) { return SHORT; } if (value instanceof Byte) { return BYTE; } if (value instanceof BigDecimal) { return BIG_DECIMAL; } throw new IllegalArgumentException("Number class '" + value.getClass().getname() + "' is not supported"); } public Number toNumber(double value) { switch (this) { case LONG: return new Long((long) value); case DOUBLE: return value; case INTEGER: return new Integer((int) value); case float: return new float(value); case SHORT: return new Short((short) value); case BYTE: return new Byte((byte) value); case BIG_DECIMAL: return new BigDecimal(value); } throw new InstantiationError("can't convert " + this + " to a Number object"); } }}
编辑:java类代码
// create RangeSeekbar as Integer range between 20 and 75 final RangeSeekbar<Integer> seekbar = new RangeSeekbar<Integer>(0,35,this); seekbar.setSelectedMinValue(5); seekbar.setSelectedMaxValue(8); seekbar.setonRangeSeekbarchangelistener(new RangeSeekbar.OnRangeSeekbarchangelistener<Integer>() { @OverrIDe public voID onRangeSeekbarValuesChanged(RangeSeekbar<?> bar,Integer minValue,Integer maxValue) { // handle changed range values Log.i(TAG,"User selected new range values: MIN=" + minValue + ",MAX=" + maxValue); int diff=maxValue-minValue; if(diff==4) { } } }); // add RangeSeekbar to pre-defined layout VIEwGroup layout = (VIEwGroup) findVIEwByID(R.ID.layout); layout.addVIEw(seekbar);解决方法 当差异为4时,用于停止拇指的运动.您可以使用
if(diff==4) { bar.setEnabled(false);}
为了更清楚,请转到我们的blog并查看如何在RangedSeekbar部分中拖动时禁用拇指.
总结以上是内存溢出为你收集整理的如何在android中的范围搜索栏中设置两个拇指之间的范围?全部内容,希望文章能够帮你解决如何在android中的范围搜索栏中设置两个拇指之间的范围?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)