Giter VIP home page Giter VIP logo

range-seek-bar's People

Contributors

googlecodeexporter avatar

Watchers

 avatar

range-seek-bar's Issues

Added rounding factor and color selection

Added some small enhancements:

- Selection of color (setActiveColor()) and two color constants or ICS-blue and 
pre-ICS orange. Being able to change the color dynamically should also allow to 
add color effects, e.g. fading to red for smaller values etc.

- Added a rounding factor (setRoundingFactor()) to allow of discrete values, 
eg. 0.5 steps


Thanks for the great widget!
Bachi

Original issue reported on code.google.com by [email protected] on 16 Mar 2012 at 5:01

Attachments:

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 9 Sep 2013 at 8:45

Implemented XML usage of widget.

Hi,

I did little refactoring of your class :).

I added supporting XML usage, but your class is abstract for now. Also I 
renamed all fields to follow Google naming code style.

Best, Igor.

Original issue reported on code.google.com by [email protected] on 14 Aug 2013 at 8:56

Attachments:

How to set new range limit?

No problem, but how can i set new range limit?

onCreate i set limit by this line:
RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, context);

How can I change range to new min and max limit? Like 30, 150


OS android



Original issue reported on code.google.com by [email protected] on 29 Aug 2014 at 5:38

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 7 Jan 2013 at 6:24

Expansion upon xml support

Purpose of code changes on this branch:
To expand upon the a previous implementation to support defining from within 
xml (https://code.google.com/p/range-seek-bar/issues/detail?id=3).

When reviewing my code changes, please focus on:
New xml enum attribute "type" was created that contains the various supported 
types, a convenience function was added to the enum to help translate between 
this the attribute and the enum.
New xml attribute "notifyWhileDragging" was added to define this value from 
within xml

attr.xml goes in the "res/values" folder

Note I've only tested in my own project with a few of the supported types, more 
testing will be needed for use-cases involving the other types

Original issue reported on code.google.com by [email protected] on 7 Feb 2013 at 10:55

Attachments:

better handling of toNumber method

When returning Double the conversion is futile, and for the other cases this 
works as well and does not consume so much memory.




public Number toNumber(double value) {
            switch (this) {
                case LONG:
                    return (long) value;
                case DOUBLE:
                    return value;
                case INTEGER:
                    return (int) value;
                case FLOAT:
                    return new Float(value);
                case SHORT:
                    return (short) value;
                case BYTE:
                    return (byte) value;
                case BIG_DECIMAL:
                    return new BigDecimal(value);
            }
            throw new InstantiationError("can't convert " + this + " to a Number object");
        }


Original issue reported on code.google.com by [email protected] on 2 Apr 2012 at 10:29

Code review request

Purpose of code changes on this branch:

Have min and max values saved and restored when view is recreated due to 
orientation change



Original issue reported on code.google.com by [email protected] on 30 Sep 2011 at 2:21

Attachments:

Work in XML

This is a fantastic Widget!  Thanks!  The reason that it doesn't work in the 
XML editor is because it used template values and the XML editor doesn't know 
how to instantiate template objects.  I have made a local edit to have it use 
only floats (like the standard SeekBar) and it works just fine in the XML 
editor.

Original issue reported on code.google.com by [email protected] on 11 Nov 2011 at 8:50

  • Merged into: #3

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 11 Dec 2014 at 6:57

Widget crashes my app

What steps will reproduce the problem?

1. Added the Test.java activity with the test.xml layout to my project
2. Ran the app on a real device

What is the expected output? What do you see instead?

I would hope to see the slider. Instead the app crashes without giving any 
error message on the LogCat window.

What version of the product are you using? On what operating system?
I am using Android SDK Tools 21.1 with version 17 of the API.


Original issue reported on code.google.com by [email protected] on 14 Mar 2013 at 11:08

Attachments:

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 10 Jul 2013 at 5:07

Provide widget via Maven

currently it is not possible for developers to easily (even it is already very 
easy) integrate the widget via maven. it would be great if a maven version 
would be provided. so the developer may also profit from any bugfixing the 
widget will receive in future.

Original issue reported on code.google.com by [email protected] on 9 Jun 2014 at 6:44

Need Listener like OnProgressChanged of Seekbar

What is the expected output? What do you see instead?

Using the setOnRangeSeekBarChangeListener is fine; but the problem is, it 
returns only when we have finished dragging the seekbar.

If it would be able to return current position of slider when we are moving 
(similar to OnProgressChanged() of Seekbar); then it would be very helpful.





Original issue reported on code.google.com by [email protected] on 17 Jan 2014 at 12:36

Sliders don't reposition on setSelectedMinValue or setSelectedMaxValue

What steps will reproduce the problem?
1. Create a RangeSeekBar in the layout
2. Add a setOnRangeSeekBarChangeListener to the RangeSeekBar object 
3. Call setSelectedMinValue or setSelectedMaxValue on the RangeSeekBar object

What is the expected output? What do you see instead?
I expected the sliders(thumbs) to move to the correct position but nothing 
happens.

What version of the product are you using? On what operating system?
Android, no version of product found

Original issue reported on code.google.com by [email protected] on 11 Jun 2012 at 12:42

your example file error

public class MyActivity extends ListActivity {

...
@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
...
        Context context;
        // create RangeSeekBar as Integer range between 20 and 75
        RangeSeekBar<Double> seekBar = new RangeSeekBar<Double>(0.0, 100.0, context);

        seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Double>() {
                @Override
                public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Double minValue, Double maxValue) {
                        // handle changed range values
                        Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
                }
        });

ERROR:
The method 
     setOnRangeSeekBarChangeListener(RangeSeekBar.OnRangeSeekBarChangeListener<Double>) in the type 
     RangeSeekBar<Double> is not applicable for the arguments (new OnRangeSeekBarChangeListener<Double>()
     {})


OnRangeSeekBarChangeListener cannot be resolved to a type

-------
if i changed to this:

seekBar.setOnRangeSeekBarChangeListener(seekBar.new 
OnRangeSeekBarChangeListener<Double>() {

i get another error:
Illegal enclosing instance specification for type 
RangeSeekBar<Double>.OnRangeSeekBarChangeListener<Double>

--------
so how to use this range seekbar?

Original issue reported on code.google.com by [email protected] on 12 May 2012 at 10:44

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 17 Jan 2013 at 11:26

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 19 Dec 2012 at 12:14

Move project to Github

Please, move project to Github. Project Hosting on Google Code will close on 
January 25th, 2016.

Original issue reported on code.google.com by [email protected] on 12 Apr 2015 at 12:41

just for learn

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 3 May 2013 at 4:21

How to use seekbar dynamic

What steps will reproduce the problem?
1.I want to add seekbar in Listview
2.I want to add multiple seekbar as I needed.
3.I want to set id for all seekbar

What is the expected output? What do you see instead?
I cant get the value of min max when I added multiple

What version of the product are you using? On what operating system?
Android SDK 4.4 (kitkat)

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 14 Jul 2014 at 10:39

Setting the Min And Max of RangSeeBar after onlistener is called

I am not too sure if this is already posted, but I had faced a problem. 
Suppose, I had range of 0-2, so when I moved the left seekbar 25%, it used to 
give min and max range as 0 and 2 but used to stay at 25% (which is confusing 
for the users, it should move to 1 (50%) or 0 ideally). So the below code sets 
the min and max value of seekbar once the seekbar is adjusted. And special 
thanks to the developer for providing the range seek bar. It is simply awesome.


final RangeSeekBar<Double> seekBar = new RangeSeekBar<Double>(0.0, 
iMatches*1.0, context);
        seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Double>() {
            @Override
            public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Double minValue, Double maxValue) {
                // handle changed range values

                minValue = (double) Math.round(minValue);
                maxValue = (double) Math.round(maxValue);

                Log.i("Yoooo", "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
                seekBar.setSelectedMinValue(minValue);
                seekBar.setSelectedMaxValue(maxValue);
            }
        });

Original issue reported on code.google.com by [email protected] on 6 Sep 2013 at 10:33

InstantiationException:

What steps will reproduce the problem?
1. application crashes with an Instantiation Exception, The complete logcat and 
the source code is attaching....


What is the expected output? What do you see instead?


What version of the product are you using? On what operating system?


Please provide any additional information below.

06-09 20:58:17.930: E/AndroidRuntime(2185): FATAL EXCEPTION: main
06-09 20:58:17.930: E/AndroidRuntime(2185): Process: com.example.seekbar, PID: 
2185
06-09 20:58:17.930: E/AndroidRuntime(2185): java.lang.RuntimeException: Unable 
to instantiate activity 
ComponentInfo{com.example.seekbar/com.example.seekbar.RangeSeekBar}: 
java.lang.InstantiationException: can't instantiate class 
com.example.seekbar.RangeSeekBar; no empty constructor
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2121)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.app.ActivityThread.access$800(ActivityThread.java:135)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.os.Handler.dispatchMessage(Handler.java:102)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.os.Looper.loop(Looper.java:136)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.app.ActivityThread.main(ActivityThread.java:5017)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
java.lang.reflect.Method.invokeNative(Native Method)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
java.lang.reflect.Method.invoke(Method.java:515)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
dalvik.system.NativeStart.main(Native Method)
06-09 20:58:17.930: E/AndroidRuntime(2185): Caused by: 
java.lang.InstantiationException: can't instantiate class 
com.example.seekbar.RangeSeekBar; no empty constructor
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
java.lang.Class.newInstanceImpl(Native Method)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
java.lang.Class.newInstance(Class.java:1208)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.app.Instrumentation.newActivity(Instrumentation.java:1061)
06-09 20:58:17.930: E/AndroidRuntime(2185):     at 
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2112)
06-09 20:58:17.930: E/AndroidRuntime(2185):     ... 11 more

Original issue reported on code.google.com by [email protected] on 9 Jun 2014 at 12:37

Attachments:

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 22 Jan 2013 at 12:17

Unable to replay video on youtube website

What steps will reproduce the problem?
1. Launch Browser > Goto www.youtube.com
2. Select video from the list > Play the video
3. While video is playing > press back key
4. Select the same video > play the video > Observe 
-> Play softkey is not responding

What is the expected output? What do you see instead?
Able to replay video

What version of the product are you using? On what operating system?
Android 4.0.4

Please provide any additional information below.
When we tap on the Video area in youtube, the Java Player needs to be created. 
This creation is done in the process of recalcStyle() initiated from 
cument::updateStyleForAllDocuments().

After this when the play event is reached to MediaPlayerPrivateAndroid.cpp, it 
starts playing the Java Player.

In the problem case mentioned in the issue, 
Document::updateStyleForAllDocuments() is not being initiated from JavaScript. 
Hence, the Java Player for that particular video is not being created. As a 
result of this when the play event reaches to MediaPlayerPrivateAndroid.cpp, it 
can't play the Java Player.

This issue is observed in Galaxy nexus. Hence, it seems an ICS common issue


Original issue reported on code.google.com by [email protected] on 8 Aug 2012 at 1:07

Vertical implementation

Hi,

I changed the code to provide a vertical implementation. Maybe it is helpful 
for someone:

import java.math.BigDecimal;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ImageView;
import de.continental.app.gesturedetection.R;

/**
 * Widget that lets users select a minimum and maximum value on a given numerical range. The range value types can be one of Long, Double, Integer, Float, Short, Byte or BigDecimal.<br />
 * <br />
 * Improved {@link MotionEvent} handling for smoother use, anti-aliased painting for improved aesthetics.
 * 
 * @author Stephan Tittel ([email protected])
 * @author Peter Sinnott ([email protected])
 * @author Thomas Barrasso ([email protected])
 * 
 * @param <T>
 *            The Number type of the range values. One of Long, Double, Integer, Float, Short, Byte or BigDecimal.
 */
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.seek_thumb_normal);
        private final Bitmap thumbPressedImage = BitmapFactory.decodeResource(getResources(), R.drawable.seek_thumb_pressed);
        private final float thumbWidth = thumbImage.getWidth();
        private final float thumbHalfWidth = 0.5f * thumbWidth;
        private final float thumbHalfHeight = 0.5f * thumbImage.getHeight();
        private final float lineWidth = 0.3f * thumbHalfWidth;
        private final float padding = thumbHalfHeight;
        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, 0x33, 0xB5, 0xE5);

        /**
         * 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 mDownMotionY;
        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);
                        mDownMotionY = event.getY(pointerIndex);

                        pressedThumb = evalPressedThumb(mDownMotionY);

                        // 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 y = event.getY(pointerIndex);

                                        if (Math.abs(y - mDownMotionY) > mScaledTouchSlop) {
                                                setPressed(true);
                                                invalidate();
                                                onStartTrackingTouch();
                                                trackTouchEvent(event);
                                                attemptClaimDrag();
                                        }
                                }

                                if (notifyWhileDragging && 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();
                        mDownMotionY = event.getY(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;
                        mDownMotionY = ev.getY(newPointerIndex);
                        mActivePointerId = ev.getPointerId(newPointerIndex);
                }
        }

        private final void trackTouchEvent(MotionEvent event) {
                final int pointerIndex = event.findPointerIndex(mActivePointerId);
                final float y = event.getY(pointerIndex);

                if (Thumb.MIN.equals(pressedThumb)) {
                        setNormalizedMinValue(screenToNormalized(y));
                }
                else if (Thumb.MAX.equals(pressedThumb)) {
                        setNormalizedMaxValue(screenToNormalized(y));
                }
        }

        /**
         * 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 height = 200;
            if (MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(heightMeasureSpec)) {
                    height = MeasureSpec.getSize(heightMeasureSpec);
            }
            int width = thumbImage.getWidth();
            if (MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(widthMeasureSpec)) {
                    width = Math.min(width, MeasureSpec.getSize(widthMeasureSpec));
            }
            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(0.5f * (getWidth() - lineWidth)
                        , padding
                        , 0.5f * (getWidth() + lineWidth)
                        , getHeight() - padding);
                paint.setStyle(Style.FILL);
                paint.setColor(Color.GRAY);
                paint.setAntiAlias(true);
                canvas.drawRect(rect, paint);

                // draw seek bar active range line
                rect.top = normalizedToScreen(normalizedMinValue);
                rect.bottom = 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(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 ? thumbPressedImage : thumbImage
                        ,(float) ((0.5f * getWidth()) - thumbHalfWidth) 
                        , screenCoord - thumbHalfHeight
                        , paint);
        }

        /**
         * Decides which (if any) thumb is touched by the given x-coordinate.
         * 
         * @param touchY
         *            The y-coordinate of a touch event in screen space.
         * @return The pressed thumb or null if none has been touched.
         */
        private Thumb evalPressedThumb(float touchY) {
                Thumb result = null;
                boolean minThumbPressed = isInThumbRange(touchY, normalizedMinValue);
                boolean maxThumbPressed = isInThumbRange(touchY, 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 = (touchY / getHeight() > 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 touchY
         *            The y-coordinate in screen space to check.
         * @param normalizedThumbValue
         *            The normalized x-coordinate of the thumb to check.
         * @return true if y-coordinate is in thumb range, false otherwise.
         */
        private boolean isInThumbRange(float touchY, double normalizedThumbValue) {
                return Math.abs(touchY - normalizedToScreen(normalizedThumbValue)) <= thumbHalfHeight;
        }

        /**
         * 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 * (getHeight() - 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 height = getHeight();
                if (height <= 2 * padding) {
                        // prevent division by zero, simply return 0.
                        return 0d;
                }
                else {
                        double result = (screenCoord - padding) / (height - 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");
                }
        }
}

Original issue reported on code.google.com by [email protected] on 2 Apr 2013 at 1:41

setSelectedMinValue and setSelectedMaxValue wont call OnRangeSeekBarChangeListener

What steps will reproduce the problem?
1. Create a RangeSeekBar in the layout
2. Add a setOnRangeSeekBarChangeListener to the RangeSeekBar object 
3. Call setSelectedMinValue or setSelectedMaxValue on the RangeSeekBar object

What is the expected output? What do you see instead?

I expected the OnRangeSeekBarChangeListener to be called.

What version of the product are you using? On what operating system?

Android ofc :)

Please provide any additional information below.

It's easy to fix the issue: Just add this code at the end of 
setNormalizedMinValue and setNormalizedMaxValue:

if(listener != null) {
    listener.onRangeSeekBarValuesChanged(this, getSelectedMinValue(), getSelectedMaxValue());
}

Greetings

Timo

Original issue reported on code.google.com by [email protected] on 19 Apr 2012 at 6:08

Range seekbar in android

I want to get the seek bar with two thumbs..and the seek bar range also has to 
be defined by me..I want this code..
please help me in this issue..

Original issue reported on code.google.com by [email protected] on 18 Jun 2013 at 7:10

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 14 Jul 2014 at 12:18

Unable to start activity ComponentInfo

What steps will reproduce the problem?
1.
2.
3.

What is the expected output? What do you see instead?


What version of the product are you using? On what operating system?


Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 30 Jul 2015 at 11:26

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 14 Mar 2014 at 4:05

Integer rounding bug.

In some rare cases the function new Integer((int) value) in the toNumber(double 
value) function works wrong. 

When I debug it, I got 2.999999 for the value and when you simple cast it to 
(int) it will be 2. 

Instead, I changed the line into this and it works very good. 
                                return new Integer((int) Math.round(value));


Original issue reported on code.google.com by [email protected] on 13 Mar 2014 at 12:34

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 9 Apr 2014 at 6:54

how to set corner sharp for the seekbar line

What steps will reproduce the problem?
1.
2.
3.

What is the expected output? What do you see instead?


What version of the product are you using? On what operating system?


Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 12 Jun 2013 at 1:09

Code review request

Purpose of code changes on this branch:


When reviewing my code changes, please focus on:


After the review, I'll merge this branch into:
/trunk


Original issue reported on code.google.com by [email protected] on 13 Jul 2014 at 6:08

Touching the seekbar will scroll up in a scrollable layout

What steps will reproduce the problem?
1. Add the range seeker into a scrollable layout
2. Tap the range seeker (or drag)

What is the expected output? What do you see instead?

The layout should not scroll/change position. However, as soon as I touch the 
range seeker, it scrolls on top. This makes it hard to use.

Am I doing something wrong here or is there a trick to solve this?



Original issue reported on code.google.com by [email protected] on 19 Jan 2012 at 12:28

Added ability to have multiple colors

You can contact me at [email protected]

Purpose of code changes on this branch:
*****
     My need was for there to be different color on each side of the thumbs points.
*****


When reviewing my code changes, please focus on:
*****
     Added two class initialization parts at lines 164 and 210 RangeSeekBar.java

     Modified the onDraw to handle the different colors starting at line 505 RangeSeekBar.java
******

Did not know if you would want to add this to your project. But thanks for 
making it available to the community. It saved me a lot of work.

Original issue reported on code.google.com by [email protected] on 22 Jun 2012 at 7:22

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.