change custom view cell on click

心已入冬 提交于 2019-12-13 08:36:57

问题


i work with swift for osx. I have a nstableview (one row, one column) with a custom cell view. in the storyboard i have "designed" two different row layouts with identifiers CellLayout1 and CellLayout2

func numberOfRows(in tableView: NSTableView) -> Int {
   return dataArray.count
}


func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
   let view = tblPositions.make(withIdentifier: "CellLayout1", owner: nil) as! CustomCell
   view.txtName.stringValue = dataArray[row]
   return view
}

now i would like to show the CellLayout2, if i click on a row i use this function to check if the selection is changing:

func tableViewSelectionDidChange(_ notification: Notification) {
  // ?        
}

but now i don't know, how can i show the CellLayout2 for the selected row. can anybody help me? :)

UPDATE

var selectedRow = Int()

func numberOfRows(in tableView: NSTableView) -> Int {
   return dataArray.count
}

func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
    if selectedRow == row {
        return 200
    } else {
        return 60
    }
}


func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
   if selectedRow == row {
      let view = tableView.make(withIdentifier: "CellLayout1", owner: nil) as! CustomCell
            return view
        }
       let view = tableView.make(withIdentifier: "CellLayout2", owner: nil) as! CustomCell
        return view
}


func tableViewSelectionDidChange(_ notification: Notification) {
   selectedRow = tblPositions.selectedRow
   tblPositions.reloadData()
   //tblPositions.reloadData(forRowIndexes: tblPositions.selectedRowIndexes, columnIndexes: tblPositions.selectedColumnIndexes)
}

this way works nearly perfect - but:

  • the layout only changes if I reload the complete table. this code does not take any effect: //tblPositions.reloadData(forRowIndexes: tblPositions.selectedRowIndexes, columnIndexes: tblPositions.selectedColumnIndexes).

  • if i select a row, the tableview reload the data, the layout will change, but the selected row will deselected. this should not happen.


回答1:


To do a good MVC it should go like this.

  1. on cell click you are updating data model. For example change flag.
  2. model should trigger notification for that change
  3. your controller should observe model, and when notification was received that item was changed, you should pass this notification to a table view:

    tableView.func reloadData(forRowIndexes: rowsToUpdate columnIndexes: colmnToUpdate)

  4. table view will reload cell for given index

  5. it will invoke again func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) where you are providing cell which matches item flag.

When using Array as a data model than KVO can be used.


From some of my projects I have a good example how controller can look like. It is in Objective C, but should be helpful:
static char dummy = 0;
static NSString * const kImageCellsId = @"ImageCellView";
static NSString * const kDescriptionCellId = @"DescriptionCellView";

@interface CommonImagesViewController () <NSTableViewDataSource, NSTabViewDelegate>

@property (nonatomic, strong) IBOutlet NSTableView *tableView;
@property (nonatomic, strong) CommonImagesHandler *imageHandler;

@end

@implementation CommonImagesViewController

- (void)dealloc {
    [self.imageHandler removeObserver: self
                           forKeyPath: kCommonImagesHandlerImageCollectionKey
                              context: &dummy];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.imageHandler = ClientManager.getInstance.imageHandler;
    [self.imageHandler addObserver: self
                        forKeyPath: kCommonImagesHandlerImageCollectionKey
                           options: (NSKeyValueObservingOptions)0
                           context: &dummy];

    [self.tableView reloadData];
}

#pragma mark - NSTableViewDataSource
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
    return (NSInteger)self.imageHandler.imageCollection.count;
}

#pragma mark - NSTabViewDelegate
- (nullable NSView *)tableView: (NSTableView *)tableView
            viewForTableColumn: (nullable NSTableColumn *)tableColumn
                           row: (NSInteger)row
{
    ImageData *item = self.imageHandler.imageCollection[(NSUInteger)row];
    if (tableColumn == tableView.tableColumns[0]) {
        NSTableCellView *cell = (NSTableCellView *)[self.tableView makeViewWithIdentifier: kImageCellsId owner: nil];
        cell.imageView.image = item.image;
        cell.textField.stringValue = item.userDesc;
        return cell;
    }
    return nil;
}

#pragma mark - actions
- (IBAction)deleteAllEntries:(id)sender
{
    [self.imageHandler clearImageCollection];
}

- (IBAction)deleteSelected:(id)sender
{
    NSIndexSet *indexes = self.tableView.selectedRowIndexes;
    [self.imageHandler removeImageCollectionAtIndexes: indexes];
}

- (IBAction)viewImage:(id)sender
{
    // TODO:
}

#pragma mark - KVO
- (void)observeValueForKeyPath: (NSString *)keyPath
                      ofObject: (id)object
                        change: (NSDictionary *)change
                       context: (void *)context
{
    if (context == &dummy) {
        if (self.imageHandler == object && [keyPath isEqualToString: kCommonImagesHandlerImageCollectionKey]) {
            NSIndexSet *indexSet = change[NSKeyValueChangeIndexesKey];
            if (indexSet.count == 0) {
                return;
            }

            NSKeyValueChange changeType = (NSKeyValueChange)[change[NSKeyValueChangeKindKey] integerValue];
            switch (changeType) {
                case NSKeyValueChangeSetting:
                    [self.tableView reloadDataForRowIndexes: indexSet
                                              columnIndexes: [NSIndexSet indexSetWithIndex: 0]];
                    break;

                case NSKeyValueChangeInsertion:
                    [self.tableView insertRowsAtIndexes: indexSet withAnimation: NSTableViewAnimationSlideLeft];
                    break;

                case NSKeyValueChangeRemoval:
                    [self.tableView removeRowsAtIndexes: indexSet withAnimation: NSTableViewAnimationSlideRight];
                    break;

                case NSKeyValueChangeReplacement:
                    [self.tableView reloadData];
                    break;
            }
        }
    } else {
        [super observeValueForKeyPath: keyPath
                             ofObject: object
                               change: change
                              context: context];
    }
}

@end

Where self.imageHandler points to my data model, which contains array with full implemented support for KVO.



来源:https://stackoverflow.com/questions/45357639/change-custom-view-cell-on-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!