DiscreteSeekBar

Overview

#DiscreteSeekBar

screenshot

screenshot

DiscreteSeekbar is my poor attempt to develop an android implementation of the Discrete Slider component from the Google Material Design Guidelines.

##Prologe I really hope Google provides developers with a better (and official) implementation ;)

##Warning After a bunch of hours trying to replicate the exact feel of the Material's Discrete Seekbar, with a beautiful stuff-that-morphs-into-other-stuff animation I was convinced about releasing the current code.

android.util.Log.wtf("WARNING!! HACKERY-DRAGONS!!");

I've done a few bit of hacky cede and a bunch of things I'm not completely proud of, so use under your sole responsibility (or help me improve it via pull-requests!)

##Implementation details This thing runs on minSDK=7 (well, technically could run 4 but can't test since AVDs for api 4 are deprecated and just don't boot). Obviously some of the subtle animations (navigating with the Keyboard, the Ripple effect, text fade ins/fade outs, etc) are not going to work on APIS lower than 11, but the bubble thing does. And I haven't found a way of improving this with 11-21 APIs, so...

The base SeekBar is pretty simple. Just 3 drawables for the track, progress and thumb. Some touch event logic to drag, some key event logic to move, and that's all.

It supports custom ranges (custom min/max), even for negative values.

The bubble thing DOESN'T USE VectorDrawableMagic . I was not really needed for such a simple morph. It uses instead an Animatable Drawable for the animation with a lot of hackery for callbacks, drawing and a bunch of old simple math.

For this to work (and sync with events, etc) I've written a fair amount of shit questionable code...

The material-floating-thing is composed into the WindowManager (like the typical overflow menus) to be able to show it over other Views without needing to set the SeekBar big enough to account for the (variable) size of he floating thing.

For this I'm not sure about the amounts of things I've copied from PopupWindow and the possible issues.

##Dependencies It uses com.android.support:support-v4 as the only dependency.

##Usage This is published in jCenter so you need to use the appropiate repo:

repositories {
    jcenter()
}

dependencies {
    compile 'org.adw.library:discrete-seekbar:1.0.1'
}

Once imported into your project, you just need to put them into your layous like:

<org.adw.library.widgets.discreteseekbar.DiscreteSeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:dsb_min="2"
        app:dsb_max="15"
/>

####Parameters You can tweak a few things of the DiscreteSeekbar:

  • dsb_min: minimum value
  • dsb_max: maximum value
  • dsb_value: current value
  • dsb_mirrorForRtl: reverse the DiscreteSeekBar for RTL locales
  • dsb_allowTrackClickToDrag: allows clicking outside the thumb circle to initiate drag. Default TRUE
  • dsb_indicatorFormatter: a string Format to apply to the value inside the bubble indicator.
  • dsb_indicatorPopupEnabled: choose if the bubble indicator will be shown. Default TRUE

####Design

  • dsb_progressColor: color/colorStateList for the progress bar and thumb drawable
  • dsb_trackColor: color/colorStateList for the track drawable
  • dsb_indicatorTextAppearance: TextAppearance for the bubble indicator
  • dsb_indicatorColor: color/colorStateList for the bubble shaped drawable
  • dsb_indicatorElevation: related to android:elevation. Will only be used on API level 21+
  • dsb_rippleColor: color/colorStateList for the ripple drawable seen when pressing the thumb. (Yes, it does a kind of "ripple" on API levels lower than 21 and a real RippleDrawable for 21+.
  • dsb_trackHeight: dimension for the height of the track drawable.
  • dsb_scrubberHeight: dimension for the height of the scrubber (selected area) drawable.
  • dsb_thumbSize: dimension for the size of the thumb drawable.
  • dsb_indicatorSeparation: dimension for the vertical distance from the thumb to the indicator.

You can also use the attribute discreteSeekBarStyle on your themes with a custom Style to be applied to all the DiscreteSeekBars on your app/activity/fragment/whatever.

##License

Copyright 2014 Gustavo Claramunt (Ander Webbs)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Adds plugin and details to upload to JCenter via bintray

    Adds plugin and details to upload to JCenter via bintray

    Uses this plugin https://github.com/novoda/bintray-release to make the library releaseable to JCenter().

    (after bintray website setup) You can release with this command:

    ./gradlew clean build bintrayUpload -PdryRun=false -PbintrayUser=BINTRAY_USERNAME -PbintrayKey=BINTRAY_KEY

    I just added the minimum config to the release details, but you can add a lot more if you want: https://github.com/novoda/bintray-release/wiki/Configuration-of-the-publish-closure

    Obviously the details are your choice, I just picked some sane defaults:

        userOrg = 'adw'
        groupId = 'org.adw.library'
        artifactId = 'discreteseekbar'
    

    Before you can push your release to BinTray you need to sign up by following these steps, which are straight forward enough: https://bintray.com/howbintrayworks#page11

    You can test your release with -PdryRun=true and it will create the files but not push them up the BinTray, if you are interested under the hood it performs the same actions as this http://blog.blundell-apps.com/locally-release-an-android-library-for-jcenter-or-maven-central-inclusion/

    opened by blundell 11
  • Can we use setOnSeekBarChangeListener?

    Can we use setOnSeekBarChangeListener?

    Hi I am new to android. Just checked your library. Can we use setOnSeekBarChangeListener in your seekbar? If so how? Awaiting your response at the earliest. Thanks in advance.

    opened by Telpr2 9
  • Moved initialization of metrics for PopupIndicator in onSizeChanged method.

    Moved initialization of metrics for PopupIndicator in onSizeChanged method.

    Fix for issue https://github.com/AnderWeb/discreteSeekBar/issues/53. In some cases, (ex. when activity containing seekBar don't recreate on rotations), PopupIndicator don't know about new display metrics, that causes indicator cut behavior when rotate from vertical layout to horizontal. To fix that, now PopupIndicator metrics initialized during onSizeChange state of SeekBar.

    opened by mrfix1t 5
  • Seek on single touch

    Seek on single touch

    The seekbar does not move to the touched position , instead user is forced to touch and move a bit. This behaviour greatly affects the user experience. Could you please make it seek-on-click? Any solutions for this?

    opened by vivekkartha 5
  • Issue 37 Fix

    Issue 37 Fix

    Fix Solving Basic Tap to set Progress as in Issue 37 (https://github.com/AnderWeb/discreteSeekBar/issues/37) Added

    • Setter, Getter and XML Attribute dsb_touch_slop
    • Changed Default Touch Slop to -1
    opened by Teja-Konjeti 5
  • Floaty Thing clipped on sides

    Floaty Thing clipped on sides

    When dragging the seekbar quickly, the floaty thing gets clipped on the sides. I'm assuming this is because the view window isn't large enough or something like that. A proposed fix would be to alter the window manager code so that the bubble floaty thing is allowed to draw on the entire width of the seekbar

    opened by AOrobator 5
  • cannot resolve dependency

    cannot resolve dependency

    i want to use these seekbar in my project,I write this in my build.gradle dependencies{ compile 'org.adw.library:discrete-seekbar:1.0.0' } and my gradle sync complete without mistakes. but i cannot import org.adw.samples.discretseekbar,what's wrong with my code?

    opened by a1154043439 4
  • Cutting bubble on screen rotate

    Cutting bubble on screen rotate

    https://i.gyazo.com/0765c4c94eb04a16335b1fc1880f9bea.gif

    Have changed screen orientation to horizontal: bubble hides on a half way. But if app starts in horizontal – it's OK.

    opened by lewkka 3
  • How to change progress color for disabled DiscreteSeekBar?

    How to change progress color for disabled DiscreteSeekBar?

    I am using DiscreteSeekBar, And it is working like a charm. I want to change the progress color of DiscreteSeekBar if it is in disabled state. How can i do that? Any hint will be appreciated. Thanks for this awesome libarary. :+1:

    opened by Dhaval2404 3
  • Indicator dismisses before releasing touch.

    Indicator dismisses before releasing touch.

    Thank you for such nice component!

    This issue happens on my device galaxy S2, android 4.0.4. But everything is OK on my another device which runs 4.2.2.

    Indicator pops up as soon as I touch it, and then dismisses quickly before I release or begin to drag.

    I guess hideFloater was invoked by accident before my releasing. I debugged. It turns out that I'm wrong.

    Any idea? Thank you.

    opened by ladjzero 3
  • Change size of indicator

    Change size of indicator

    I want to change the size of indicator in order to adjust my text there, I reduced textSize to 8sp but it is still trimming. How can I change the size of indicator or more specifically PopupIndicator. Another thing, I add drawable to indicator instead of color, is it possible and how?

    Thanks in advance.

    opened by HassanJawed 3
  • Slider crashes on Android Q (Preview edition)

    Slider crashes on Android Q (Preview edition)

    Crashes the moment you attempt to scroll when using on Android Q (Preview)... This works perfectly on all recent Android versions prior to Q.

    Stacktrace attached:

    java.lang.IllegalArgumentException: path must be convex at android.graphics.Outline.setConvexPath(Outline.java:286) at org.adw.library.widgets.discreteseekbar.internal.compat.SeekBarCompatDontCrash$1.getOutline(SeekBarCompatDontCrash.java:44) at android.view.View.rebuildOutline(View.java:16874) at android.view.View.invalidateDrawable(View.java:22071) at android.graphics.drawable.Drawable.invalidateSelf(Drawable.java:456) at org.adw.library.widgets.discreteseekbar.internal.drawable.MarkerDrawable.updateAnimation(MarkerDrawable.java:148) at org.adw.library.widgets.discreteseekbar.internal.drawable.MarkerDrawable.access$400(MarkerDrawable.java:46) at org.adw.library.widgets.discreteseekbar.internal.drawable.MarkerDrawable$1.run(MarkerDrawable.java:191) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:981) at android.view.Choreographer.doCallbacks(Choreographer.java:791) at android.view.Choreographer.doFrame(Choreographer.java:722) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:966) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:209) at android.app.ActivityThread.main(ActivityThread.java:7021) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:486) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:872)

    opened by ayqooi 6
  • Discrete seekbar use in kotlin

    Discrete seekbar use in kotlin

    Is there possible to use this library in kotlin? I got the error in seekbar change listner below method to convert in kotlin

    seekbar.setOnProgressChangeListener(new DiscreteSeekBar.OnProgressChangeListener() { @Override public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) { Toast.makeText(getApplicationContext(), "Value Changed "+value , Toast.LENGTH_LONG).show(); }

    @Override
    public void onStartTrackingTouch(DiscreteSeekBar seekBar) {
    
    }
    
    @Override
    public void onStopTrackingTouch(DiscreteSeekBar seekBar) {
    
    }
    

    });

    While importing module in kotlin i got below error

    Unable to load class 'org.gradle.api.internal.component.Usage'. Possible causes for this unexpected error include: Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.) Re-download dependencies and sync project (requires network)

    The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem. Stop Gradle build processes (requires restart)

    Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.

    In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

    What can i do ?Please help..

    opened by ishank1610 0
  • Migrate to AndroidX

    Migrate to AndroidX

    We are using this library since long time and it works great. We have recently Migrating to AndroidX, although by adding android.enableJetifier=true and android.useAndroidX=true in gradle.properties converts all support package of dependency at build time. The stable release of 28.0.0 will be the final feature release packaged as android.support. All subsequent feature releases will only be made available as androidx-packaged artifacts. For more detail please check. I suggest you to update the library with AndroidX to avoid confusion.

    opened by persource 0
  • Bubble animation breaks when setting new max value

    Bubble animation breaks when setting new max value

    I have the following onStopTrackingTouch listener:

     @Override
      public void onStopTrackingTouch(DiscreteSeekBar seekBar) {
           viewModel.updateValue(seekBar.getProgress());
      }
    

    The viewModel observer eventually updates the max value of the seekbar:

    this.viewModel.getSettings().observe(this, settings -> {
            this.boostValueSeekBar.setMax(settings.getMax());
            this.boostValueSeekBar.setProgress(settings.getValue());
    });
    

    Even if the max value does not change, the thumb handle disappears forever. The animation is also gone.

    This only appears to happen if the max value is changed as a direct result of onStopTrackingTouch.

    An easy test case is the following:

     @Override
      public void onStopTrackingTouch(DiscreteSeekBar seekBar) {
           seekBar.setMax(seekBar.getMax());
      }
    

    This will permanently break the indicator until the activity or fragment is reloaded.

    Expected behaviour At the very least I would expect setting the max value to the same value to do nothing (this can of course be done by the consumer as well). In all other cases I would expect the indicator to keep working when setting the max value from onStopTrackingTouch();

    opened by EZL0512 0
Owner
null