Закрепление кнопки UIB в указанном c месте на фотографии - PullRequest
0 голосов
/ 29 марта 2020

urbanPan

Привет,

У меня есть фотография с кнопками пользовательского интерфейса сверху. Кнопки пользовательского интерфейса должны быть в очень точном c и точном месте на фотографии.

Когда я изменяю размер фотографии (например, для разных устройств), кнопки пользовательского интерфейса никогда не остаются в выравнивании.

Контейнеры не работают, так как они относятся к размеру и ориентации экрана, а не к аспекту и размерам фотографии.

Например, когда фотография не обрезается на более крупных устройствах, таких как iPad, тогда контейнерные правила уже не актуальны.

Закрепление не работает, поскольку абсолютные значения не могут быть увеличены и изменены.

Я знаю, что я пытаюсь достичь возможно, как это часто встречается в других приложениях. Однако выравнивание и ограничения в XCode, кажется, не способствуют этому?

Я уверен, что что-то упустил. Любые идеи, с благодарностью.

См. Изображение urbanPan ниже или urbanPan.io для файлов Github.

urbanPan

Blessup, UrbanSma sh

Хотя проблема, по-видимому, более непосредственно связана с макетом Main.Storyboard, здесь код для ViewController.swift

//
//  ViewController.swift
//  urbanPan
//
//  Created by URBANSMASH pro on 29/08/2019.
//  Copyright © 2019 Play it on Pan. All rights reserved.
//

import UIKit
import AVFoundation
import AudioKit

class ViewController: UIViewController, AVAudioPlayerDelegate {

    var player : AVAudioPlayer!

    let sounds = ["Rest", "2-F3", "2-FS3", "2-G3", "2-GS3", "2-A3", "2-AS3", "2-B3", "2-C4", "2-CS4", "2-D4", "2-DS4", "2-E4", "2-F4", "2-FS4", "2-G4", "2-GS4", "2-A4", "2-AS4", "2-B4", "2-C5", "2-CS5", "2-D5", "2-DS5", "2-E5", "2-F5", "2-FS5", "2-G5", "2-GS5", "2-A5", "2-AS5", "2-B5", "2-C6"]

    var noteNum = 0

    let conductor = Conductor.shared
    var isPlaying = false
    var currentSound = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        conductor.midi.addListener(self)
        conductor.loadSamples(byIndex: currentSound)
    }


    @IBAction func noteReleased(_ sender: UIButton) {
        noteNum = sender.tag
//        player.currentTime = 0
        stopSound()

    }

    @IBAction func notePlayed(_ sender: UIButton) {
        noteNum = sender.tag
        //        player.currentTime = 0
        playSound()

    }

    func stopSound() {

        noteOff(note: MIDINoteNumber(noteNum))

    }

    func playSound() {

        noteOn(note: MIDINoteNumber(noteNum))

    }

    func noteOn(note: MIDINoteNumber) {
        DispatchQueue.main.async {
            self.conductor.playNote(note: note, velocity: 100, channel: 0)
        }
    }

    func noteOff(note: MIDINoteNumber) {
        DispatchQueue.main.async {
            self.conductor.stopNote(note: note, channel: 0)
        }
    }

}

extension ViewController: AKMIDIListener {

    func receivedMIDINoteOn(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, channel: MIDIChannel) {
        DispatchQueue.main.async {
            self.conductor.playNote(note: noteNumber, velocity: velocity, channel: channel)
        }
    }

    func receivedMIDINoteOff(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, channel: MIDIChannel) {
        DispatchQueue.main.async {
            self.conductor.stopNote(note: noteNumber, channel: channel)
        }
    }

    // MIDI Controller input
    func receivedMIDIController(_ controller: MIDIByte, value: MIDIByte, channel: MIDIChannel) {
        AKLog("Channel: \(channel + 1) controller: \(controller) value: \(value)")
        //conductor.controller(controller, value: value)
    }

    // MIDI Pitch Wheel
    func receivedMIDIPitchWheel(_ pitchWheelValue: MIDIWord, channel: MIDIChannel) {
        //conductor.pitchBend(pitchWheelValue)
    }

    // After touch
    func receivedMIDIAfterTouch(_ pressure: MIDIByte, channel: MIDIChannel) {
        conductor.afterTouch(pressure)
    }

    func receivedMIDISystemCommand(_ data: [MIDIByte]) {
        // do nothing: silence superclass's log chatter
    }

    // MIDI Setup Change
    func receivedMIDISetupChange() {
        AKLog("midi setup change, midi.inputNames: \(conductor.midi.inputNames)")
        let inputNames = conductor.midi.inputNames
        inputNames.forEach { inputName in
            conductor.midi.openInput(name: inputName)
        }
    }

    func setSpeakersAsDefaultAudioOutput() {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
        }
        catch {
            // hard to imagine how we'll get this exception
            let alertController = UIAlertController(title: "Speaker Problem", message: "You may be able to hear sound using headphones.", preferredStyle: UIAlertController.Style.alert)
            let okAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default) {
                (result: UIAlertAction) -> Void in
            }

            alertController.addAction(okAction)
            self.present(alertController, animated: true, completion: nil)
        }
    }



}

1 Ответ

0 голосов
/ 30 марта 2020

Для этого макета, я думаю, FrameLayout предпочтительнее, чем AutoLayout. Когда вызывается метод viewDidLayoutSubviews, вы вычисляете и обновляете размер и положение вида в соответствии с размером экрана.

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let screenSize = UIScreen.main.bounds
        // ... 
        d4View.frame = ...
    }
...