41 Commits

Author SHA1 Message Date
Ramotion 98c787c0d4 Update README.md 2020-04-06 10:02:45 +03:00
igor.k 68e2df9512 iOS 13 hot fix 2019-11-13 03:47:57 +03:00
igor.k c41cd1687b add SPM config 2019-11-13 03:28:07 +03:00
Ramotion 99d0951432 Update README.md 2019-10-12 21:14:16 +03:00
Alex K 15617cc501 bump version 2019-04-03 15:08:27 +03:00
Alex K bf9930968b converted to swift 5 2019-04-03 15:04:53 +03:00
Alex K 4ce9c82b37 bump version 2019-03-06 09:59:05 +03:00
Alex K c7aad6709e Merge branch 'master' of github.com:Ramotion/fluid-slider 2019-03-06 09:32:01 +03:00
Alex K db7027f83a fix 2019-03-06 09:31:47 +03:00
Alex deca1502db Merge pull request #31 from rishi420/master
Allow override init to make custom class fixes #19
2019-03-06 09:26:49 +03:00
Warif Akhand Rishi 3179730d3d Allow override init to make custom class fixes #19 2019-03-06 11:58:41 +06:00
Ramotion f69257e0e8 Update README.md 2019-01-08 11:45:08 +03:00
Ramotion f336343cae Update README.md 2018-12-10 11:55:27 +03:00
Ramotion a2ee6a1584 Update README.md 2018-12-10 10:17:42 +03:00
Alex K 7acf118741 swift 4.2 2018-09-27 09:33:29 +03:00
Ramotion e716e1a91f Update README.md 2018-06-29 14:21:08 +03:00
Ramotion 7b05e78b03 Update README.md 2018-06-26 11:19:35 +03:00
Ramotion 4e2eb1fcc7 Update README.md 2018-05-29 12:04:48 +03:00
Ramotion 6301985395 Update README.md 2018-04-28 16:04:19 +03:00
Ramotion c191997683 Add files via upload 2018-04-28 06:03:22 -07:00
Ramotion 719cb3e14d Update README.md 2018-04-19 11:12:45 +03:00
Alex ebb0d57822 Update README.md 2018-03-22 09:47:45 +03:00
Ramotion 1e81b746d7 Update README.md 2018-03-13 10:22:37 +03:00
Alex Mikhnev 141cb106c5 Update README.md 2018-02-21 14:38:21 +03:00
Vlad I 27d1ee69ee Update README.md 2018-02-05 16:43:42 +03:00
Vlad I 133a5fab44 Update README.md 2018-02-05 16:29:23 +03:00
i.kolpachkov 4ba849f057 add swift-version file 2018-01-18 17:02:04 +03:00
i.kolpachkov 60d2be5777 bump pod version 2018-01-18 16:52:56 +03:00
i.kolpachkov 36a7d8e640 small cleanup, fix warnings, update launch screen 2018-01-18 16:51:55 +03:00
Alex K d0b81d70e1 update podspec 2018-01-10 17:54:13 +03:00
Alex 17e0441e4b Merge pull request #11 from boherna/master
Adds the open access level to isAnimationEnabled and isSliderTracking…
2018-01-10 17:51:43 +03:00
Bohdan Hernandez 9b6251017f Adds the open access level to isAnimationEnabled and isSliderTracking to make them accessible. 2018-01-10 13:34:19 +00:00
Juri Vasylenko 515e89d070 Update README.md 2018-01-07 18:49:01 +03:00
Alex Mikhnev da0b11bc42 Update README.md 2018-01-03 10:46:53 +03:00
Alex K a3721925c0 update podspec 2017-12-27 11:26:38 +03:00
Alex 71c5e1e1f2 Merge pull request #9 from boherna/master
Allows setting minimum and maximum images. Updates the Example project.
2017-12-27 11:21:51 +03:00
Bohdan Hernandez 257c2978cf Allows to optionally disable the valueView animation. 2017-12-22 22:04:26 +00:00
Bohdan Hernandez 7536c76155 Allows to optionally show the fraction value only while tracking. 2017-12-22 21:35:50 +00:00
Bohdan Hernandez c1c17bee86 Updates the Example project to show how to set the minimum and maximum images. 2017-12-22 15:07:22 +00:00
Bohdan Hernandez 1a9daa850d Allows setting minimum and maximum images along with their margin and color. 2017-12-22 15:06:24 +00:00
Alex K 425e0082b4 update podspec 2017-12-20 18:04:12 +03:00
22 changed files with 312 additions and 96 deletions
+1
View File
@@ -0,0 +1 @@
4.2
+8 -3
View File
@@ -150,11 +150,12 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0900;
LastUpgradeCheck = 0900;
LastUpgradeCheck = 1000;
ORGANIZATIONNAME = "Dmitry Nesterenko";
TargetAttributes = {
1176CDF51F97F97400C75DFC = {
CreatedOnToolsVersion = 9.0.1;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
@@ -279,6 +280,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -286,6 +288,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -336,6 +339,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -343,6 +347,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -387,7 +392,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.chebur.Example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -407,7 +412,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.chebur.Example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
+1 -27
View File
@@ -13,34 +13,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
@@ -103,8 +103,9 @@
"scale" : "2x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Ramotion.png",
"scale" : "1x"
}
],
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "banana.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "cake.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@@ -10,16 +14,40 @@
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2018 Ramotion. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fcf-sN-ku0">
<rect key="frame" x="16" y="630" width="343" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Fluid Slider" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bCd-3b-lHA">
<rect key="frame" x="141.5" y="323" width="92" height="21"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<constraints>
<constraint firstItem="fcf-sN-ku0" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leadingMargin" id="811-hI-Egq"/>
<constraint firstItem="bCd-3b-lHA" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="T4x-O3-JqD"/>
<constraint firstItem="bCd-3b-lHA" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="VFr-tp-sPw"/>
<constraint firstItem="fcf-sN-ku0" firstAttribute="trailing" secondItem="Ze5-6b-2t3" secondAttribute="trailingMargin" id="dS9-pv-ebe"/>
<constraint firstItem="xb3-aO-Qok" firstAttribute="top" secondItem="fcf-sN-ku0" secondAttribute="bottom" constant="20" id="kbD-dX-t3N"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
<point key="canvasLocation" x="52" y="374.66266866566718"/>
</scene>
</scenes>
</document>
+16 -5
View File
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13174"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
@@ -21,23 +21,33 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="26J-5w-SBc">
<rect key="frame" x="16" y="243.5" width="343" height="54"/>
<rect key="frame" x="16" y="203.5" width="343" height="54"/>
<string key="text">If you know how many calories you ate use the slider below to add them to your daily diary without having to search the specific foods.</string>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BlG-BI-dyo" customClass="Slider" customModule="Slider">
<rect key="frame" x="16" y="321.5" width="343" height="44"/>
<rect key="frame" x="16" y="281.5" width="343" height="44"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="xYl-Vg-d9W"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AY8-ee-HcY" customClass="Slider" customModule="Slider">
<rect key="frame" x="16" y="395.5" width="343" height="44"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="VKG-sm-ddv"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="BlG-BI-dyo" secondAttribute="trailing" id="4HA-D7-s4l"/>
<constraint firstItem="BlG-BI-dyo" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerYWithinMargins" id="gMp-l4-NZA"/>
<constraint firstItem="AY8-ee-HcY" firstAttribute="top" secondItem="BlG-BI-dyo" secondAttribute="bottom" constant="70" id="5VW-AC-mBt"/>
<constraint firstItem="AY8-ee-HcY" firstAttribute="leading" secondItem="BlG-BI-dyo" secondAttribute="leading" id="SSJ-0e-5l7"/>
<constraint firstItem="AY8-ee-HcY" firstAttribute="trailing" secondItem="BlG-BI-dyo" secondAttribute="trailing" id="Yvw-XF-Lbz"/>
<constraint firstItem="BlG-BI-dyo" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerYWithinMargins" constant="-40" id="gMp-l4-NZA"/>
<constraint firstItem="26J-5w-SBc" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" id="hoq-H8-M5b"/>
<constraint firstItem="BlG-BI-dyo" firstAttribute="top" secondItem="26J-5w-SBc" secondAttribute="bottom" constant="24" id="izw-iy-Rv2"/>
<constraint firstAttribute="trailingMargin" secondItem="26J-5w-SBc" secondAttribute="trailing" id="xkK-EP-ZPV"/>
@@ -48,6 +58,7 @@
<connections>
<outlet property="label" destination="26J-5w-SBc" id="sYN-sj-4xR"/>
<outlet property="slider" destination="BlG-BI-dyo" id="siw-gJ-6ld"/>
<outlet property="sliderWithImages" destination="AY8-ee-HcY" id="Ztl-5M-G82"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+21 -1
View File
@@ -13,11 +13,12 @@ class ViewController: UIViewController {
@IBOutlet var label: UILabel!
@IBOutlet var slider: Slider!
@IBOutlet var sliderWithImages: Slider!
override func viewDidLoad() {
super.viewDidLoad()
let labelTextAttributes: [NSAttributedStringKey : Any] = [.font: UIFont.systemFont(ofSize: 12, weight: .bold), .foregroundColor: UIColor.white]
let labelTextAttributes: [NSAttributedString.Key : Any] = [.font: UIFont.systemFont(ofSize: 12, weight: .bold), .foregroundColor: UIColor.white]
slider.attributedTextForFraction = { fraction in
let formatter = NumberFormatter()
formatter.maximumIntegerDigits = 3
@@ -39,6 +40,25 @@ class ViewController: UIViewController {
slider.didEndTracking = { [weak self] _ in
self?.setLabelHidden(false, animated: true)
}
sliderWithImages.attributedTextForFraction = { fraction in
let formatter = NumberFormatter()
formatter.maximumIntegerDigits = 3
formatter.maximumFractionDigits = 0
let string = formatter.string(from: (fraction * 800 + 100) as NSNumber) ?? ""
return NSAttributedString(string: string, attributes: [.font: UIFont.systemFont(ofSize: 12, weight: .bold), .foregroundColor: UIColor.black])
}
sliderWithImages.setMinimumImage(UIImage(named: "banana"))
sliderWithImages.setMaximumImage(UIImage(named: "cake"))
sliderWithImages.imagesColor = UIColor.white.withAlphaComponent(0.8)
sliderWithImages.setMinimumLabelAttributedText(NSAttributedString(string: "", attributes: labelTextAttributes))
sliderWithImages.setMaximumLabelAttributedText(NSAttributedString(string: "", attributes: labelTextAttributes))
sliderWithImages.fraction = 0.5
sliderWithImages.shadowOffset = CGSize(width: 0, height: 10)
sliderWithImages.shadowBlur = 5
sliderWithImages.shadowColor = UIColor(white: 0, alpha: 0.1)
sliderWithImages.contentViewColor = UIColor.purple
sliderWithImages.valueViewColor = .white
}
private func setLabelHidden(_ hidden: Bool, animated: Bool) {
+43
View File
@@ -0,0 +1,43 @@
// swift-tools-version:5.1
//
// Package.swift
//
// Copyright (c) Ramotion (https://www.ramotion.com/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import PackageDescription
let package = Package(
name: "FluidSlider",
platforms: [
.iOS(.v10)
],
products: [
.library(name: "FluidSlider",
targets: ["FluidSlider"]),
],
targets: [
.target(name: "FluidSlider",
path: "Sources")
],
swiftLanguageVersions: [.v5]
)
+52 -27
View File
@@ -1,30 +1,39 @@
![header](./header.png)
![preview](./preview.gif)
<a href="https://www.ramotion.com/agency/app-development/?utm_source=gthb&utm_medium=repo&utm_campaign=fluid-slider"><img src="https://github.com/Ramotion/folding-cell/blob/master/header.png"></a>
# Fluid Slider
[![Twitter](https://img.shields.io/badge/Twitter-@Ramotion-blue.svg?style=flat)](http://twitter.com/Ramotion)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Ramotion/fluid-slider)
[![codebeat badge](https://codebeat.co/badges/6f67da5d-c416-4bac-9fb7-c2dc938feedc)](https://codebeat.co/projects/github-com-ramotion-fluid-slider)
<a href="https://github.com/Ramotion/folding-cell">
<img align="left" src="https://github.com/Ramotion/fluid-slider/blob/master/fluid-slider.gif" width="480" height="360" /></a>
<p><h1 align="left">FLUID SLIDER</h1></p>
<h4>A slider widget with a popup bubble displaying the precise value selected written on Swift.</h4>
___
<p><h6>We specialize in the designing and coding of custom UI for Mobile Apps and Websites.</h6>
<a href="https://www.ramotion.com/agency/app-development/?utm_source=gthb&utm_medium=repo&utm_campaign=fluid-slider">
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a>
</p>
<p><h6>Stay tuned for the latest updates:</h6>
<a href="https://goo.gl/rPFpid" >
<img src="https://i.imgur.com/ziSqeSo.png/" width="156" height="28"></a></p>
Inspired by [Virgil Pana](https://dribbble.com/virgilpana) [shot](https://dribbble.com/shots/3868232-Fluid-Slider)
**Looking for developers for your project?**<br>
This project is maintained by Ramotion, Inc. We specialize in the designing and coding of custom UI for Mobile Apps and Websites.
</br>
<a href="https://ramotion.com/?utm_source=gthb&utm_medium=special&utm_campaign=fluid-slider-contact-us/#Get_in_Touch">
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a> <br>
The [iPhone mockup](https://store.ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=fluid-slider) available [here](https://store.ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=fluid-slider).
## Try this UI control in action
<a href="https://itunes.apple.com/app/apple-store/id1182360240?pt=550053&ct=gthb-fluid-slider&mt=8" > <img src="https://github.com/Ramotion/navigation-stack/raw/master/Download_on_the_App_Store_Badge_US-UK_135x40.png" width="170" height="58"></a>
[![Twitter](https://img.shields.io/badge/Twitter-@Ramotion-blue.svg?style=flat)](http://twitter.com/Ramotion)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Ramotion/fluid-slider)
[![codebeat badge](https://codebeat.co/badges/6f67da5d-c416-4bac-9fb7-c2dc938feedc)](https://codebeat.co/projects/github-com-ramotion-fluid-slider)
[![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/Ramotion)
## Requirements
iOS 10.0
Xcode 9
Swift 4.0
- iOS 10.0
- Xcode 9
- Swift 4.0
## Installation
You can install `fluid-slider` in several ways:
@@ -49,6 +58,10 @@ github "Ramotion/fluid-slider"
### Slider
```swift
import fluid_slider
```
The slider can be inserted in a view hierarchy as a subview. Appearance can be configured with a number of public attributes:
```swift
@@ -90,16 +103,28 @@ There are a couple of callbacks which allow you to listen to the slider's tracki
This control is designed to use device CPU resources with care. The fluid-style animation will be disabled when low power mode is enabled or the system is under heavy load.
# Get the Showroom App for iOS to give it a try
This library is a part of a <a href="https://github.com/Ramotion/swift-ui-animation-components-and-libraries"><b>selection of our best UI open-source projects.</b></a>
## 🗂 Check this library on other language:
<a href="https://github.com/Ramotion/fluid-slider-android">
<img src="https://github.com/Ramotion/navigation-stack/blob/master/Android_Kotlin@2x.png" width="178" height="81"></a>
## 📄 License
Fluid Slider is released under the MIT license.
See [LICENSE](./LICENSE) for details.
This library is a part of a <a href="https://github.com/Ramotion/swift-ui-animation-components-and-libraries"><b>selection of our best UI open-source projects.</b></a>
If you use the open-source library in your project, please make sure to credit and backlink to https://www.ramotion.com/
## 📱 Get the Showroom App for iOS to give it a try
Try this UI component and more like this in our iOS app. Contact us if interested.
<a href="https://itunes.apple.com/app/apple-store/id1182360240?pt=550053&ct=fluid-slider&mt=8" >
<img src="https://github.com/ramotion/gliding-collection/raw/master/app_store@2x.png" width="117" height="34"></a>
<a href="https://ramotion.com/?utm_source=gthb&utm_medium=special&utm_campaign=fluid-slider/#Get_in_Touch">
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a>
<br>
<br>
Follow us for the latest updates<br>
[![Twitter URL](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=https://github.com/ramotion/fluid-slider)
[![Twitter Follow](https://img.shields.io/twitter/follow/ramotion.svg?style=social)](https://twitter.com/ramotion)
<a href="https://www.ramotion.com/agency/app-development/?utm_source=gthb&utm_medium=repo&utm_campaign=fluid-slider">
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a>
+9 -4
View File
@@ -112,12 +112,12 @@
1176CDCF1F97F87F00C75DFC /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0900;
LastUpgradeCheck = 1000;
ORGANIZATIONNAME = "Dmitry Nesterenko";
TargetAttributes = {
1176CDD71F97F87F00C75DFC = {
CreatedOnToolsVersion = 9.0.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
@@ -128,6 +128,7 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 1176CDCE1F97F87F00C75DFC;
productRefGroup = 1176CDD91F97F87F00C75DFC /* Products */;
@@ -196,6 +197,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -203,6 +205,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -256,6 +259,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -263,6 +267,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -316,7 +321,7 @@
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -341,7 +346,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.chebur.Slider;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
LastUpgradeVersion = "1000"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,7 +26,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -37,7 +36,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
+1 -1
View File
@@ -60,7 +60,7 @@ class MetaballFilter : CIFilter {
guard let inputImage = inputImage else { return nil }
// color
var image = CIFilter(name: "CIColorControls", withInputParameters: [kCIInputBrightnessKey: 1, kCIInputSaturationKey: 0, kCIInputContrastKey: 0, kCIInputImageKey: inputImage])?.outputImage
var image = CIFilter(name: "CIColorControls", parameters: [kCIInputBrightnessKey: 1, kCIInputSaturationKey: 0, kCIInputContrastKey: 0, kCIInputImageKey: inputImage])?.outputImage
// blur
image = image?.applyingGaussianBlur(sigma: Double(blurRadius))
+81 -10
View File
@@ -22,7 +22,7 @@ private func isAnimationAllowed() -> Bool {
let isSimulator = TARGET_OS_SIMULATOR != 0
return !isSimulator && !ProcessInfo.processInfo.isLowPowerModeEnabled && !UIAccessibilityIsReduceMotionEnabled() && !isUnderHighload
return !isSimulator && !ProcessInfo.processInfo.isLowPowerModeEnabled && !UIAccessibility.isReduceMotionEnabled && !isUnderHighload
}
open class Slider : UIControl {
@@ -40,7 +40,7 @@ open class Slider : UIControl {
// MARK: - Initialization
override init(frame: CGRect) {
override public init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
@@ -60,6 +60,8 @@ open class Slider : UIControl {
addSubview(contentView)
contentView.addSubview(backgroundImageView)
contentView.addSubview(minimumImageView)
contentView.addSubview(maximumImageView)
contentView.addSubview(minimumLabel)
contentView.addSubview(maximumLabel)
contentView.addSubview(valueView)
@@ -82,6 +84,12 @@ open class Slider : UIControl {
layoutValueView()
}
}
open var showFractionOnlyWhileTracking = false {
didSet {
updateValueViewText()
}
}
open var attributedTextForFraction: (CGFloat) -> (NSAttributedString) = { fraction in
let formatter = NumberFormatter()
@@ -112,11 +120,46 @@ open class Slider : UIControl {
valueView.outerFillColor = contentViewColor
valueView.innerFillColor = valueViewColor
}
open var isAnimationEnabled = true
private(set) open var isSliderTracking = false
private func updateValueViewText() {
let text = attributedTextForFraction(fraction)
valueView.attributedText = text
if !showFractionOnlyWhileTracking || isSliderTracking {
let text = attributedTextForFraction(fraction)
valueView.attributedText = text
} else {
valueView.attributedText = nil
}
}
// MARK: - Images
private let minimumImageView = UIImageView()
private let maximumImageView = UIImageView()
open var imagesMargin: CGFloat = 10 {
didSet {
layoutImageViews()
}
}
open var imagesColor: UIColor? {
didSet {
minimumImageView.tintColor = imagesColor
maximumImageView.tintColor = imagesColor
}
}
open func setMinimumImage(_ image: UIImage?) {
minimumImageView.image = image?.withRenderingMode(.alwaysTemplate)
layoutImageViews()
}
open func setMaximumImage(_ image: UIImage?) {
maximumImageView.image = image?.withRenderingMode(.alwaysTemplate)
layoutImageViews()
}
// MARK: - Labels
@@ -183,6 +226,7 @@ open class Slider : UIControl {
filterView.mask?.frame = filterView.bounds
layoutBackgroundImage()
layoutImageViews()
layoutLabelsText()
layoutValueView()
}
@@ -194,22 +238,39 @@ open class Slider : UIControl {
maximumLabel.sizeToFit()
maximumLabel.frame = CGRect(x: bounds.maxX - labelsMargin - maximumLabel.bounds.width, y: bounds.midY - maximumLabel.bounds.midY, width: maximumLabel.bounds.width, height: maximumLabel.bounds.height).integral
}
private func layoutImageViews() {
let imageInset = ValueView.kLayoutMarginInset * 2
let imageSize = CGSize(width: bounds.height - imageInset * 2, height: bounds.height - imageInset * 2)
minimumImageView.frame = CGRect(x: imagesMargin, y: imageInset, width: imageSize.width, height: imageSize.height).integral
minimumImageView.contentMode = .left
if let image = minimumImageView.image, image.size.width > minimumImageView.bounds.width || image.size.height > minimumImageView.bounds.height {
minimumImageView.contentMode = .scaleAspectFit
}
maximumImageView.frame = CGRect(x: bounds.maxX - imagesMargin - imageSize.width, y: imageInset, width: imageSize.width, height: imageSize.height).integral
maximumImageView.contentMode = .right
if let image = maximumImageView.image, image.size.width > maximumImageView.bounds.width || image.size.height > maximumImageView.bounds.height {
maximumImageView.contentMode = .scaleAspectFit
}
}
private func layoutBackgroundImage() {
let inset = UIEdgeInsets(top: min(0, shadowOffset.height - shadowBlur), left: min(0, shadowOffset.width - shadowBlur), bottom: max(0, shadowOffset.height + shadowBlur) * -1, right: max(0, shadowOffset.width + shadowBlur) * -1)
backgroundImageView.frame = UIEdgeInsetsInsetRect(self.bounds, inset)
backgroundImageView.frame = self.bounds.inset(by: inset)
backgroundImageView.image = UIGraphicsImageRenderer(bounds: backgroundImageView.bounds).image(actions: { context in
if let color = shadowColor {
context.cgContext.setShadow(offset: shadowOffset, blur: shadowBlur, color: color.cgColor)
}
contentViewColor?.setFill()
let inset = UIEdgeInsets(top: inset.top * -1, left: inset.left * -1, bottom: inset.bottom * -1, right: inset.right * -1)
UIBezierPath(roundedRect: UIEdgeInsetsInsetRect(backgroundImageView.bounds, inset), cornerRadius: contentViewCornerRadius).fill()
UIBezierPath(roundedRect: backgroundImageView.bounds.inset(by: inset), cornerRadius: contentViewCornerRadius).fill()
})
}
private func layoutValueView() {
let bounds = UIEdgeInsetsInsetRect(self.contentView.bounds, UIEdgeInsets(top: 0, left: valueViewMargin, bottom: 0, right: valueViewMargin))
let bounds = self.contentView.bounds.inset(by: UIEdgeInsets(top: 0, left: valueViewMargin, bottom: 0, right: valueViewMargin))
let centerX = fraction * bounds.size.width + bounds.minX
setValueViewPositionX(to: centerX)
}
@@ -223,6 +284,7 @@ open class Slider : UIControl {
override open func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let result = super.beginTracking(touch, with: event)
let x = touch.location(in: self).x
isSliderTracking = true
fraction = fractionForPositionX(x)
valueView.animateTrackingBegin()
sendActions(for: .valueChanged)
@@ -233,6 +295,7 @@ open class Slider : UIControl {
override open func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let result = super.continueTracking(touch, with: event)
let x = touch.location(in: self).x
isSliderTracking = true
fraction = fractionForPositionX(x)
filterView.center.x = valueView.center.x
sendActions(for: .valueChanged)
@@ -241,18 +304,22 @@ open class Slider : UIControl {
override open func endTracking(_ touch: UITouch?, with event: UIEvent?) {
super.endTracking(touch, with: event)
isSliderTracking = false
valueView.animateTrackingEnd()
updateValueViewText()
didEndTracking?(self)
}
override open func cancelTracking(with event: UIEvent?) {
super.cancelTracking(with: event)
isSliderTracking = false
valueView.animateTrackingEnd()
updateValueViewText()
didEndTracking?(self)
}
private func boundsForValueViewCenter() -> CGRect {
return UIEdgeInsetsInsetRect(bounds, UIEdgeInsets(top: 0, left: valueViewMargin - ValueView.kLayoutMarginInset + valueView.bounds.midX, bottom: 0, right: valueViewMargin - ValueView.kLayoutMarginInset + valueView.bounds.midX))
return bounds.inset(by: UIEdgeInsets(top: 0, left: valueViewMargin - ValueView.kLayoutMarginInset + valueView.bounds.midX, bottom: 0, right: valueViewMargin - ValueView.kLayoutMarginInset + valueView.bounds.midX))
}
private func fractionForPositionX(_ x: CGFloat) -> CGFloat {
@@ -275,7 +342,7 @@ open class Slider : UIControl {
private let context = CIContext()
private func redrawFilterView() {
guard isAnimationAllowed() else { return }
guard isAnimationEnabled && isAnimationAllowed() else { return }
let scale = UIScreen.main.scale
let radius: CGFloat = UIScreen.main.bounds.width >= 414 ? kBlurRadiusIphonePlus : kBlurRadiusDefault
@@ -288,7 +355,11 @@ open class Slider : UIControl {
}
filter.blurRadius = radius
filter.threshold = 0.49
if #available(iOS 13.0, *) {
filter.threshold = 0.7
} else {
filter.threshold = 0.45
}
filter.backgroundColor = contentViewColor
filter.antialiasingRadius = scale / 2
filter.inputImage = CIImage(cgImage: inputImage.cgImage!)
+11 -7
View File
@@ -63,13 +63,17 @@ class ValueView : UIView {
return textLabel.attributedText
}
set {
// apply centered horizontal alignment
let string = newValue?.mutableCopy() as! NSMutableAttributedString
let paragraph = (string.attribute(.paragraphStyle, at: 0, effectiveRange: nil) as? NSParagraphStyle ?? NSParagraphStyle()).mutableCopy() as! NSMutableParagraphStyle
paragraph.alignment = .center
string.addAttribute(.paragraphStyle, value: paragraph, range: NSMakeRange(0, string.length))
textLabel.attributedText = string
}
if let newValue = newValue {
// apply centered horizontal alignment
let string = newValue.mutableCopy() as! NSMutableAttributedString
let paragraph = (string.attribute(.paragraphStyle, at: 0, effectiveRange: nil) as? NSParagraphStyle ?? NSParagraphStyle()).mutableCopy() as! NSMutableParagraphStyle
paragraph.alignment = .center
string.addAttribute(.paragraphStyle, value: paragraph, range: NSMakeRange(0, string.length))
textLabel.attributedText = string
} else {
textLabel.attributedText = nil
}
}
}
// MARK: - Laying out Subviews
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'fluid-slider'
s.version = '0.0.1'
s.version = '1.1.0'
s.summary = 'A slider widget with a popup bubble displaying the precise value selected.'
s.homepage = 'https://github.com/Ramotion/fluid-slider'
s.license = 'MIT'