0

In my application, I created a scrollView and set the width of this scrollView to twice the width of the screen. Then I created two contentViews. (contentView1 and contentView2) I use these contentViews as two screens. When I click on the "YENİ KAYIT" button in contentView1, the scrollView moves forward and contentView2 comes. The problem with contentView2 is that if I click anywhere other than the Stop button, it goes to an irrelevant place.

You can click here for detailed video : https://github.com/krmdmr7/ProgrammaticScrollView/assets/120031527/a873700b-9bd9-466c-b9b4-8670a1e8604a

You can click here for detailed code : https://github.com/krmdmr7/ProgrammaticScrollView

My UI Views :

    private var allRecordsScrollView: UIScrollView = {
        let allRecordsScrollView = UIScrollView()
        allRecordsScrollView.isPagingEnabled = true
        allRecordsScrollView.contentInsetAdjustmentBehavior = .never
        allRecordsScrollView.showsHorizontalScrollIndicator = false
        allRecordsScrollView.translatesAutoresizingMaskIntoConstraints = false
        allRecordsScrollView.contentSize = CGSize(width: UIScreen.main.bounds.width * 2, height: UIScreen.main.bounds.height)
        return allRecordsScrollView
    }()
    
    private var contentView1: UIView = {
        let contentView1 = UIView()
        contentView1.translatesAutoresizingMaskIntoConstraints = false
        contentView1.backgroundColor = UIColor(named: "LightGreen")
        return contentView1
    }()
    
    private var contentView2: UIView = {
        let contentView2 = UIView()
        contentView2.translatesAutoresizingMaskIntoConstraints = false
        contentView2.backgroundColor = UIColor(named: "Green")
        contentView2.isHidden = true
        return contentView2
    }()

Life Cycle :

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red
        configureUI()
    }

UI Görünümleri Kısıtlamaları :

    private func configureUI(){
        view.addSubview(allRecordsScrollView)
        NSLayoutConstraint.activate([
            allRecordsScrollView.topAnchor.constraint(equalTo: view.topAnchor),
            allRecordsScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            allRecordsScrollView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 2),
            allRecordsScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
            
        ])
        // ContentViews constraints for allRecordsScrollView
        allRecordsScrollView.addSubview(contentView1)
        allRecordsScrollView.addSubview(contentView2)
        NSLayoutConstraint.activate([
            // contentView1 constraints for scrollView
            contentView1.topAnchor.constraint(equalTo: allRecordsScrollView.topAnchor),
            contentView1.bottomAnchor.constraint(equalTo: allRecordsScrollView.bottomAnchor),
            contentView1.leadingAnchor.constraint(equalTo: allRecordsScrollView.leadingAnchor, constant: 0),
            contentView1.widthAnchor.constraint(equalTo: allRecordsScrollView.widthAnchor, multiplier: 0.5),
            contentView1.heightAnchor.constraint(equalTo: allRecordsScrollView.heightAnchor),
            
            // contentView2 constraints for scrollView
            contentView2.topAnchor.constraint(equalTo: allRecordsScrollView.topAnchor),
            contentView2.bottomAnchor.constraint(equalTo: allRecordsScrollView.bottomAnchor),
            contentView2.leadingAnchor.constraint(equalTo: contentView1.trailingAnchor),
            contentView2.widthAnchor.constraint(equalTo: allRecordsScrollView.widthAnchor, multiplier: 0.5),
            contentView2.heightAnchor.constraint(equalTo: allRecordsScrollView.heightAnchor)
        ])
}

Button Functions :

    @objc func recordButtonTapped() {
        print("Record button tapped.")
        contentView2.isHidden = false
        contentView1.isHidden = true
        let xOffset = allRecordsScrollView.frame.width / 2
        allRecordsScrollView.setContentOffset(CGPoint(x: xOffset, y: 0), animated: false)
    }
    
    @objc func stopRecordButtonTapped(){
        contentView2.isHidden = true
        contentView1.isHidden = false
        print("Stop record button tapped.")
        allRecordsScrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
    }

  • Do you want ***scrolling*** at all? Your code currently has `animated: false` when changing views, so we don't see `contentView1` and `contentView2` *sliding* left/right... and the user cannot drag them left/right. If that is what you want, there is no reason to use a scroll view. – DonMag Aug 22 '23 at 12:41
  • That's not the problem. If you download it from github and try it, you will see the problem. When I click somewhere other than the button in contentView2, it changes to a different view. – Kerem DEMİR Aug 22 '23 at 12:48
  • Yes, that **IS** the problem. To fix it, we need to know... do you ***want scrolling***? Or, do you just want to change between views? – DonMag Aug 22 '23 at 12:56
  • Which of these do you want? https://imgur.com/a/rXknr8b ... or, something completely different? – DonMag Aug 22 '23 at 13:05
  • I want the bottom one. But did you touch anything on the screen except the button? There's a problem there too. – Kerem DEMİR Aug 22 '23 at 13:23

1 Answers1

1

You are making things very overcomplicated by using a UIScrollView ... and you're using it incorrectly anyway.

A much easier approach is to:

  • add your "bubble" image as the first subview of the controller's view
  • set background color to .clear for both contentView1 and contentView2... that will allow the "bubble" image to "show through"
  • to view contentView1, show contentView1 and hide contentView2
  • to view contentView2, show contentView2 and hide contentView1

Here is a modified version of your complete ViewController class from your posted GitHub project:

class ViewController: UIViewController {
    
    // MARK : UI Elements
    private var contentView1: UIView = {
        let contentView1 = UIView()
        contentView1.translatesAutoresizingMaskIntoConstraints = false
        // clear
        //contentView1.backgroundColor = UIColor(named: "LightGreen")
        contentView1.backgroundColor = .clear
        return contentView1
    }()
    
    private var contentView2: UIView = {
        let contentView2 = UIView()
        contentView2.translatesAutoresizingMaskIntoConstraints = false
        // clear
        //contentView2.backgroundColor = UIColor(named: "Green")
        contentView2.backgroundColor = .clear
        return contentView2
    }()
    
    private let kendinYapLabel:UILabel = {
        let kendinYapLabel = UILabel()
        kendinYapLabel.translatesAutoresizingMaskIntoConstraints = false
        kendinYapLabel.font = UIFont(name: "Overpass-Bold", size: 24.0)
        kendinYapLabel.text = "KENDİN YAP"
        kendinYapLabel.textColor = .white
        return kendinYapLabel
    }()
    
    lazy var backButton: UIButton = {
        let backButton = UIButton()
        backButton.translatesAutoresizingMaskIntoConstraints = false
        backButton.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside)
        backButton.setImage(UIImage(named: "backIcon"), for: .normal)
        backButton.setTitleColor(UIColor.white, for: .normal)
        return backButton
    }()
    
    private let bigGreenTopBubbleImageView: UIImageView = {
        let bigGreenTopBubbleImageView = UIImageView()
        let image = UIImage(named: "bigGreenTopBubble")
        bigGreenTopBubbleImageView.translatesAutoresizingMaskIntoConstraints = false
        bigGreenTopBubbleImageView.image = image
        bigGreenTopBubbleImageView.contentMode = .scaleAspectFill
        return bigGreenTopBubbleImageView
    }()
    
    lazy var recordButton:UIButton = {
        let recordButton = UIButton()
        let image = UIImage(named: "recordButtonBGAll")
        recordButton.translatesAutoresizingMaskIntoConstraints = false
        recordButton.addTarget(self, action: #selector(recordButtonTapped), for: .touchUpInside)
        recordButton.setImage(image, for: .normal)
        return recordButton
    }()
    
    private let recorderVoicesLabel:UILabel = {
        let recorderVoicesLabel = UILabel()
        recorderVoicesLabel.translatesAutoresizingMaskIntoConstraints = false
        recorderVoicesLabel.text = "KAYITLI SESLER"
        recorderVoicesLabel.font = UIFont(name: "Overpass-Bold", size: 20.0)
        recorderVoicesLabel.textColor = .white
        return recorderVoicesLabel
    }()
    
    public var recordCounterLabel:UILabel = {
        let recordCounterLabel = UILabel()
        recordCounterLabel.translatesAutoresizingMaskIntoConstraints = false
        recordCounterLabel.font = UIFont(name: "Overpass-Regular", size: 100.0)
        recordCounterLabel.text = "00:00"
        recordCounterLabel.textColor = .white
        return recordCounterLabel
    }()
    
    public var recordingStatusLabel:UILabel = {
        let recordingStatusLabel = UILabel()
        recordingStatusLabel.translatesAutoresizingMaskIntoConstraints = false
        recordingStatusLabel.font = UIFont(name: "Overpass-Regular", size: 20.0)
        recordingStatusLabel.text = "Ses kaydı bekleniyor."
        recordingStatusLabel.textColor = .white
        return recordingStatusLabel
    }()
    
    lazy var stopRecordButton:UIButton = {
        let stopRecordButton = UIButton()
        let image = UIImage(named: "recordButtonStopIcon")
        stopRecordButton.translatesAutoresizingMaskIntoConstraints = false
        stopRecordButton.addTarget(self, action: #selector(stopRecordButtonTapped), for: .touchUpInside)
        stopRecordButton.setImage(image, for: .normal)
        return stopRecordButton
    }()
    
    
    // MARK : Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // set view background color
        view.backgroundColor = UIColor(named: "LightGreen")
        
        configure()
    }
    
    private func configure(){
        configureUI()
    }
    
    
    // MARK : Setup UI
    private func configureUI(){
        
        // add bigGreenTopBubbleImageView as the first subview
        //  the "content" views will have clear backgrounds,
        //  so we see the "bubble" image through them
        view.addSubview(bigGreenTopBubbleImageView)
        NSLayoutConstraint.activate([
            // BigGreenBubble constraints
            bigGreenTopBubbleImageView.topAnchor.constraint(equalTo: view.topAnchor, constant: -70),
            bigGreenTopBubbleImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0),
            bigGreenTopBubbleImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0),
            bigGreenTopBubbleImageView.heightAnchor.constraint(equalToConstant: 466),
        ])
        
        // add the two "content" views
        view.addSubview(contentView1)
        view.addSubview(contentView2)
        NSLayoutConstraint.activate([
            
            // constrain both "content" views to fill the view
            //  contentView2 will be "overlaid on top of" contentView1
            
            contentView1.topAnchor.constraint(equalTo: view.topAnchor),
            contentView1.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            contentView1.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            contentView1.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            
            contentView2.topAnchor.constraint(equalTo: view.topAnchor),
            contentView2.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            contentView2.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            contentView2.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            
        ])
        
        // add contentView1's subviews
        contentView1.addSubview(backButton)
        contentView1.addSubview(kendinYapLabel)
        contentView1.addSubview(recordButton)
        contentView1.addSubview(recorderVoicesLabel)
        NSLayoutConstraint.activate([
            // constrain subviews to contentView1, NOT to view
            // Back button constraints
            backButton.topAnchor.constraint(equalTo: contentView1.topAnchor, constant: 48),
            backButton.leadingAnchor.constraint(equalTo: contentView1.leadingAnchor, constant: 20),
            backButton.widthAnchor.constraint(equalToConstant: 50),
            backButton.heightAnchor.constraint(equalToConstant: 54),
            // KendinYapLabel constraints
            kendinYapLabel.centerXAnchor.constraint(equalTo: contentView1.centerXAnchor),
            kendinYapLabel.centerYAnchor.constraint(equalTo: backButton.centerYAnchor),
            // RecordButton constraints
            recordButton.topAnchor.constraint(equalTo: kendinYapLabel.bottomAnchor, constant: 55),
            recordButton.leadingAnchor.constraint(equalTo: contentView1.leadingAnchor, constant: 91),
            recordButton.trailingAnchor.constraint(equalTo: contentView1.trailingAnchor, constant: -91),
            recordButton.heightAnchor.constraint(equalToConstant: 77),
            // RecorderVoicesLabel constraints
            recorderVoicesLabel.topAnchor.constraint(equalTo: recordButton.bottomAnchor, constant: 20),
            recorderVoicesLabel.leadingAnchor.constraint(equalTo: contentView1.leadingAnchor, constant: 43),
            recorderVoicesLabel.heightAnchor.constraint(equalToConstant: 25.5)
        ])
        
        // add contentView2's subviews
        contentView2.addSubview(recordCounterLabel)
        contentView2.addSubview(recordingStatusLabel)
        contentView2.addSubview(stopRecordButton)
        NSLayoutConstraint.activate([
            // constrain subviews to contentView2, NOT to view
            // Record counter label constraints
            recordCounterLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 200),
            recordCounterLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            // Recording status label constraints
            recordingStatusLabel.topAnchor.constraint(equalTo: recordCounterLabel.bottomAnchor, constant: 10),
            recordingStatusLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            // Stop record button constraints
            stopRecordButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -132),
            stopRecordButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            stopRecordButton.widthAnchor.constraint(equalToConstant: 118),
            stopRecordButton.heightAnchor.constraint(equalToConstant: 118)
        ])

        // start with contentView2 hidden
        contentView2.isHidden = true
    }
    
    
    // MARK : Functions
    
    // MARK : Actions
    @objc func recordButtonTapped() {
        print("Record button tapped.")
        // hide contentView1, show contentView2
        contentView1.isHidden = true
        contentView2.isHidden = false
    }
    
    @objc func backButtonTapped() {
        print("Back button tapped.")
    }
    
    @objc func stopRecordButtonTapped(){
        print("Stop record button tapped.")
        // show contentView1, hide contentView2
        contentView1.isHidden = false
        contentView2.isHidden = true
    }
    
}
DonMag
  • 69,424
  • 5
  • 50
  • 86