嗨,
我有一张照片,上面有UI按钮。 UI按钮必须位于照片上非常特定且精确的位置。
[当我调整照片尺寸时(例如,对于不同的设备),UI按钮永远不会对齐。
容器不起作用,因为它们相对于屏幕尺寸和方向,而不是照片的外观和尺寸。
例如,当照片在较大的设备(如iPad)上未裁剪时,则容器规则不再适用。
固定无效,因为无法按比例放大和调整绝对值。
我知道我想要实现的目标是可能的,因为这在其他应用程序中很常见。但是,Xcode中的对齐方式和约束似乎不方便吗?
我确定我缺少什么。任何想法,不胜感激。
请参见下面的urbanPan图片或Github文件的urbanPan.io。
祝福,UrbanSmash
尽管该问题似乎与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)
}
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let screenSize = UIScreen.main.bounds
// ...
d4View.frame = ...
}