背景
我需要获得一个正方形图像,以一个小的边距左右填充表格单元格,并使其适用于所有设备。
我处理不同设备的方法是以编程方式根据设备设置表格中的行高,并使用AspectFit使图像填充行 - 当我知道什么值时效果很好将行高设置为。只需要几个猜测就可以做到。
问题
图像在模拟器中的显示方式与在真实设备上显示的方式不同,使得在模拟器上无法进行测试并且需要确定真实设备。
这是图像和模拟器的已知问题吗?是否有一些我缺少的解决方法或设置?
我想让模拟器演示文稿与图像相关的设备演示文稿相匹配,这样我就可以有效地测试而无需访问大量的物理设备。
提前致谢。
参考图片
第一张图片来自iPhone 6模拟器。第二个(正确的)来自真正的iPhone 6设备。您不会从模拟器中猜出图像在实际设备上是正确的。
我们也看到了其他模拟器的问题,例如iPhone 7模拟器和iPhone SE模拟器,所以我们假设它是所有模拟器的问题。
此控制器的源代码
import UIKit
import AVFoundation
import GRDB
import SwiftPhotoGallery
class SpeciesDescriptionController: UITableViewController, SwiftPhotoGalleryDataSource, SwiftPhotoGalleryDelegate {
let tableCell = "TableCell"
var target_id : Int64 = 0
var item_scanned : Bool = false
let scanned = Scanned()
var species_array = [Species]()
var species : Species!
var primary_image : Image!
var image_names = [String]()
let favorites = Favorites()
@IBAction func toggle_favorites(_ sender: Any) {
if (favorites.check(species_id: species.id!) == true) {
favorites.remove(species_id: species.id!)
} else {
favorites.add(content_id: species.id!, table_name: "Species", display_name: species.display_name)
}
set_favorites_status()
}
@IBOutlet weak var favorites_status: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
loadSpeciesDescription()
loadPrimaryImage()
setTitle()
formatTable()
set_favorites_status()
if item_scanned == true {
scanned.add(content_id: species.id!, table_name: "Species", display_name: species.display_name)
}
let modelName = UIDevice.current.modelName
print("\n\nThe model name is: \(modelName)\n\n")
}
private func set_favorites_status() {
if (favorites.check(species_id: species.id!) == true) {
favorites_status.image = UIImage(named: "glyphicons-50-star")
} else {
favorites_status.image = UIImage(named: "glyphicons-49-star-empty")
}
}
private func loadSpeciesDescription() {
species = try! dbQueue.inDatabase { db in
try Species.fetchOne(db, key: target_id)
}
}
private func loadPrimaryImage() {
let visibleIdColumn = Column("visible_id")
let visibleTypeColumn = Column("visible_type")
let primaryPhotoColumn = Column("primary_photo")
let request = Image.filter(visibleIdColumn == species.id )
.filter(visibleTypeColumn == "Species")
.filter(primaryPhotoColumn == "t")
primary_image = try! dbQueue.inDatabase { db in
try request.fetchOne(db)
}
}
func formatTable() {
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
tableView.tableFooterView = UIView(frame: CGRect.zero) // deny empty table rows
}
func setTitle() {
self.title = species.display_name
}
func species_names() -> String {
var all_names: String = ""
let scientific_names = "Scientific: \(species.scientific_name)\n"
let common_names = "Common: \(species.common_name)"
let other_names = "\nNoongar: \(species.other_names)"
all_names = scientific_names + common_names
if (other_names != "\nNoongar: ") {
all_names = all_names + other_names
}
return all_names
}
/////////////////// Table //////////////////////////////
override func numberOfSections(in tableView: UITableView) -> Int {
return 6
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
var title : String = ""
switch section {
case 0 : title = " " // must have blank to print the blank section header
case 1 : title = "Names"
case 2 : title = "Audio"
case 3 : title = "Identification"
case 4 : title = "Description"
case 5 : title = "Range"
default: title = "Not defined..."
}
return title
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
if indexPath.section == 0 {
return CGFloat(row_height_for_device())
} else {
return UITableViewAutomaticDimension
}
}
func row_height_for_device() -> Int {
switch UIDevice.current.modelName {
case "iPhone SE" :
return 290 //confirmed to work with SE
case "iPhone 6", "iPhone 6s" :
return 290 // confirmed to work with 6
case "iPhone 7" :
return 348 //
case "iPhone 8" :
return 348 //
case "iPhone 6 Plus", "iPhone 6s Plus","iPhone 7 Plus", "iPhone 8 Plus" :
return 380
case "iPhone X" :
return 400
default:
// handles 2G, 3G, 3GS, 4, 4s, 5, 5s, 5c, SE
// confirmed to work with SE
return 290
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: tableCell) as UITableViewCell?
if (cell == nil) {
cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: tableCell)
}
cell!.imageView?.image = nil
cell!.imageView?.contentMode = .scaleAspectFit
cell!.textLabel?.text = nil
cell!.textLabel?.numberOfLines = 0
cell!.textLabel?.lineBreakMode = .byWordWrapping
cell!.textLabel?.font = UIFont.systemFont(ofSize: 16)
switch indexPath.section {
case 0 :
let image_file_name = "primary_\(primary_image.image_file_name)"
print("The image the app is looking for is called: \(image_file_name)")
cell!.imageView?.image = UIImage(named: image_file_name)
case 1 : cell!.textLabel?.text = species_names()
case 2 :
cell!.imageView?.image = UIImage(named: "glyphicons-169-ear-plugs")
cell!.textLabel?.text = "1 Minute Audio Summary"
case 3 : cell!.textLabel?.text = species.identification
case 4 : cell!.textLabel?.text = species.description
case 5 : cell!.textLabel?.text = species.range
default : cell!.textLabel?.text = ""
}
return cell!
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 2 {
textToSpeech(audio_summary: species.audio_summary)
}
if indexPath.section == 0 {
show_gallery(species_id: species.id!)
}
}
func standard_alert(_ alertTitle: String, alertMessage: String) -> Void {
let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Ok"), style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
func bail_out() {
performSegue(withIdentifier: "no_content", sender: nil)
}
func textToSpeech(audio_summary : String)
{
let synth = AVSpeechSynthesizer()
var myUtterance = AVSpeechUtterance(string: "")
myUtterance = AVSpeechUtterance(string: audio_summary)
myUtterance.voice = AVSpeechSynthesisVoice(language: "en-AU")
synth.speak(myUtterance)
}
///////////
func show_gallery(species_id: Int64) {
// load_image_names(species_id: species_id)
let image_file_name = "large_primary_" + primary_image.image_file_name
image_names = [image_file_name] // array of one item for now
let gallery = SwiftPhotoGallery(delegate: self, dataSource: self)
gallery.backgroundColor = UIColor.black
gallery.pageIndicatorTintColor = UIColor.gray.withAlphaComponent(0.5)
gallery.currentPageIndicatorTintColor = UIColor.white
gallery.hidePageControl = true
present(gallery, animated: true, completion: nil)
}
// MARK: SwiftPhotoGalleryDataSource Methods
func numberOfImagesInGallery(gallery: SwiftPhotoGallery) -> Int {
return image_names.count
}
func imageInGallery(gallery: SwiftPhotoGallery, forIndex: Int) -> UIImage? {
return UIImage(named: image_names[forIndex])
}
// MARK: SwiftPhotoGalleryDelegate Methods
func galleryDidTapToClose(gallery: SwiftPhotoGallery) {
dismiss(animated: true, completion: nil)
}
} // class
答案 0 :(得分:0)
根据评论讨论,最初的问题是由于“设备”显示选项设置为“缩放”。关闭缩放功能后,模拟器将再次与设备匹配。
另外,我假设目标是使图像居中放置在单元格中,并在每侧各留一点填充(约20点),同时保持正方形?如果是这样...
我建议创建一个自定义单元格类。
添加约束为UIImageView
的{{1}}。然后将图像视图设置为具有Top: 0, Bottom: 0, Leading 20, Trailing: 20
比率约束。
现在,图像视图将“自动”拉伸到单元格的宽度(减去填充),自动布局将设置高度以匹配宽度。无需手动计算/设置行高。