UISlider MaximumTrackImage clips when slider has extreme max values - ios

I've dragged a UISlider to my view using Xcode's storyboard. Then I made an outlet and customised slider's appearance (in Swift) as follows:
slider.setMinimumTrackImage(UIImage(named: "Images/slider_min.png")?.stretchableImageWithLeftCapWidth(3, topCapHeight: 0), forState: UIControlState.Normal)
slider.setMaximumTrackImage(UIImage(named: "Images/slider_max.png")?.stretchableImageWithLeftCapWidth(3, topCapHeight: 0), forState: UIControlState.Normal)
slider.setThumbImage(UIImage(named: "Images/slider_thumb.png"), forState: UIControlState.Normal)
slider.setThumbImage(UIImage(named: "Images/slider_thumb.png"), forState: UIControlState.Highlighted)
The slider is stepped so possible values are integers ∈ [1,12].
These are the referenced images, they are transparent PNGs:
I'm having problems with the two biggest possible values (11, 12): the MaximumTrackImage clips for some reason. This is what happens:
Initial, minimum position, value = 1
Last OK position, value = 10
First position where the clipping occurs, value = 11
Maximum position, still clipping, value = 12
Why this happens? Can this be fixed or are there any workarounds?

Oh well, it seems the problem was with the MaximumTrackImage—it was unnecessarily wide. I cropped the track images to be 6 px in width and the problem disappeared.
Cropping the MaximumTrackImage was sufficient, but cropping the MinimumTrackImage too didn't hurt.

Related

What causes horizontal padding around title of UIButton?

I programmatically created two UIButtons and constrained them to 2 points apart (horizontally). I see extra space, so I clicked the "Debug View Hierachy" button in Xcode, and here is what I see:
What is causing the extra space around the "abc" title? I looked at a few suspect properties of the button and they are all zero. (contentEdgeInsets, titleEdgeInsets)
I haven't done anything to the buttons other than:
let b = UIButton(type: .system)
b.translatesAutoresizingMaskIntoConstraints = false
b.setTitle("...", for: .normal)
The constraints look like:
b1.centerXAnchor.constraint(equalTo: outer.centerXAnchor)
b2.leftAnchor.constraint(equalTo: b1.rightAnchor, constant: 2)
b2.firstBaselineAnchor.constraint(equalTo: b1.firstBaselineAnchor, constant: 0)
UIButton has an intrinsic minimum width of 30-pts.
So, if the title text is shorter than 30-pts, the button's title label will be centered horizontally in the button's 30-pt frame.
You can explicitly set the width to less than 30, but then you'll have to take some other steps to get your button to auto-size with a longer title.

Swift Changing UISlider images and tint doesn't work as expected

I have a slider in my ViewController:
#IBOutlet weak var timeSlider: UISlider!
When using the code:
timeSlider.setMinimumTrackImage(#imageLiteral(resourceName: "track"), for: .normal)
timeSlider.setMaximumTrackImage(#imageLiteral(resourceName: "track"), for: .normal)
timeSlider.setThumbImage(#imageLiteral(resourceName: "thumb2"), for: .normal)
My slider looks like this:
It works great and behaves as one would expect it to behave
Now I want to make the part before thumb have different color and the part after to also have different color, so I created a function which creates new images as templates (templates being an array) from images I use for my view:
func setTemplates(){
templates.removeAll()
for i in 0 ..< 10{
templates.append(playImg[i].withRenderingMode(.alwaysTemplate))
}
}
templates[5] is the same image as "thumb2"
templates[6] = "track"
and then I wanted to assign template[6] (which the image "track" converted to template) and color it in the same fashion I do with other images in the view like buttons, or to color labels etc. like this:
timeSlider.setMinimumTrackImage(templates[6], for: .normal)
timeSlider.setMaximumTrackImage(templates[6], for: .normal)
timeSlider.setThumbImage(templates[5], for: .normal)
timeSlider.minimumTrackTintColor = colors.primaryColor
timeSlider.maximumTrackTintColor = colors.detailColor
timeSlider.thumbTintColor = colors.secondaryColor
Where colors is a struct holding four different colors. But as you can see it doesn't work properly
The image thumb is being set to default one, it doesn't even behave properly as I can't move the thumb to 0.0 position of the slider and after I move it or the colors change, the part after thumb gets blue color which is default for slider.
I tried different ways to fight this problem but this is the closest I got it to working properly. At this point I'm starting to think it's a bug but maybe I made some mistake in my code. As I said I have buttons, labels, which I color the same way I tried here
button.setImage(templates[7], forState: .normal)
button.tintColor = colors.primaryColor
and it works
What am I doing wrong?
From the documentation for UISlider thumbTintColor:
Setting this property resets the thumb images back to the slider’s default images; any custom images are released by the slider. Setting this property to nil resets the tint color to the default and removes any custom thumb images.
Same for the two track tints.
If you want custom images then just set the custom images without also setting the tints.
In other words, set either the custom images or set the tints. Do not set both.

Custom UISlider using UIEdgedInset does not render well

I'm trying to do a custom uislider using images (without a visible knob, i hide it when user can't edit and show it when he can) The problem is that the the side render perfectly but the right part is cute and doesn't seems to use the edges...
Any idea how i can edit it ?
Actual code :
let capLeft:CGFloat = 9
let capRight:CGFloat = 9
imageMin = imageMinimum?.resizableImage(withCapInsets: UIEdgeInsets(top: 0, left: capLeft, bottom: 0, right: capRight), resizingMode: .stretch)
imageMax = imageMaximum
slider.setMaximumTrackImage(imageMax, for: UIControlState())
slider.setMinimumTrackImage(imageMin, for: UIControlState())
How it's rendering :
How it should render :
Minimum track image :
Maximum Tracking Image :
Do you have any idea ?
I think there is a bit of confusion about Min and Max images with UISlider.
The Min image is drawn (and stretched) on the Left side of the Thumb. The Max image is drawn (and stretched) on the Right side of the Thumb.
Create a small, square solid red image - such as 16x16 - and assign it (without insets) to .setMaximumTrackImage. See how that ends up looking, as you go from low to high values.
Edit: I used NO insets on the Min image for this example...
Note: I used a 20x20 clear image for the Thumb in these caps.

UIButton with template image receiving touch events only for non-transparent pixels

I have an iOS app written in Swift (2.1). I'm using a little workaround which I've found to make smaller margins between UIBarButtonItem's in NavigationBar. Here's my code:
let modeImage = UIImage(named: modeFilename)!.imageWithRenderingMode(.AlwaysTemplate)
modeButton = UIButton(frame: CGRectMake(0, 0, 22, 22))
modeButton.setBackgroundImage(modeImage, forState: .Normal)
modeButton.addTarget(self, action: Selector("modeClicked:"), forControlEvents:.TouchUpInside)
modeButton.transform = CGAffineTransformMakeTranslation(10, 0)
let modeButtonContainer = UIView(frame: modeButton.frame)
modeButtonContainer.addSubview(modeButton)
modeButtonItem = UIBarButtonItem(customView: modeButtonContainer)
Button works, but I have a square-like simple image and touch is only working on non-transparent pixels (or near them maybe). It's hard to hit it on simulator not to mention real device. It's a real pain. I've found solution to use Tap Gesture Recognizer on modeButtonContainer, but then button is not hovering so it's not a best solution.
Using setImage instead of setBackgroundImage doesn't change anything. Same goes for creating button with type UIButtonType.Custom.
Help!
Figured it out! My theory was wrong. It's not because of transparent pixels. Problem causes this line:
modeButton.transform = CGAffineTransformMakeTranslation(10, 0)
This caused button to be offsetted by 10 points instead being at center of its container. Button seemed looking good, but when I've set background to modeButtonContainer I realized button work only on containers area and doesn't work outside it.
So I needed to remove this line and instead use add this as first item in rightBarButtonItems:
let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpacer.width = -10

How to remove right padding/margin/space from a custom bar button item which has an image?

I've been trying to find a solution to this problem for the past two days and still nothing I have tried works for me. Some solutions I have tried either stretch or completely mess up my custom image but nothing removes the right padding. Here is my code below as well as the result. Notice how the right bar button has a bigger space than the left system one.
var saveButton: UIButton = UIButton(frame: CGRectMake(0, 0, 32, 32))
saveButton.addTarget(self, action: "saveAction:", forControlEvents: .TouchUpInside)
let img = UIImage(named: "save")
saveButton.setBackgroundImage(img, forState: .Normal)
var saveBarButton: UIBarButtonItem = UIBarButtonItem(customView: saveButton)
self.navigationItem.setRightBarButtonItem(saveBarButton, animated: false)
Alright guys, I've found a solution that works pretty well for me. Instead of creating and setting the bar button item in code I added one in storyboard and set it's left margin in size inspector to -6 (or whatever value you like) and it's right margin to 6 (again whatever value you prefer note that the two values must be the same values but one is positive and the other is negative). Then I set it's image to the image I desired in the attributes inspector. If for some reason you want to change the image in code you can do so like this:
barButtonOutlet.image = UIIMage(named: "yourImage") as UIImage?
Hope this helps some of you out.
This is my solution. Try..
rightBtn.imageInsets = UIEdgeInsets(top: 0, left: -13.0, bottom: 0, right: 13.0)
self.navigationItem.rightBarButtonItem = rightBtn

Resources