I want to increase or decrease the level of blur effect in the photo using the pickerview. Even if I decrease the value, it adds a continuous blur effect to it. What should I do?
Working on latest Swift and Xcode
class ViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource {
#IBOutlet var bg: UIImageView!
#IBOutlet var pickView: UIPickerView!
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return arr.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
switch arr[row] {
case "1":
Blur(blur: 0.3)
case "2":
Blur(blur: 0.6)
case "3":
Blur(blur: 0.0)
default:
print("not change")
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return arr[row]
}
let arr = ["1","2","3"]
override func viewDidLoad() {
super.viewDidLoad()
pickView.dataSource = self
pickView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
func Blur(blur:CGFloat)
{
let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light)
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.frame = bg.bounds
blurView.alpha = blur
self.view.addSubview(blurView)
}
}
Your Blur(blur: 0.3) is a function not an object class, it will run not change properties. And your func added a Subview to your parent View but none code line to remove it before add another. So it will be stack up.
Remove old blur subView then add new.
Create a default blur view first then change it properties.
Related
I have this demo app:
As you can see, the alpha of the background is changing to black according to the value.
But the problem is that there is no smooth transition:
As you can see from the GIF, the background is only changing after the scrolling is over. And I don't want it to be like that.
this is my code:
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var backView: UIView!
let max = 100
override func viewDidLoad() {
super.viewDidLoad()
pickerView.delegate = self
pickerView.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return max + 1 // To include '0'
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let l = UILabel(frame: .zero)
l.text = String(max - row)
l.textColor = .white
l.font = UIFont.preferredFont(forTextStyle: .title3)
l.textAlignment = .center
return l
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
backView.alpha = CGFloat(max - row) / 100
}
}
I am giving the delegate UIView instead of String, because I had an idea: to test every time the location of each row is changing, and when the row is in the middle of the screen I should update the background. But unfortunately I don't know how to do that.
Maybe you can help? or perhaps suggest any other ideas?
Thank you!
The delegate method didSelectRow is only called when the rolling stops, so this is not the place you should update your alpha. UIPickerView has no delegate method which will notify you about the change during the rolling, however the UIPickerView will call your data source and delegate methods to get the title or in your case the view for a given row so it can be displayed as the user scrolls. So what you should do is just move your alpa changing logic there:
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
backView.alpha = CGFloat(max - row) / 100
}
Note that this delegate method will be called when the UIPickerView is loaded, so maybe you should disable the alpha changing until view is not layout out correctly(maybe viewDidAppear will do it).
As the delegate method can sometimes behave unexpectedly(calling not just the next lines, but any line from the picker), we should store and also check if the row is just one step ahead or behind the last saved value, otherwise we should just ignore that. I made a simple demo to demonstrate how it works:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
private let pickerView = UIPickerView()
private var isPickerReady = false
private var lastValue = 0
private let max = 100
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(pickerView)
pickerView.translatesAutoresizingMaskIntoConstraints = false
pickerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
pickerView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
pickerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
pickerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
pickerView.delegate = self
pickerView.dataSource = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
isPickerReady = true
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return max
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
// Do not update the value until the view is not loaded
// Only consider delegate methods which are one step ahead or behind the last value
if row + 1 == lastValue && isPickerReady || row - 1 == lastValue && isPickerReady {
lastValue = row
view.alpha = CGFloat(max - lastValue ) / 100
}
return "Tiltle \(row)"
}
}
should look like this
In pickerView i want to change title font size, as I scroll the selected row title font will be of high font size and above selected title font size will be decreasing and same for below selected row.
import UIKit
Vc:
class ViewController: UIViewController {
#IBOutlet weak var pickerView: UIPickerView!
var pickerTitle = ["10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00","10:00"]. // time to display in pickerView
var fontSize = [4,6,8,10,12,14,16,18,20,22,24,26,24,22,20,18,16,14,12,10,8,6,4,2] // font size when view is loaded and when I scroll I need to change the font size so this won't work I guess
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
pickerView.delegate = self
pickerView.dataSource = self
pickerView.reloadAllComponents()
pickerView.selectRow(11, inComponent: 0, animated: true)
}
}
datasource and delete for pickerView:
extension ViewController: UIPickerViewDelegate,UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerTitle.count
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let pickerLabel = UILabel()
let titleData = pickerTitle[row]
let myTitle = NSAttributedString(string: titleData, attributes: [NSAttributedString.Key.font:UIFont(name: "Georgia", size: CGFloat(fontSize[row]))!,NSAttributedString.Key.foregroundColor:UIColor.black])
pickerLabel.attributedText = myTitle
pickerLabel.textAlignment = .right
return pickerLabel
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
for var i in 0...row{
print(i)
}
for var i in row..<pickerTitle.count{
print(i)
}
pickerView.reloadAllComponents()
}
}
Not sure what your requirements are, and what you're doing in the code.
But what I could understand is that you want an increased font size for selected title in pickerView, and the rest unselected titles stays smaller; then here is the code:
(if not, please clarify further)
extension ViewController: UIPickerViewDelegate,UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerTitle.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
pickerView.reloadAllComponents()
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
var label = view as! UILabel?
if label == nil {
label = UILabel()
label?.textAlignment = .center
}
switch component {
case 0:
label?.text = pickerTitle[row]
if(pickerView.selectedRow(inComponent: 0) == row){
label?.font = UIFont(name: "Georgia", size: 26)
}
return label!
default:
return label!
}
}
}
The text field delegate method textFieldDidEndEditing is not firing when picker view is used in Swift 3. How can I call it? There is no button to dynamically call the delegate.
You can see my code below.
import UIKit
class ThroewViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource,UITextFieldDelegate {
#IBOutlet weak var pickerText: UITextField!
let thePicker = UIPickerView()
var dashTitle_Arr = ["One","Two","Three","Four","Five","Six"]
override func viewDidLoad() {
super.viewDidLoad()
pickerText.delegate = self
thePicker.dataSource = self
thePicker.delegate = self
pickerText.inputView = thePicker
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dashTitle_Arr .count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return dashTitle_Arr [row] }
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
pickerText.text = dashTitle_Arr [row]
}
func textFieldDidEndEditing(_ textField: UITextField) {
addIntoArray(text: textField.text)
}
func addIntoArray(text: String?) {
guard let text = text, text.characters.count > 0 else {
return
}
dashTitle_Arr.append(text)
thePicker.reloadAllComponents()
}
}
There is a property of picker-view is accessoriesView. Create a tool bar with done or cancel button and set it in the picker view's assessoriesView.
In the toolbar button action write the textfield.resignFirstResponder()
After that the textFieldDidEndEditing delegate method fired
It works fine for me. Hope it will helps you. Thank you
I made it this far and it replies my text without a problem:
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var foodLabel: UILabel!
#IBOutlet weak var foodSlider: UIPickerView!
var picker = UIPickerView()
let foodsScroll = ["pizza \npepperoni" ,"chicken \nnuggets ","meat \nballs","hamburger \nbloody","omelette \ngrilled","ice cream \nberry"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return 80.00
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let cgRect = CGRect(x: 0.00, y: 0.00, width: 400, height: 200)
let label = UILabel(frame: cgRect)
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
label.text = foodsScroll[row]
label.sizeToFit()
return label
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return foodsScroll[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return foodsScroll.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
foodLabel.text = foodsScroll[row]
}
override func viewDidLoad() {
}
}
And it comes to the part where I need to add a single icon to one side of each food's name. I can't quite figure out how it's done, but I know you can use 2 simple ways of:
Using an extra UIView and
Using an UIImage.
Any alternative methods are also welcome.
You are the question and you are the answer Yes!! here two simple way to add your idea
1)using an extra UIView and
2)using an UIImage.
3)create a card
And finally it's one here it's card. but it's same as UIView
https://github.com/aclissold/CardView
I am trying to use images in a Swift PickerView. I don't know how to get the images to actually appear in the component. I know how to do this using Strings with the titleForRow function but I don't know how to do this using images. Here is my code so far:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var pickerView: UIPickerView!
var imageArray: [UIImage] = [UIImage(named: "washington.jpg")!,
UIImage(named: "berlin.jpg")!, UIImage(named: "beijing.jpg")!,
UIImage(named: "tokyo.jpg")!]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// returns the number of 'columns' to display.
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
// returns the # of rows in each component..
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return imageArray.count
}
}// end of app
You will need to implement a couple more the delegate methods for the UIPickerViewDelegate protocol. In particular a rowHeight delegate method and a viewForRow delegate method.
Something like:
// MARK: UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 2
}
func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return 60
}
// MARK: UIPickerViewDelegate
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {
var myView = UIView(frame: CGRectMake(0, 0, pickerView.bounds.width - 30, 60))
var myImageView = UIImageView(frame: CGRectMake(0, 0, 50, 50))
var rowString = String()
switch row {
case 0:
rowString = “Washington”
myImageView.image = UIImage(named:"washington.jpg")
case 1:
rowString = “Beijing”
myImageView.image = UIImage(named:"beijing.jpg")
case 2:
default:
rowString = "Error: too many rows"
myImageView.image = nil
}
let myLabel = UILabel(frame: CGRectMake(60, 0, pickerView.bounds.width - 90, 60 ))
myLabel.font = UIFont(name:some font, size: 18)
myLabel.text = rowString
myView.addSubview(myLabel)
myView.addSubview(myImageView)
return myView
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// do something with selected row
}
Note that the label layout etc is just for demonstration, would need to be tweaked, or probably better to use Auto Layout ect.
I had this same question and did some research until I figured it out. Here's an example that works great for me. Just make sure your images in the Assets folder are all named the same as your case strings and you'll be set!
#IBOutlet weak var pickerView: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
pickerView.delegate = self
}
// MARK: UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 11
}
// MARK: UIPickerViewDelegate
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView {
var myImageView = UIImageView()
switch row {
case 0:
myImageView = UIImageView(image: UIImage(named:"airplane"))
case 1:
myImageView = UIImageView(image: UIImage(named:"beach"))
case 2:
myImageView = UIImageView(image: UIImage(named:"bike"))
case 3:
myImageView = UIImageView(image: UIImage(named:"hiking"))
case 4:
myImageView = UIImageView(image: UIImage(named:"ironman"))
case 5:
myImageView = UIImageView(image: UIImage(named:"moneybag"))
case 6:
myImageView = UIImageView(image: UIImage(named:"moneybills"))
case 7:
myImageView = UIImageView(image: UIImage(named:"ninjaturtle"))
case 8:
myImageView = UIImageView(image: UIImage(named:"running"))
case 9:
myImageView = UIImageView(image: UIImage(named:"shoppingcart"))
case 10:
myImageView = UIImageView(image: UIImage(named:"workingout"))
default:
myImageView.image = nil
return myImageView
}
return myImageView
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// do something with selected row
}
Making switch statements could be tedious when dealing with a lot of stuff.
Instead, use a for loop like this
for _ in 1..<imageArray.count {
myImageView.image = UIImage(named: imageArray[row])
}
You do not need to subclass UIPickerView (and in fact that is probably not a wise view to subclass anyhow). Instead you need to have an object that implements the UIPickerViewDelegate protocol. Within this object you would implement the method
optional func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView
This method provides the individual components' views. Within that method you would return the appropriate value from your image array.
var pickerDataSource = [UIImage(named:"house-7"),UIImage(named:"house-7"),UIImage(named:"house-7"),UIImage(named:"house-7"),UIImage(named:"house-7")]
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let myImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 61))
myImageView.image = pickerDataSource[row]
return myImageView
}