How to remove the space between UISlider and Minimum Image - swift

I would like to remove the space / offset at the beginning of the UISlider and join it with the custom minimum image that I have.
Is it possible to do it programmatically in Swift?
I have checked this, but it's old and it's for Objective-C.

well, I looked at the answer you tagged, and made something up for you on playground. Not sure if it works precisely for your case, but the key is to look into the methods of UISlider that you can override here
import UIKit
class SomeController: UIViewController {
let slider = MyCustomSlider()
//etc...
}
class MyCustomSlider: UISlider {
override func maximumValueImageRect(forBounds bounds: CGRect) -> CGRect {
var r = super.maximumValueImageRect(forBounds: bounds)
r.origin.x -= 3
return r
}
}

Related

I want to give the thumb image to NSSlider in swift

I`m working on an editor app, where I need to add image in the slider thumb as I'm doing macOS development so unfortunately I'm not able to do that in macOS, there is available in UISlider.
this is what I have and I want to insert the thumb Image as give below
I find out the solution, I hope this will help you all.
I made a NSSliderCell class and override the function drawKnob.
class CustomSliderCell: NSSliderCell {
#IBInspectable var knobImage: NSImage?{
didSet{
if let knobImage = knobImage{
self.knobImage = knobImage
}
}}
override func drawKnob(_ knobRect: NSRect) {
var rect = knobRect
rect.size = NSSize(width: rect.width, height: rect.height - 4)
self.knobImage?.draw(in: rect)
}
}
just assign this class to you nsslider cell from your storyboard and change the image on your storyboard.
enter image description here
The Result is given Below :
[This is the resultant Image][2]
enter image description here

How to to determinate in Swift the current width of the app when in Split View?

EDIT: I have a project with a row of buttons on top on it. Usually the buttons are 5 in Compact view and 6 in Regular view. I would like to remove a button when the app runs in 1/3 Split View. How can I determine the width of the app?
I'm using this code to determinate the current width of the app when in Split View (multitasking):
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
// works but it's deprecated:
let currentWidth = UIScreen.mainScreen().applicationFrame.size.width
print(currentWidth)
}
It works, but unfortunately applicationFrame is deprecated in iOS 9, so I'm trying to replace it with this:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
// gives you the width of the screen not the width of the app:
let currentWidth = UIScreen.mainScreen().bounds.size.width
print(currentWidth)
}
The problem is that the first statement gives you the effective width of the app and it's fine, instead the second one, gives you the width of the screen, so you can't use it to learn the real width of the app when it is in Split View.
Would someone know what code would be necessary to replace this deprecated statement?
let currentWidth = UIScreen.mainScreen().applicationFrame.size.width // deprecated
#TheValyreanGroup's answer will work if there are no intervening view controllers mucking with sizes. If that possibility exists you should be able to use self.view.window.frame.size.width
You can just get the size of the parent view.
let currentSize = self.view.bounds.width
That will return the width accurately even in split view.
You can do something like this to determine whether to show or hide a button.
let totalButtonWidth: Int
for b in self.collectionView.UIViews{
let totalButtonWidth += b.frame.width + 20 //Where '20' is the gap between your buttons
}
if (currentSize < totalButtonWidth){
self.collectionView.subviews[self.collectionView.subviews.count].removeFromSuperview()
}else{
self.collectionView.addSubview(buttonViewToAdd)
}
Something like that, but i think you can get the idea.
Thanks to the replay of TheValyreanGroup and David Berry on this page I made a solution that can respond to the interface changes without using the deprecate statement UIScreen.mainScreen().applicationFrame.size.width I post it here with its context to made more clear what is the problem and the (surely improvable) solution. Please post any suggestion and comment you think could improve the code.
// trigged when app opens and when other events occur
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
let a = self.view.bounds.width
adaptInterface(Double(a))
}
// not trigged when app opens or opens in Split View, trigged when other changes occours
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
adaptInterface(Double(size.width))
}
func isHorizontalSizeClassCompact () -> Bool {
if (view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact) {
return true // Comapact
} else {
return false // Regular
}
}
func adaptInterface(currentWidth: Double) {
if isHorizontalSizeClassCompact() { // Compact
// do what you need to do when sizeclass is Compact
if currentWidth <= 375 {
// do what you need when the width is the one of iPhone 6 in portrait or the one of the Split View in 1/3 of the screen
} else {
// do what you need when the width is bigger than the one of iPhone 6 in portrait or the one of the Split View in 1/3 of the screen
}
} else { // Regular
// do what you need to do when sizeclass is Regular
}
}

Layer transform matrix (CATransform3D, etc.) but with IBDesignable?

This class will put perspective on an upright image.
It works perfectly BUT does not work live in Storyboard with IBDesignable. Which is very sad.
Is it possible to use CATransform3D and the like for live display on Storyboard with IBDesignable??
// Twist.swift .. twist on Y, perspective from the left
import UIKit
#IBDesignable
class Twist:UIViewController
{
#IBInspectable var perspective:CGFloat = 0.5 // -1 to 1
#IBOutlet var im:UIView! // the image you want to twist on y
override func prepareForInterfaceBuilder()
{ twist(perspective) }
override func viewDidAppear(animated: Bool)
{
twist(perspective)
super.viewWillAppear(animated)
}
func twist(f:CGFloat) // -1 to 1
{
// hinge around left edge
im.layer.anchorPoint = CGPointMake(0, 0.5)
im.center = CGPointMake(0.0, self.view.bounds.size.height/2.0)
// base transform, twist on y
var t:CATransform3D = CATransform3DIdentity
t.m34 = -1/500
im.layer.transform = t
im.layer.transform = CATransform3DRotate(t, f*CGFloat(M_PI_2), 0, 1, 0);
}
}
I already had an issue with live preview transformations. It seems it just doesn't work, maybe not implemented yet.
There's a thing, only UIViews can be #IBDesignable. Here you can see that both of #UIDesignable classes can't be rendered. I created a Class TwistableView for the example.

How can I make a vertical slider in swift?

I was wondering how I can create a vertical slider in swift.
I have tried using .transform and then adding a rotate but this returned an exception and rotated the whole screen. I just need a vertical slider.
I was wondering if anyone know of a way to rotate a slider in swift?
Thanks
Assuming you are talking about UISlider :
You were looking in a right direction but probably applied AffineTransformation to the wrong item... You should use UISlider.transform to change it orientation.
Here is working code (I did add UISlider using InterfaceBuilder):
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var verticalSlider: UISlider!{
didSet{
verticalSlider.transform = CGAffineTransform(rotationAngle: CGFloat(-M_PI_2))
}
}
}
Options 1:
In Swift 4:
-M_PI_2 is deprecated so Use Double.pi / 2
verticalSlider.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi / 2))
OR
Options 2: for All Objective C and Swift
Key path = layer.transform.rotation.z
Type = String
Value = -1.570795
Most Imp Note: before and After keypath No Space
Use OOP. If you define this rotation as an Extension on UIView, then not only the UIView but also all subclasses that inherit from UIView can be rotated. This of course includes UISlider, but also UILabel, UIButton and about 200? other subclasses... see here
list of subclasses for UIView
extension UIView
{
func makeVertical()
{
transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
}
}
// usage example:
sldBoilerTemperature.makeVertical()
It's good to be aware of inheritance, saves a lot of work. For many Swift extensions to make, it might be a good idea trying to move it upwards in the class hierarchy, like in this example.
Swift-5 Vertical slider with constraints
func transformSlider(){
var constraints = [NSLayoutConstraint]()
ControlSlider.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))
ControlSlider.translatesAutoresizingMaskIntoConstraints = false
constraints.append(ControlSlider.widthAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.8))
constraints.append(ControlSlider.centerYAnchor.constraint(equalTo: self.centerYAnchor))
let sliderWidth = (ControlSlider.frame.height * 0.8)/2
print(sliderWidth)
constraints.append(ControlSlider.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: (20-sliderWidth)))
NSLayoutConstraint.activate(constraints)
}

How can I move the clear button in a UITextField?

For some reason, when I add a UITextfield as a subview of the contentview of a tablecell, the clearbutton does not align with the text typed in the field, and appears a bit underneath it. Is there any way I can move the text of the clearbutton to stop this from happening? Thanks for any help,
As stated by #Luda the correct way is to subclass UITextField and override - (CGRect)clearButtonRectForBounds:(CGRect)bounds. However the bounds passed in to the method are those of the view itself and not the button. Therefore you should call super to get the OS provided size (to avoid distortion of the image) and then adjust the origin to suit your needs.
e.g.
- (CGRect)clearButtonRectForBounds:(CGRect)bounds {
CGRect originalRect = [super clearButtonRectForBounds:bounds];
return CGRectOffset(originalRect, -10, 0); //shift the button 10 points to the left
}
Apple docs state:
Discussion You should not call this method directly. If you want to
place the clear button in a different location, you can override this
method and return the new rectangle. Your method should call the super
implementation and modify the returned rectangle’s origin only.
Changing the size of the clear button may cause unnecessary distortion
of the button image.
The answer from Van Du Tran in Swift 4:
class CustomTextField: UITextField {
override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
let originalRect = super.clearButtonRect(forBounds: bounds)
return originalRect.offsetBy(dx: -8, dy: 0)
}
}
Swift 4, 5
Subclass UITextField (Working Perfectly, Tested)
class textFieldWithCrossButtonAdjusted: UITextField {
override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
let originalRect = super.clearButtonRect(forBounds: bounds)
//move 10 points left
return originalRect.offsetBy(dx: -10, dy: 0)
}
}
I had subclassed the UITextField and override the function clearButtonRectForBounds:.
.h
#import <UIKit/UIKit.h>
#interface TVUITextFieldWithClearButton : UITextField
#end
.m
#import "TVUITextFieldWithClearButton.h"
#implementation TVUITextFieldWithClearButton
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)awakeFromNib
{
self.clearButtonMode = UITextFieldViewModeWhileEditing;
}
- (CGRect)clearButtonRectForBounds:(CGRect)bounds
{
return CGRectMake(bounds.size.width/2-20 , bounds.origin.y-3, bounds.size.width, bounds.size.height);
}
#end
I haven't seen this, and a screen shot would be helpful. But, the quick answer is that you can inspect the subviews array of the UITextField, find the subview that contains the clear button, and adjust its frame.origin.
Edit: It seems I've been downvoted for this answer (written in 2010). This is of not an "officially" approved method because you're manipulating private objects, but it's not detectable by Apple. The main risk is that the view hierarchy might be changed at some point.
Subclass UITextField and override this method:
- (CGRect)clearButtonRectForBounds:(CGRect)bounds
{
return CGRectMake(bounds.origin.x - 10, bounds.origin.y, bounds.size.width, bounds.size.height);
}
return the CGRect that matches your needs.
Swift 4 version would be
import UIKit
class LoginTextField: UITextField {
override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: xPos, y:yPos, width: yourWidth, height: yourHeight)
}
}