问题
How to change view based tableview cell height dynamically after loading data into cell using swift os x application. Programmatically I added labels to the custom view based on that i want to change the height of the tableview cell.
I used visual format language to add autolayout constraints. i have created imageview and labels programmatically inside custom view based nstableview cell. i want to change the cell height according to the labels added to the custom cell.
import Cocoa
class ViewController: NSViewController {
var fileName:String?
var size:String?
var image:NSImage?
var rowHeight:CGFloat?
var imageView:NSImageView?
var fileNameLabel:NSTextField?
var fileSizeLabel:NSTextField?
@IBOutlet weak var tableView: NSTableView!
var data: [Int:[String]]=[:]
let fileInfo=FileInfo()
override func viewDidLoad() {
super.viewDidLoad()
let nib = NSNib(nibNamed: "MyCellView", bundle: NSBundle.mainBundle())
tableView.registerNib(nib!, forIdentifier: "MyCellView")
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
@IBAction func scanAction(sender: AnyObject) {
var i:Int=0
let dictDupeFiles=fileInfo.enumerateDirectory()
print(dictDupeFiles.count)
for value in dictDupeFiles{
print(value)
}
for value in dictDupeFiles.values{
//print("\(key):\(value)")
data[i++]=value.componentsSeparatedByString("\n")
}
print(data.count)
tableView.reloadData()
}
}
extension ViewController: NSTableViewDataSource, NSTableViewDelegate {
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return data.values.count
}
func tableView(tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
let cell = tableView.makeViewWithIdentifier("MyCellView", owner: self) as! MyCellView
cell.bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds))
return 300
}
func RowHeightChanged(notification:NSNotification){
NSAnimationContext.beginGrouping()
NSAnimationContext.currentContext().duration=0
let indexSet:NSIndexSet=NSIndexSet(index: notification.object as! Int)
tableView.noteHeightOfRowsWithIndexesChanged(indexSet)
NSAnimationContext.endGrouping()
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cell = createCustomCellForRow(row)
NSAnimationContext.beginGrouping()
NSAnimationContext.currentContext().duration=0
cell.translatesAutoresizingMaskIntoConstraints=true
let indexSet:NSIndexSet=NSIndexSet(index: row)
tableView.noteHeightOfRowsWithIndexesChanged(indexSet)
NSAnimationContext.endGrouping()
return cell
}
func createCustomCellForRow(row:Int) -> MyCellView{
let cell = tableView.makeViewWithIdentifier("MyCellView", owner: self) as! MyCellView
let customConstraints=CustomViewConstraints()
var previousLabel:NSTextField?
var label:NSTextField?
if(data.count>0){
rowHeight=0.0
for object in cell.subviews
{
object.removeFromSuperview()
}
imageView=customConstraints.createImageView()
fileNameLabel=customConstraints.createFileNameLabel()
fileSizeLabel=customConstraints.createLabel()
cell.addSubview(imageView!)
cell.addSubview(fileNameLabel!)
cell.addSubview(fileSizeLabel!)
cell.translatesAutoresizingMaskIntoConstraints=true
for value in data[row]!{
if(value == ""){
continue
}else{
imageView!.image=customConstraints.makeThumbnail(value)
fileNameLabel!.stringValue=(value as NSString).lastPathComponent
let filesize=String(customConstraints.sizeForLocalFilePath(value))
size=(NSByteCountFormatter.stringFromByteCount(Int64(filesize)!,countStyle: NSByteCountFormatterCountStyle.Binary))
fileSizeLabel!.stringValue=size!
var views = ["imageView": imageView!,
"fileNameLabel": fileNameLabel!,
"fileSizeLabel": fileSizeLabel!]
var allConstraints = customConstraints.createConstraints(cell, value: value, views: views)
if(previousLabel == nil){
label=customConstraints.createLabel()
label?.stringValue=value
previousLabel=label
cell.addSubview(label!)
views["filePathLabel"]=label
let filePathLabelVerticalConstraints = customConstraints.createLayoutConstraints("V:[fileSizeLabel]-[filePathLabel]", views: views)
allConstraints += filePathLabelVerticalConstraints
let filePathLabelHorizontalConstraints = customConstraints.createLayoutConstraints("H:[imageView]-[filePathLabel]-|", views: views)
allConstraints += filePathLabelHorizontalConstraints
}else{
label=customConstraints.createLabel()
label?.stringValue=value
cell.addSubview(label!)
views["previousLabel"]=previousLabel
views["newFilePathLabel"]=label
let format:String?
if(value == data[row]?.last){
format="V:[previousLabel]-[newFilePathLabel]-|"
}else{
format="V:[previousLabel]-[newFilePathLabel]"
}
let newFilePathLabelVerticalConstraints = customConstraints.createLayoutConstraints(format!, views: views)
allConstraints += newFilePathLabelVerticalConstraints
let newFilePathLabelHorizontalConstraints = customConstraints.createLayoutConstraints("H:[imageView]-[newFilePathLabel]-|", views: views)
allConstraints += newFilePathLabelHorizontalConstraints
previousLabel=label
}
NSLayoutConstraint.activateConstraints(allConstraints)
rowHeight=(fileNameLabel?.frame.height)! + (fileSizeLabel?.frame.height)! + (previousLabel?.frame.height)! + 30
tableView.rowHeight=rowHeight!
NSNotificationCenter.defaultCenter().postNotificationName("RowHeightChanged", object: row)
}//end of if
}//end of for
}//end of if
return cell
}
func tableViewColumnDidResize(notification: NSNotification) {
tableView.reloadData()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "RowHeightChanged:", name:"RowHeightChanged" , object: notification.object)
}
}
Constraints which are added
var previousLabel:NSTextField?
var label:NSTextField?
func createConstraints(cell:MyCellView,value:String, views:[String:AnyObject]) -> [NSLayoutConstraint]{
var allConstraints = [NSLayoutConstraint]()
let imageViewHorizontalConstraints = createLayoutConstraints("H:|-[imageView]", views: views)
allConstraints += imageViewHorizontalConstraints
let imageViewVerticalConstraints = createLayoutConstraints("V:|-[imageView]", views: views)
allConstraints += imageViewVerticalConstraints
let fileNameHorizontalConstraints = createLayoutConstraints("H:[imageView]-[fileNameLabel]-|", views: views)
allConstraints += fileNameHorizontalConstraints
let fileSizeHorizontalConstraints = createLayoutConstraints("H:[imageView]-[fileSizeLabel]-|", views: views)
allConstraints += fileSizeHorizontalConstraints
let fileNameLabelVerticalConstraints = createLayoutConstraints("V:|-[fileNameLabel]", views: views)
allConstraints += fileNameLabelVerticalConstraints
let fileSizeLabelVerticalConstraints = createLayoutConstraints("V:[fileNameLabel][fileSizeLabel]", views: views)
allConstraints += fileSizeLabelVerticalConstraints
return allConstraints
}
func createLayoutConstraints(format:String,views:[String:AnyObject]) -> [NSLayoutConstraint]{
let constraint=NSLayoutConstraint.constraintsWithVisualFormat(
format,
options: [],
metrics: nil,
views: views)
return constraint
}
func createLabel() -> NSTextField{
let label = NSTextField(frame:NSMakeRect(0, 0, 0,0))
label.translatesAutoresizingMaskIntoConstraints=false
label.font=NSFont.systemFontOfSize(11)
label.selectable=false
label.drawsBackground=false
label.bezeled=false
label.editable=false
return label
}
func createFileNameLabel() -> NSTextField{
let label = NSTextField(frame:NSMakeRect(0, 0, 0,0))
label.translatesAutoresizingMaskIntoConstraints=false
label.font=NSFont.boldSystemFontOfSize(14)
label.selectable=false
label.drawsBackground=false
label.bezeled=false
label.editable=false
return label
}
func createImageView() -> NSImageView{
let imageView=NSImageView()
imageView.translatesAutoresizingMaskIntoConstraints=false
imageView.needsLayout=true
imageView.addConstraint(NSLayoutConstraint(item: imageView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 100))
imageView.addConstraint(NSLayoutConstraint(item: imageView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 100))
return imageView
}
func sizeForLocalFilePath(filePath:String) -> UInt64 {
do {
let fileAttributes = try NSFileManager.defaultManager().attributesOfItemAtPath(filePath)
if let fileSize = fileAttributes[NSFileSize] {
return (fileSize as! NSNumber).unsignedLongLongValue
} else {
print("Failed to get a size attribute from path: \(filePath)")
}
} catch {
print("Failed to get file attributes for local path: \(filePath) with error: \(error)")
}
return 0
}
func makeThumbnail(filePath:String) -> NSImage{
let size:NSSize=CGSizeMake(300, 300)
let option=NSDictionary(object: NSNumber(bool: false), forKey: kQLThumbnailOptionIconModeKey as NSString)
let fileURL=NSURL(fileURLWithPath: filePath)
if let thumb=QLThumbnailImageCreate(kCFAllocatorDefault, fileURL, size, option){
let thumbnail=NSImage(CGImage: thumb.takeUnretainedValue(), size: NSZeroSize)
return thumbnail
}else{
let image: NSImage = NSWorkspace.sharedWorkspace().iconForFile((fileURL).path!)
return image
}
}
来源:https://stackoverflow.com/questions/35285965/i-want-to-change-the-height-of-the-view-based-nstableview-cell-based-on-label-ad