Giter Club home page Giter Club logo

ios-knob-control's Introduction

Knobs in the App Store

Dubsar

Dubsar

Dubsar is an open-source dictionary app by the same author that supports different themes (fonts, color schemes). A knob is used to select themes within the app. The theme changes as the knob rotates, including the theming of the generated discrete knob itself.

Dubsar is available for free on the App Store.

cpyn

cpyn audio settings cpyn cross feed settings cpyn reverb settings 1 cpyn reverb settings 2

cpyn is an audio-player app by the same author inspired by the Spin tab in the demo apps here. Unlike the demo here, cpyn provides an array of audio features like equalization, reverb and cross fading. It also allows you to play in reverse and scratch records as they play.

Quite a few generated continuous knobs appear to adjust various audio settings. Unlike the demos here, the knob control is not used for the turntable, which is entirely built on OpenGL, not UIKit. Note that some settings support fine tuning via the vertical pan gesture vs. one-finger rotation.

Have an app in the App Store using this knob control? Get in touch, and I'll post your screenshot here.

iOS Knob Control

Spin   Continuous   Rotary Dial   Months

This is a generic, reusable knob control you can insert into any application. You may provide custom knob images or use the customizable default images. The control animates rotation of the image in response to one of several configurable gestures from the user. The knob has a number of configurable modes:

  • Linear return mode: Like a circular generalization of the UIPickerView control. Only certain discrete positions are allowed. The knob rotates to follow the user's gesture, but on release returns to an allowed position. The time scale for the return animation may be configured as a property of the control.
  • Wheel of Fortune mode: Like linear return, except for the animation after the user releases the knob. Only a narrow strip between each pair of segments is excluded, like the pegs on the rim of a carnival wheel. If the knob was released in one of those small excluded strips, it rotates just far enough to exit the excluded strip. Otherwise, the knob stays where the user leaves it. This mode is like continuous mode except for the behavior in the excluded strips and the availability of the positionIndex property.
  • Continuous mode: Like a circular generalization of the UISlider control or a potentiometer/volume knob. Often used with min. and max. angles, but can also be circular. Knob remains wherever the user leaves it and can attain any value between the min. and max. equally.
  • Rotary dial mode: Like an old rotary telephone dial.

It responds to four different gestures, depending on the value of a property:

  • One-finger rotation: Custom gesture recognition. The spot under your finger tracks your touch as you rotate the knob.
  • Two-finger rotation: The standard iOS two-finger rotation gesture.
  • Vertical pan: Drag your finger up or down to increase or decrease the value of the position property, respectively.
  • Tap: Select a position for the knob or dial a number in rotary dial mode by tapping.

The knob control can be circular, permitting the user to rotate it all the way around, or it can have a min. and max. angle in continuous and discrete modes.

The control is distributed as a single pair of files (IOSKnobControl.h and IOSKnobControl.m in this directory), which you can simply drop into your project. Without any externally supplied image, the control generates appropriate, customizable images in all modes. It can also accept externally supplied images. You can use any of the images in the demo project here or supply your own.

The knob control and all images must be square. Images will usually be circles or regular polygons, with a transparent background or a solid one that matches the view behind it. However, the aspect ratio must be 1:1. The effect of the animation is circular rotation. This only works if the control is square. You can produce other effects, for example, by partially clipping a square control or using an oblong background. But the control itself always has to be square.

The control honors the enabled property. That is, if you set enabled to NO, it enters the UIControlStateDisabled and stops responding to user input. If specified, a disabled image is displayed instead of the normal image. Even when disabled, the control's position may always be specified at any time programmatically, with or without animation. With appropriate images, a disabled knob control may be used as a dial view to display a numeric value.

There are two demo apps, one in Objective-C, in the KnobControlDemo-ObjC subdirectory, and one in Swift, in the KnobControlDemo-Swift subdirectory. Both exercise the same functionality using the same Objective-C knob control. Both demos contain projects that can be used to build a simple demo app to exercise the different modes of the control and provide examples of use. Both use storyboards and autolayout and so require iOS 6.0 or greater. The control works on 64-bit devices. (Swift requires both iOS 7.0 or greater on the device or simulator and Xcode6-Beta4 or later to compile Swift.)

The control itself, the IOSKnobControl class, may be compiled down to iOS 5.0, but the demo projects will not build if the iOS Deployment Target is set below 6.0 for reasons that have nothing to do with the control. The control uses ARC, so it cannot be used below iOS 5.0 without modification. It has not been tested below iOS 6.1, however, and there may be problems there that have not yet been discovered.

Violation

See iOS Knob Control and Violation.

Documentation

All API documentation can be found in IOSKnobControl.h. Browsable HTML documentation generated from this source is checked into this repository in the doc/html subdirectory. See doc/html/index.html.

Appledoc

The HTML documentation here is built with Appledoc. If you install Appledoc (from a distro like Homebrew or MacPorts or from source; see https://github.com/tomaz/appledoc#quick-install) you can use the build-appledoc script in this directory to update the HTML if it is out of date and install the documentation as a docset that you can view with XCode.

Releases

Stable releases are indicated by tags in the repo (e.g., 1.1.0.2) and notes in the ChangeLog. When in doubt, use the last stable release tag as opposed to the HEAD revision. If no development has been done since the last release, those may be the same revision.

Known Issues

Known bugs, planned enhancements and other issues are tracked on Github.

Media

Some images (the nice ones) courtesy of Mike Calvert (@bloodymonster).

License

The software and media here are available under The BSD 3-Clause License:

Copyright (c) 2013-14, Jimmy Dee
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions
   and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   and the following disclaimer in the documentation and/or other materials provided with the
   distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse
   or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGE.

ios-knob-control's People

Contributors

jdee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ios-knob-control's Issues

Get slide event

Hi!
Is there anyway to get an event callback when the user finishes the full sliding action on the knob?

Thank you and compliments for the component!

improve sharing between demo apps

This has nothing to do with the control, but at the moment, the two demo apps, Obj-C and Swift, are both complete standalone apps, each with its own asset catalog and storyboard, which are essentially identical between the two.

A quick attempt to symlink one asset catalog to the other failed, but at least it should be possible to link the individual images within the catalogs. And it may be possible to reuse storyboards.

How to do a continious rotation with set values per every 360 degrees?

Hi,
I am using the knob to allow the user to select between 1-600 and would like each full rotation of the dial cover 100 of the values (using WheelOfForutne) and ending at 6 rotations = 600.
How to I set the properties to handle that and how is min and max handled on continuous rotations. Can I start 0 position at a certain point (perhaps 0 degrees) and each time the rotation passes that, it bumps to the next 100?

John

min and max values not validated

The min property should take a value in (-M_PI,0] and the max property in [0,M_PI). These ranges should be enforced, just as the position property is limited to a certain range. If you try to set either of those properties outside the ranges above, they should take the nearest available values.

Shadows don't always resize properly

If you use NSLayoutConstraints properly, you can make the knob control resize continuously on rotation. But if you have shadows and use a shadow path (by setting the middleLayerShadowPath, foregroundLayerShadowPath and/or knobRadius properties), the shadow will not transform continuously with the control, which doesn't look very nice. You'll have to adjust it after the rotation is complete. If you don't use a shadow path, everything works fine, but the performance is not as good.

It is possible to animate the shadowPath property of a CALayer. Getting this right probably means something like:

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    super.willRotateToInterfaceOrientation(toInterfaceOrientation, duration: duration)
    let frame = computeNewFrameForKnobControl()
    knobControl.setFrame(frame, duration: duration)
}

With a new setFrame:duration: selector, you could properly animate the control with a rotation and in general animate the shadow path along with any change to the control frame.

A fix for this may wait until after the control moves to the Violation framework.

Provide a Swift demo

A demo app will be built in Swift. This may coexist with the Objective-C demo app for a time, but eventually the Obj-C demo app has to be retired.

configurable gesture

It may be desirable in some cases to provide support for other gestures. In particular, the stock two-finger rotation gesture and a simple vertical pan gesture may alternately be supported via an enumerated property.

control state hiccup on first rotation

The control should enter the UIControlStateHighlighted as long as a touch is down in its frame. What actually happens is that the control becomes highlighted as soon as a touch goes down, but as soon as the touch moves to drag the knob, the state returns to UIControlStateNormal. Then it quickly becomes UIControlStateHighlighted again and remains so until the pan gesture finally ends or is canceled.

This is due to default gesture recognition in the UIControl base class, which is responsible for the initial highlighted state on the first touch. Once the touch moves, that gesture is canceled, however, so the state quickly returns to UIControlStateNormal before becoming highlighted again once the pan gesture is recognized.

rotary dial subclass?

It might be best to break the knob control into two classes and make the rotary dialer a subclass of the knob control. This would clean up a lot of code. A rotary dialer isn't really a knob, and things like dialNumber: don't really belong in the knob control.

But as an app developer, I like solutions that come in a single code unit, with one .h and one .m file. It's really simple to grab something from GitHub and pop it into a project that way. Hence, I'm reluctant to build a lot of smaller code units and force the use of a framework.

However, I am going to be releasing some other open-source iOS components soon, and the iOS Knob Control will certainly at least be friends with that code base and probably join the family before too long. That project will definitely be a framework with multiple components, and the knob and rotary dial controls would make a nice fit.

This public repo will not go away any time soon, but it's likely over the coming months that this control will be deprecated in favor of the new project.

Poor performance with shadows

Shadows can be expensive. This issue is a work in progress. There has been a bit of optimization by precomputing shadow paths when possible. The rotary dial mode is still problematic. This isn't recognizable from the demo on late-model hardware, but it's an issue.

Want that Bounce Back during Number Dial

Hi Jee,

I am using IKCModeRotaryDial type but i have one problem as we dial number its rotating full. What i want if i select 5, 5 should touch Dial stop then back it should not rotate full.

I am using Objective-C code. It would be good if you can tell solution for that.

Thanks

control hops min/max boundary

The position of the knob is properly constrained, but if you set circular to NO, you can drag the knob past the min or max until it jumps to the far side.

control requires a holder

It's not clear why this is, but if you try programmatically just inserting a control with a certain frame, it tends to hug the upper lefthand corner of the superview. Use a holder view as in the storyboards in the demo apps here, even if making a view programmatically.

Poor behavior on resizing

If you change the frame of the control after initializing it, things don't work. This will be fixed.

Generated labels can be very small in discrete modes

Using .LinearReturn or .WheelOfFortune, it can be hard to squeeze more than half a dozen titles or so onto a knob. I'd like to do something like a dynamic zoom that would enlarge the size of the selected label at the top at least.

improve numbers in generated knobs/dials

The generated rotary dial view uses CATextLayers in the background to display the numbers on the dial. But the rendered text is blurry and pixelated. According to the doc:

CATextLayer disables sub-pixel antialiasing when rendering text.

This is the root of the problem.

There are three CALayers used as sublayers of the control view's layer. The bottom and top layers are stationary. Only the middle one rotates. This allows a finger stop to be rendered floating on top of the rotating dial in rotary dial mode, without interfering with gesture recognition.

The back layer is empty except for ten CATextLayer sublayers containing the digits.

A better mechanism than CATextLayer needs to be found.

This issue also arises in generated discrete knobs, when CATextLayers are used.

Cannot initialize a variable of type 'CTFontRef' with 'CFTypeRef'

Hello Guys,
I have imported the iOSKnobcontrol.h/.m in my project and at build time I am getting three different error in the iOSKnobControl.m file. I was able to run the demo fine, but in my own project it is creating the issue.

Please find attached the screenshots for more clearity.
Thanks.
screen shot 2017-02-15 at 6 44 16 pm
screen shot 2017-02-15 at 6 44 41 pm

imageless knob control

It needs to be possible to use the control in continuous and discrete modes without images. In particular, it should be possible to use it like a one-component picker view. It should not require anything beyond an array of strings to render the knob without a custom image.

no value changed events when position set programmatically

To conform to the behavior of other UIControl implementations (like UISlider), the IOSKnobControl should only generate a UIControlEventValueChanged in response to a user gesture. When the position is programmatically set (knobControl.position = x), no such event should be generated.

square image and aspect ratio not enforced

If the images used and the control itself are not square, the animation simply doesn't work. There may be some ways to work with an oblong control, but if the image is not square, the rotation animation will break. This should be enforced by the control. At the very least, the setImage:forState: method should ignore any image that is not square.

incorrect animation in rotary dial mode

Using the one-finger rotation gesture, if you drag your finger quickly from the 1 past the finger stop, the dial will abruptly jump back to its rest position.

rotary dial mode

This is not terribly difficult. It will depend on having a decent image, which can probably be found somewhere on the web or produced without much trouble.

The main code change will be to have the positionIndex property read the position selected by the user even after the return animation completes, until the user dials again. That could include the position property as well. This is at any rate different from the way the current discrete modes work.

This is planned some time after the initial release.

Attributed strings for titles

I plan to allow NSAttributedString instances for titles in the generated discrete knobs. That way, for example, you could use a different font for each title.

further customization hooks

A lot of the interface to the IOSKnobControl class has been based on UIButton, particularly things like imageForState: and titleColorForState:. UIButton has in common with this control that it can use a custom image or images, but if you don't supply any, it will supply a default image using text you provide (in the discrete case) or even default text in the case of the IOSKnobControl. And while it honors the tintColor property and tries to choose a consistent set of colors for different states, you can override all these choices using setTitleColor:forState:, setFillColor:forState and the titles property.

UIButton provides further customization options that may or may not make sense for the IOSKnobControl.

  • Background image per state: This is something an app developer cannot easily do with the current control. The control could have new methods backgroundImageForState: and setBackgroundImage:forState: like UIButton. But then shouldn't it also have a configurable background color per state as well, in case you're not using custom images? But UIButton doesn't have this. And currently the knob control has no background. It is transparent, and whatever host view you put it in shows through as the background. Adding a background image per state would probably mean yet a third CALayer.
  • Title(s) per state: Where UIButton has one title to display, the knob control has many, the number specified by the positions property. It's not clear if the titles on the knob should also be configurable per state, since the positions they mark don't change. If this were required, the control would need something like (NSArray_)titlesForState:(UIControlState)state or (NSString_)titleForPositionIndex:(NSInteger)positionIndex andState:(UIControlState)state and a related setter.

Background is white box?

Hi,
Using the sample code with swift, I have a IOSKnobControl with a background image. The background image is circular with transparent corners. But the IOSKnobControl renders with a white background behind the image. I don't understand what I am doing wrong here.

I think it has something to do with the IOSKnobControl holder (a UIView) but I can't figure it out.
Any idea?

inconsistencies in handling of positionIndex

For one thing, the position property is constrained to (-M_PI,M_PI]. This mostly matches the return range of atan2, it's attractive because of its symmetry, and it's easier/natural to start with the control at 0 and enforce min and max with a continuous range with 0 at the center. The absolute value of min is the farthest you can go from the initial position in the negative direction; the value of max is the farthest you can go in the positive direction.

However, I like to interpret positionIndex as something like an array index. I like to use it to select from a sequentially numbered enumeration by doing something like:

MyEnum selectedValue = MyEnumFirstValue + knobControl.positionIndex;

Hence, positionIndex returns a 0-based index. This is true regardless of the value of circular. If circular is NO, the segments are sequentially numbered starting with the one closest to min, which has index 0. If circular is YES, the segments are numbered from 0 to 2*M_PI, with the first segment (index 0) centered at 0. The control always starts at position 0 by default. When using a discrete mode (IKCMLinearReturn or IKCMWheelOfFortune), if circular is YES, positionIndex will initially be 0; if NO, positionIndex will be positions/2.

For now, all solutions seem to have drawbacks. This will simply remain a known, documented issue until a clear solution emerges.

runtime version check

The recommended way to use the control is just to drop the .h and .m files into an application project. But it's possible I might eventually build it into a library or that someone else could do so. In case the object file was compiled separately from the application, it's a good idea to validate that IKC_VERSION == IKC_TARGET_VERSION && IKC_BUILD == IKC_TARGET_BUILD at runtime, in all constructors. In any other language, I'd throw an exception in that case, but in Objective-C, it might be better to go with a @Property (nonatomic, readonly) BOOL valid. That property could be set to NO for any number of reasons. There could also be an error message property or something similar.

For now, the likelihood of this being a problem is very small, so I'm considering it an enhancement.

faulty knob animation

There is a problem with the way the knob animation is handled when the setPosition: method is called. The default handling of the transformation by the CALayer on iOS 7+ is too slow to keep up with a fast rotation without an explicit animation. The knob typically lags the finger that rotates it, and rotating too fast can confuse it and make it rotate the wrong way.

Fortunately, the fix is easy, effective and forthcoming presently.

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.