2016-03-21 5 views
4

Ich benutze die Reichweite Suchleiste in meiner App.Es funktioniert gut, aber meine Anforderung ist der Bereich zwischen den beiden Daumen. Im Standard überlappen sich beide Daumen in meinem Fall Daumen nicht überlappen einander.Wie Bereich zwischen zwei Daumen in Bereich Suchleiste in Android festlegen?

Wie stelle ich den Bereich zwischen den beiden Daumen im Bereich Suchleiste ein?

unten ist meine Bereichssuche bar class.In meinem Fall Unterschied zwischen den beiden Daumen ist 3.wenn zwei Daumen Unterschied ist 3, Daumen sind nicht überlappen.wie Bereich zwischen den Daumen?

hier ist die Klasse, was ich

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, 0, 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, getSelectedMinValue(), 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, boolean pressed, Canvas canvas) 
    { 
      canvas.drawBitmap(pressed ? thumbPressedImage : thumbPressedImage, screenCoord - thumbHalfWidth, (float) ((0.5f * getHeight()) - thumbHalfHeight), 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.min(1d, 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"); 
      } 
    }} 

enter image description here

EDIT verwendet: Java Class Code

// 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); 
+0

können Sie bitte Ihre Java-Klasse zeigen, wo Sie die RangeSeekBar verwendet haben. –

+0

sagen Sie den Bereichswert s/w Ihre Daumen in Ihrer RangeSeekBar. Was ist in dieser Methode festgelegt. seekBar.setRangeValues ​​(0, 100); –

+0

@AmanGupta Danke für die Antwort, ich versuchte dies, aber keine Verwendung.In meinem Fall beide Schieberegler nicht zusammen bewegt werden, wenn die Differenz zu erreichen ist 4. – Rajesh

Antwort

3

Für die Bewegung von Daumen zu stoppen, wenn die Differenz 4. ist Sie verwenden können

if(diff==4) { 
    bar.setEnabled(false); 
} 

Für mehr Klarheit gehen Sie zu unserem blog und sehen Sie Wie Sie Daumen beim Ziehen in RangeedSeekBar Abschnitt deaktivieren.

+1

Danke, es funktioniert wie ein Charme .. – Rajesh

+0

Ihre Begrüßung @ Rajesh. Könnten Sie bitte unseren Blog kommentieren? http://mobikul.com/how-to-make-range-seekbar-or-dual-thums-seekbar-in-android/ –

+0

@AmanGupta hallo können Sie mir helfen, ich bin nicht in der Lage, Werte zwischen zwei Mal zu zeigen, dass ist in msicconfs – Erum

Verwandte Themen