为什么“填充比例”会生成比UIImageView尺寸更大的图像?(使用Swift)

29

我正在尝试使用PFQueryTableViewController来展示包括照片在内的地点名称列表。它包含在parse.com的ParseUI SDK中。

我已经成功显示了图片,但是当我将UIImageView模式更改为Aspect fill时,图片变得比应该更大。

以下是图片:

https://dl.dropboxusercontent.com/u/86529526/pic_normal.png https://dl.dropboxusercontent.com/u/86529526/pic_error.png

pic_normal中,您将看到两个单元格,每个单元格都有一个正常大小的图像。 在pic_error中,您会发现第二个单元格被第一个单元格的图像覆盖。

有人能帮我解决这个问题吗?我也将我的全部代码放在这里:

import UIKit

class TableViewController: PFQueryTableViewController, UISearchBarDelegate {

    @IBOutlet var searchBar: UISearchBar!


    // Initialise the PFQueryTable tableview
    override init(style: UITableViewStyle, className: String!) {
        super.init(style: style, className: className)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // Configure the PFQueryTableView
        self.pullToRefreshEnabled = true
        self.paginationEnabled = false
    }

    // Define the query that will provide the data for the table view
    override func queryForTable() -> PFQuery {

        // Start the query object
        var query = PFQuery(className: "Places")

        // query with pointer
        query.includeKey("mainPhoto")

        // Add a where clause if there is a search criteria
        if searchBar.text != "" {
            query.whereKey("name", containsString: searchBar.text)
        }

        // Order the results
        query.orderByAscending("name")

        // Return the qwuery object
        return query
    }


    //override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell? {
        var cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomTableViewCell!
        if cell == nil {
            cell = CustomTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CustomCell")
        }

        // Extract values from the PFObject to display in the table cell
        if let name = object["name"] as? String{
            cell.name.text = name
        }

        // display initial image
        var initialThumbnail = UIImage(named: "question")
        cell.photo.image = initialThumbnail


        // extract image from pointer
        if let pointer = object["mainPhoto"] as? PFObject {
            cell.detail.text = pointer["photoTitle"] as? String!
            if let thumbnail = pointer["photo"] as? PFFile {
                cell.photo.file = thumbnail
                cell.photo.loadInBackground()
            }
        }
        cell.sendSubviewToBack(cell.photo)

        // return the cell
        return cell
    }




    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        // Get the new view controller using [segue destinationViewController].
        var detailScene = segue.destinationViewController as! DetailViewController

        // Pass the selected object to the destination view controller.
        if let indexPath = self.tableView.indexPathForSelectedRow() {
            let row = Int(indexPath.row)
            detailScene.currentObject = objects[row] as? PFObject
        }
    }

    override func viewDidLoad(){
        super.viewDidLoad()
        let tapGesture = UITapGestureRecognizer(target:self, action:Selector("hideKeyboard"))
        tapGesture.cancelsTouchesInView = true
        tableView.addGestureRecognizer(tapGesture)
    }

    func hideKeyboard(){
        tableView.endEditing(true)
    }

    override func viewDidAppear(animated: Bool) {

        // Refresh the table to ensure any data changes are displayed
        tableView.reloadData()

        // Delegate the search bar to this table view class
        searchBar.delegate = self
    }

    func searchBarTextDidEndEditing(searchBar: UISearchBar) {

        // Dismiss the keyboard
        searchBar.resignFirstResponder()

        // Force reload of table data
        self.loadObjects()
    }

    func searchBarSearchButtonClicked(searchBar: UISearchBar) {

        // Dismiss the keyboard
        searchBar.resignFirstResponder()

        // Force reload of table data
        self.loadObjects()
    }

    func searchBarCancelButtonClicked(searchBar: UISearchBar) {

        // Clear any search criteria
        searchBar.text = ""

        // Dismiss the keyboard
        searchBar.resignFirstResponder()

        // Force reload of table data
        self.loadObjects()
    }

}

使UIImageView的模式为Aspect Fit。 - Rizwan Shaikh
我想填充UIImageVIew,但也要保持纵横比。 - Gibran
1
参考这个答案,你可以了解aspect fill和aspect fit之间的区别:https://dev59.com/QG445IYBdhLWcg3wXZO8 - Rizwan Shaikh
这个答案在所有的UIViewContentModes都无法解决问题时对我很有帮助。- https://dev59.com/jInca4cB1Zd3GeqP9E52#35685883 - Fitzgerald Afful
5个回答

97

当设置内容模式为Aspect Fill时,请尝试将裁剪边界设置为true,原因是内容模式aspect fill会继续填充图像视图的框架,直到框架完全填满内容,并保持aspect ratio不变。在保持宽高比的情况下填充图像容器时,无论是垂直还是水平框架被完全填充,填充将继续进行,直到另一个(如果是水平则是垂直或者相反)部分被完全填满。因此,第一个填充的部分(横向或纵向)将超出边界,而内容将在图像视图的框架外可见。为了裁剪额外的内容,我们需要使用imageView的clipsToBounds属性将多余部分裁剪掉并将其设置为true

cell.photo.contentMode = UIViewContentMode.ScaleAspectFill
cell.photo.clipsToBounds = true

17

2
那不能只是一个在问题下面的评论吗?你并没有真正提供答案,而仅仅是提供了参考。这就是人们通常提供小有帮助的贡献,虽然不完全符合由发布者提供的技术答案。 - clearlight
抱歉,答案非常冗长。此外,我认为最好将信用归于撰写该答案的人。我是 Stack Overflow 的新手,请建议我现在该怎么做。 - Avinash B
@AvinashB,你可以直接引用文章而不是回答。这样你仍然保留了对作者的致谢。更好的方法是:从文章中提取重要部分,并在SO上回答时提及信息来源。 - Korayem

9

如果您更喜欢使用 Interface Builder,则可以在选择 Aspect Fill 时,在图像视图中勾选 Clip Subviews,这样它就不会调整您的图像视图大小,但仍将保持相同的纵横比。

enter image description here


4

如果你想在宽度变化的情况下保持纵横比,那么请使用AspectFill,并且使用imageView属性clipstoBounds,这样它就不会将imageView扩展到框架之外。


3

来自苹果文档

UIViewContentModeScaleToFill

按比例缩放内容以适应自身大小,必要时更改内容的宽高比。

UIViewContentModeScaleAspectFill

按比例缩放内容以填充视图大小。可能会裁剪一部分内容以填充视图边界。

因此,您可以选择使用:

  • UIViewContentModeScaleToFill,并可能更改显示图像的宽高比,
  • UIViewContentModeScaleAspectFill,并在您的PFImageView上使用clipToBounds = YES,以将图像的某些部分裁剪到边界之外。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接