Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New features #12

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions Example/TactileSlider/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="vXZ-lx-hvc">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="vXZ-lx-hvc">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand All @@ -20,7 +22,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="23G-Tb-ylv" customClass="TactileSlider" customModule="TactileSlider">
<rect key="frame" x="40" y="8" width="295" height="50"/>
<rect key="frame" x="40" y="28" width="295" height="50"/>
<accessibility key="accessibilityConfiguration" label="Example value 1">
<bool key="isElement" value="YES"/>
</accessibility>
Expand All @@ -39,10 +41,17 @@
<userDefinedRuntimeAttribute type="number" keyPath="value">
<real key="value" value="0.14999999999999999"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="image" keyPath="image">
<imageReference key="value" image="sun.min.fill" catalog="system" symbolScale="large" renderingMode="original" variableValue="5.5511151231257827e-17"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="imageTintColor">
<color key="value" systemColor="systemRedColor"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="string" keyPath="position" value="right"/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZDQ-j3-34d" customClass="TactileSlider" customModule="TactileSlider">
<rect key="frame" x="40" y="74" width="295" height="50"/>
<rect key="frame" x="40" y="94" width="295" height="50"/>
<accessibility key="accessibilityConfiguration" label="Example value 2">
<bool key="isElement" value="YES"/>
</accessibility>
Expand All @@ -62,10 +71,12 @@
<userDefinedRuntimeAttribute type="number" keyPath="value">
<real key="value" value="0.14999999999999999"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="image" keyPath="image" value="sun.min.fill" catalog="system"/>
<userDefinedRuntimeAttribute type="string" keyPath="position" value="left"/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NV5-ku-zjX" customClass="TactileSlider" customModule="TactileSlider">
<rect key="frame" x="40" y="140" width="50" height="200"/>
<rect key="frame" x="40" y="160" width="50" height="200"/>
<accessibility key="accessibilityConfiguration" label="Example value 3">
<bool key="isElement" value="YES"/>
</accessibility>
Expand All @@ -85,10 +96,12 @@
<userDefinedRuntimeAttribute type="number" keyPath="value">
<real key="value" value="0.14999999999999999"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="image" keyPath="image" value="sun.min.fill" catalog="system"/>
<userDefinedRuntimeAttribute type="string" keyPath="position" value="top"/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BEf-fM-pCA" customClass="TactileSlider" customModule="TactileSlider">
<rect key="frame" x="106" y="140" width="50" height="200"/>
<rect key="frame" x="106" y="160" width="50" height="200"/>
<accessibility key="accessibilityConfiguration" label="Example value 4">
<bool key="isElement" value="YES"/>
</accessibility>
Expand All @@ -108,6 +121,7 @@
<userDefinedRuntimeAttribute type="number" keyPath="value">
<real key="value" value="0.14999999999999999"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="image" keyPath="image" value="sun.min.fill" catalog="system"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
Expand All @@ -132,4 +146,10 @@
<point key="canvasLocation" x="56.799999999999997" y="27.436281859070466"/>
</scene>
</scenes>
<resources>
<image name="sun.min.fill" catalog="system" width="128" height="123"/>
<systemColor name="systemRedColor">
<color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>
65 changes: 62 additions & 3 deletions TactileSlider/Classes/TactileSlider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,15 @@ import UIKit
}
}
}


public enum ImagePosition:String{
case right
case left
case top
case bottom
case center
}

private enum Direction {
case rightToLeft
case leftToRight
Expand Down Expand Up @@ -195,6 +203,16 @@ import UIKit
setTapEnabled()
}
}

/// Indicates whether a drag within the slider's bounds will set its value.
///
/// If true, drag anywhere in the slider will set it to that value.
@IBInspectable open var enableDragging: Bool = true {
didSet {
setDragEnabled()
}
}


/// An array of `UITouch.TouchType`s used to distinguish the type of touches for the ``enableTapping`` feature.
///
Expand Down Expand Up @@ -309,6 +327,43 @@ import UIKit
}
}
}

/// The image of the slider.
///
/// If the image is set, the slider will show the image in the specified location.
/// for more information about image position, check``imagePosition``
/// (default value: ``nil``)
@IBInspectable open var image:UIImage? = nil{
didSet{
renderer.image = image
}
}

/// The position of the slider's image.
///
/// If set image position, the slider will show the image in the selected position. (default value: ``bottom``)
open var imagePosition:ImagePosition? = nil{
didSet{
renderer.imagePosition = imagePosition ?? .bottom
}
}


/**
The position of the slider image for the storyboard.

If set image position, slider will show image in selected position.for more information about image position, check``imagePosition``(default value: ``bottom``)
- Note: If creating a view from code, use ``imagePosition`` instead.
*/
@IBInspectable open var position:String? = nil{
didSet{
guard let position = position?.lowercased() else {
imagePosition = nil
return
}
imagePosition = ImagePosition.init(rawValue: position)
}
}

/// See [`UIView.frame`](https://developer.apple.com/documentation/uikit/uiview/1622621-frame)
override open var frame: CGRect {
Expand Down Expand Up @@ -521,6 +576,10 @@ import UIKit
private func setTapEnabled() {
tapGestureRecognizer.isEnabled = enableTapping
}

private func setDragEnabled() {
dragGestureRecognizer.isEnabled = enableDragging
}

@available(iOS 13.4, *)
private func setScrollingEnabled() {
Expand All @@ -531,7 +590,7 @@ import UIKit
}
}

@objc func didPan(sender: UIPanGestureRecognizer) {
@objc public func didPan(sender: UIPanGestureRecognizer) {
Copy link
Author

@Ali72 Ali72 Jul 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when didPan function is public, I can set my custom drag gesture (like other view drag gestures) into the slider

let translationLengthAlongValueAxis = valueAxisFrom(sender.translation(in: self))

accumulatedMovement += translationLengthAlongValueAxis
Expand Down Expand Up @@ -588,7 +647,7 @@ import UIKit
}
}

@objc func didTap(sender: UITapGestureRecognizer) {
@objc public func didTap(sender: UITapGestureRecognizer) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when didTap function is public, I can set my custom tap gesture (like other view taps) into the slider

if sender.state == .ended {
let tapLocation: CGFloat
if (reverseValueAxis && !vertical) || (!reverseValueAxis && vertical) {
Expand Down
64 changes: 63 additions & 1 deletion TactileSlider/Classes/TactileSliderLayerRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,33 @@ internal class TactileSliderLayerRenderer {
}
}
}

var image:UIImage? = nil{
didSet{
updateImage()
}
}

var imagePosition:TactileSlider.ImagePosition = .bottom{
didSet{
updateImageFrame()
}
}

var imageSize:CGSize = .init(width: 20, height: 20){
didSet{
updateImageFrame()
}
}


let trackLayer = CALayer()
let thumbLayer = CAShapeLayer()
let maskLayer = CAShapeLayer()
let outlineLayer = CAShapeLayer()
let thumbOutlineLayer = CAShapeLayer()

let imageLayer = CALayer()

init() {
trackLayer.backgroundColor = trackBackground.cgColor
thumbLayer.fillColor = thumbTint.cgColor
Expand All @@ -74,12 +94,15 @@ internal class TactileSliderLayerRenderer {

updateOutlineLayer(updateBounds: false)
updateOutlineColors()
updateImage()
updateImageFrame()
}

internal func setupLayers() {
trackLayer.addSublayer(thumbLayer)
trackLayer.addSublayer(outlineLayer)
thumbLayer.addSublayer(thumbOutlineLayer)
trackLayer.addSublayer(imageLayer)
}

private func updateThumbLayerPath() {
Expand Down Expand Up @@ -185,6 +208,9 @@ internal class TactileSliderLayerRenderer {
thumbOutlineLayer.position = trackLayer.position
updateThumbLayerPath()

updateImage()
updateImageFrame()

if let value = tactileSlider?.value {
setValue(value)
}
Expand All @@ -210,4 +236,40 @@ internal class TactileSliderLayerRenderer {

CATransaction.commit()
}

private func updateImage(){
guard let image else {
imageLayer.contents = nil
return
}

imageLayer.contents = image.cgImage
}

private func updateImageFrame(){


var origin:CGPoint = .zero
switch imagePosition {
case .left:
let leftPadding = min(trackLayer.frame.maxX * 0.1, 30)
origin = .init(x: trackLayer.frame.minX + leftPadding, y: trackLayer.frame.midY-imageSize.height/2)
case .right:
let rightPadding = min(trackLayer.frame.maxX * 0.1, 30)
origin = .init(x: trackLayer.frame.maxX - imageSize.width - rightPadding, y: trackLayer.frame.midY-imageSize.height/2)
case .top:
let topPadding = min(trackLayer.frame.maxY * 0.1, 30)
origin = .init(x: trackLayer.frame.midX - imageSize.width/2, y: trackLayer.frame.minY+topPadding)
case .bottom:
let bottomPadding = min(trackLayer.frame.maxY * 0.1, 30)
origin = .init(x: trackLayer.frame.midX - imageSize.width/2, y: trackLayer.frame.maxY-imageSize.height - bottomPadding)
case .center:
origin = .init(x: trackLayer.frame.midX - imageSize.width/2, y: trackLayer.frame.midY-imageSize.height/2)
}


imageLayer.frame = .init(origin: origin, size: imageSize)
imageLayer.contentsGravity = .resizeAspect
imageLayer.isGeometryFlipped = true
}
}