iOS - Adding controls on top of AVPlayerViewController - ios

I have a subclass of AVPlayerViewController that I want to add my custom controls on it. I successfully added my custom controls on top of the AVPlayerViewController. However, these controls are only responsive for a short time. After a few seconds, clicking any of the button won't trigger the touchUpInside event.
Below is the code I'm using:
class LSPlayerViewController : AVPlayerViewController {
private var btnPlay : UIButton!
func addControls() {
self.showsPlaybackControls = false
//PLAY BUTTON
let btnPlayRect = CGRect(x: 0, y: 0, width: 19, height: 25)
btnPlay = UIButton(frame: btnPlayRect)
btnPlay.center = self.view.center
btnPlay.setImage(#imageLiteral(resourceName: "PauseIcon"), for: .normal)
btnPlay.addTarget(self, action: #selector(self.playButtonTapped(sender:)), for: .touchUpInside)
btnPlay.alpha = 0
btnPlay.isUserInteractionEnabled = true
self.view.addSubview(btnPlay)
}
func playButtonTapped(sender: UIButton!) {
if sender.isPlayIconOn == true {
sender.setImage(#imageLiteral(resourceName: "PauseIcon"), for: .normal)
self.player?.play()
} else {
sender.setImage(#imageLiteral(resourceName: "PlayIcon"), for: .normal)
self.player?.pause()
}
}

I solved the issue by adding the following two lines alongside the addSubview function:
self.addChildViewController(playerViewController)
playerView.addSubview(playerViewController.view)
playerViewController.didMove(toParentViewController: self)

Related

How to create a button programmatically with for loop in swift

I created buttons with for loop and i want to print button number when pressed to button. How can i do this?
for x in 0..<5 {
let button = UIButton(frame: CGRect(x: CGFloat(x) * view.frame.size.width + 10 , y: 40, width: view.frame.size.width - 20, height: 30))
buttonKontrol = x
print(buttonKontrol)
button.setTitle("Button", for: .normal)
button.backgroundColor = .white
button.setTitleColor(.black, for: .normal)
button.addTarget(self, action: #selector(btntapped), for: .touchUpInside)
scrollView.addSubview(button)
}
and objc func:
#objc func btntapped(_ sender: UIButton) {
print("button tapped")
}
Various ways to do that...
find the frame of the tapped button (not a good approach, but for your simple example it could work)
use the .tag property of the button
evaluate the .currentTitle property of the button
add the buttons to an array... on tap, use let buttonNumber = btnsArray.firstIndex(of: sender)
There are lots of ways, but a 'Swifty' way might be like this:
final class TargetAction {
let work: () -> Void
init(_ work: #escaping () -> Void) {
self.work = work
}
#objc func action() {
work()
}
}
class ViewController: UIViewController {
private var tas: [TargetAction] = []
override func viewDidLoad() {
super.viewDidLoad()
(0...4).forEach { x in
let button = UIButton(frame: CGRect(x: CGFloat(x) * 50 , y: 40, width: 44, height: 44))
button.setTitleColor(.black, for: .normal)
button.setTitle("\(x)", for: .normal)
let ta =
TargetAction {
print(x)
}
tas.append(ta)
button.addTarget(ta, action: #selector(TargetAction.action), for: .touchUpInside)
view.addSubview(button)
}
}
}

Swift: Cannot click button in subview

I have a ViewController, LockScreenVC, and am adding a UIView to it.
In that UIView, I am adding a UIButton. The button shows up, but I cannot click the button. If I add the button instead to the LockScreenVC, I can click the button - but it is no longer part of the UIView.
I've tried setting isUserInteractionEnabled to true, but that has not done anything.
import UIKit
class LockScreenVC: UIViewController {
lazy var detailContainer : UIView = {
let v = UIView();
v.backgroundColor = UIColor.black.withAlphaComponent(0.2)
return v
}()
lazy var detailButton: UIButton = {
let btn = UIButton(frame: CGRect(x: 10, y: 10, width: 300, height: 150))
btn.setTitle("Click Me", for: .normal)
return btn
}()
override func viewDidLoad() {
super.viewDidLoad()
detailButton.addTarget(self, action: #selector(onDetailButtonPressed), for: .touchUpInside)
detailContainer.addSubview(detailButton)
detailContainer.isUserInteractionEnabled = true
view.addSubview(detailContainer)
}
#objc func onDetailButtonPressed() {
print("You pressed the button!")
}
}
Your detailContainer has zero frame. Please set frame for it

Change Color of Programmatically Created Button when Pressed

I'm using a function to create multiple buttons for my game.
func createButton() {
let button = UIButton()
button.setTitle("", for: .normal)
button.frame = CGRect(x:15, y: 50, width: 200, height:100)
button.backgroundColor = UIColor.red
self.view.addSubview(button)
button.addTarget(self, action: Selector(("buttonPressed:")), for:
.touchUpInside)
}
I call this function once for testing in viewDidLoad function, but I don't know what code I should put into my buttonPressed() function for the color of my button to change? I tried doing
self.backgroundColor = UIColor.blue
but that didn't work. I also tried using UIButton and button instead of self, but both of those didn't work either. What should I do?
Your code isn't clean Swift 4 code. Here's how to do this:
Create your button like you are, but change Selector to #selector:
func createButton() {
let button = UIButton()
button.setTitle("", for: .normal)
button.frame = CGRect(x:15, y: 50, width: 200, height:100)
button.backgroundColor = UIColor.red
self.view.addSubview(button)
button.addTarget(self, action: #selector((buttonPressed)), for: .touchUpInside)
}
Use the sender that is automatically added:
#objc func buttonPressed(sender: UIButton) {
sender.backgroundColor = UIColor.blue
}
Additionally may I offer a few suggestions?
Check the background color before changing it. No sense in needlessly changing a button that is already blue.
Since you aren't setting the title to your button, set the tag property (you can even add this as a parameter to createButton). This way you can know which button was tapped.
Just make the button an instance property.
let changingButton = UIButton()
func createButton() {
changingButton.backgroundColor = UIColor.red
changingButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
}
#objc func buttonPressed() {
changingButton.backgroundColor = UIColor.blue
}

Adding UIButton to AVPlayer in iOS (Swift) When Video Plays in WebView

I'm putting together an iOS app (using Swift) that contains a webview. A user will click on a video in the webview and the video will load, at which time I want to display a button on the video. I've been able to display the button but it is not responding to touches and I'm not sure why. I made the button huge just to make sure it was being hit. Here's my code. I extended AVPlayerViewController.
Thanks in advance for your time and patience.
extension AVPlayerViewController {
open override func viewDidLoad() {
let btn = UIButton(type: .roundedRect)
btn.backgroundColor = UIColor.red
btn.setTitle("Do stuff", for: .normal)
btn.frame = CGRect(x: 0, y: 330, width: 300, height: 300)
btn.addTarget(self, action: #selector(self.pressButton(button:)), for: .touchUpInside)
btn.isUserInteractionEnabled = true
btn.isEnabled = true
btn.clipsToBounds = true
self.contentOverlayView?.addSubview((btn as? UIButton)!)
self.showsPlaybackControls = false
}
func pressButton(button: UIButton) {
print("Worked")
}
}
In your extension of AVPlayerViewController, you have overridden viewDidLoad method, which is not correct in my view. Instead you can add the button adding logic in the extension and call that method eherever ypu have initialized the AVPlayerViewController.
extension AVPlayerViewController {
func addButton() {
let btn = UIButton(type: .roundedRect)
btn.backgroundColor = UIColor.red
btn.setTitle("Do stuff", for: .normal)
btn.frame = CGRect(x: 0, y: 330, width: 300, height: 300)
btn.addTarget(self, action: #selector(self.pressButton(button:)), for: .touchUpInside)
btn.isUserInteractionEnabled = true
btn.isEnabled = true
btn.clipsToBounds = true
self.contentOverlayView?.addSubview((btn as? UIButton)!)
self.showsPlaybackControls = false
}
func pressButton(button: UIButton) {
print("Worked")
}
}

Selector method of UIButton not called during animation

I have dynamically created buttons on a dynamic view and later I add that dynamic view to main view.
Everything is working well except that the selector method of UIButton is not called.
var baseView:UIView?
override func viewDidLoad() {
super.viewDidLoad()
randomizeButtons()}
func randomizeButtons(){
baseView = UIView(frame:CGRectMake(view.bounds.origin.x + 10, view.bounds.origin.y + 50, view.bounds.size.width, view.bounds.size.height-20))
let viewWidth = baseView.bounds.size.width;
let viewHeight = baseView.bounds.size.height;
baseView.userInteractionEnabled = true
let i = GlobalArrayofUsers.count
var loopCount = 0
while loopCount < i{
let userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % viewWidth - 90) , abs(CGFloat(arc4random()) % viewHeight - 120), 90, 90))
print(userBaseView.frame)
userBaseView.backgroundColor = UIColor.redColor()
userBaseView.userInteractionEnabled = true
userBaseView.layer.cornerRadius = 45
userBaseView.clipsToBounds = true
let button = UIButton(frame: userBaseView.bounds)
button.backgroundColor = UIColor.greenColor()
button.showsTouchWhenHighlighted = true
button.addTarget(self, action: #selector(ViewController.handleTapEventofBtn(_:)), forControlEvents: .TouchUpInside)
button.setTitle("hello", forState: .Normal)
button.userInteractionEnabled = true
userBaseView.addSubview(button)
baseView.addSubview(userBaseView)
print("button frame is\(button.frame)")
baseView.bringSubviewToFront(userBaseView)
loopCount += 1
}
}
baseView.subviews.forEach { (users) in
UIView.animateWithDuration(1, delay: 0, options: [.Autoreverse,.Repeat], animations: {
users.center.y += 10
}, completion: nil)
}
view.insertSubview(baseView, atIndex: view.subviews.count)
}
func handleTapEventofBtn(sender: UIButton!) {
// handling code
}
Any idea why my selector method is not called? It is due to animation. How can i handle it.
SOLUTION: Allow userinteraction in UIAnimationOptions
The problem is that you are trying to click an object that is being animated. From the docs:
During an animation, user interactions are temporarily disabled for
the views being animated. (Prior to iOS 5, user interactions are
disabled for the entire application.)
But worry not, the solution is very easy, just call your animation with the option .AllowUserInteraction. For example (with your code):
UIView.animateWithDuration(1, delay: 0, options: [.Autoreverse,.Repeat,.AllowUserInteraction], animations: {
users.center.y += 10
}, completion: nil)
Have you tried this way:
for _ in 0...5{
// generate new view
let userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % viewWidth - 90) , abs(CGFloat(arc4random()) % viewHeight - 120), 90, 90))
userBaseView.backgroundColor = UIColor.redColor()
// add button to view
let button = UIButton(frame: userBaseView.bounds)
button.backgroundColor = UIColor.yellowColor()
button.showsTouchWhenHighlighted = true
button.addTarget(self, action: #selector(self.handleTapEventofBtn(_:)), forControlEvents: .TouchUpInside)
button.setTitle("hello", forState: .Normal)
userBaseView.addSubview(button)
}
self.view.addSubview(userBaseView)
All you need is to create userBaseView before cycle, then create buttons in cycle and add them to userBaseView, after that just add userBaseView to self.view or where you need to add it. In your example you create userBaseView in every iteration of the loop.
I think the problem could be here:
userBaseView.addSubview(button)
// add new view containing button to self.view
self.view.addSubview(userBaseView)
}
userBaseView.addSubview(button)
baseView.addSubview(userBaseView)
First you add userBaseView to self.view in the loop:
// add new view containing button to self.view
self.view.addSubview(userBaseView)
then add it to baseView:
baseView.addSubview(userBaseView)
Can you post how it looks like in IB?
The action has a parameter so the selector signature is actually takeActionBtn:
(note the colon at the end).
You need to change that or the button will try to call a version of the function with no parameter which doesn't exist.
button.addTarget(self, action: "button:",forControlEvents: UIControlEvents.TouchUpInside)
func button(sender: UIButton!) {
// handling code
print("1")
}
// hi. your problem is in the selector line. try this:
for _ in 0...5 {
// generate new view
let userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % self.view.frame.size.width - 90) , abs(CGFloat(arc4random()) % self.view.frame.size.height - 120), 90, 90))
userBaseView.backgroundColor = UIColor.redColor()
// add button to view
let button = UIButton(frame: userBaseView.bounds)
button.backgroundColor = UIColor.yellowColor()
button.showsTouchWhenHighlighted = true
button.addTarget(self, action: "buttonAction", forControlEvents: UIControlEvents.TouchUpInside)
button.setTitle("hello", forState: .Normal)
userBaseView.addSubview(button)
self.view.addSubview(userBaseView)
}
// tested with xcode 7.2
func buttonAction() {
print("working")
}

Resources