Disable TableView cells - ios

How can I disable all cells, except the first 3 cells of a UITableView?
This returns nil if one of the disabled cells is selected:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ( indexPath.row >= 3 ) {
[[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]] setAlpha:0.5];
return nil;
}
return indexPath; }
How can I make the disabled cells "visible"?
This works, but I only on start up, because the indexPath of every cell changes while scrolling (reuse cells):
for(int i = 3; i <= 100; i++) {
[[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]] setAlpha:0.5];
}

You can disable the cells by setting the selectionStyle property, see the code below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = ...
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
Another way to disable the cell selection is by disabling the user interaction of the cell. See the code below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = ...
cell.userInteractionEnabled = NO;
}
Enjoy. :)

It's best to set the opacity of the disabled cells in tableView:cellForRowAtIndexPath:. As #Parcs correctly says in their answer, you can also set userInteractionEnabled for the disabled cells to NO there.
You can just ignore the taps on inactive cells in tableView:didSelectRowAtIndexPath:.

Since the other answer providing code is outdated only showing how it's done in obj-c, here is a swift solution.
To disable a cell you need to set the isUserInteractionEnabled flag of a UITableViewCell to false.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// dequeue cell
...
cell.isUserInteractionEnabled = false
return cell
}
For subclasses of UITableViewCell you probably also want to alter the appearance of the now disabled cell. You can do so by overriding the property to run additional code when the flag gets set.
override var isUserInteractionEnabled: Bool {
didSet {
super.isUserInteractionEnabled = isUserInteractionEnabled
// additional code to change text colors for example
}
}

Related

How to increase and decrease the height of the custom cell in TableViewCell

I am new to iphone development. I am using custom tableview cell. In that I have to increase and decrease the custom cell height based upon the condition. I have increased but while increasing the custom cell the main tableview also increases. I need to increase only the custom cell. Below I have shown the code what I have used.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"test"];
if (!cell) {
cell= [[TableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"test"];
}
cell.backgroundColor = [UIColor blueColor];
// Configure the cell...
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
int testvalue=1;
if(testvalue == 1) {
return 45;
} else {
return 100;
}
}
Here I have attached screenshot.both main tableview and custom cell height is increasing. I don't want to increase main tableview cell height.
First of all , I would highly recommend to use UITableViewAutomaticDimension for your tableView , so that you dont have to worry about the cell size.
Now, as per your requirement, you want to change cell size for certain conditions, so you can do something like this:
Take one base view in cell which will have all other views as
subview.
Give height constraint to this base view and take outlet of that
height constraint.
Now when you want to increase or decrease the height, simply change
the height constarint constant value like
your_height_constraint.constant = your_new_value
Hope this helps you.
How I did was by Animating last view bottom constraints
func showOrHide() {
UIView.animate(withDuration: 0.2) {
if !self.isExpanded {
self.heightConstraint?.constant = 0
self.isExpanded = true
} else {
self.heightConstraint?.constant = 150
self.isExpanded = false
}
self.contentView.layoutIfNeeded()
}
}
And then calling beginUpdates and endUpdates on tableview adjust cell height else sinking will not work
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
cell.showOrHide()
tableview.beginUpdates()
tableview.endUpdates()
}

How do I hide the multi-select edit gui for certain cells in UITableView?

I am using UITableView, setting editing true, and using these options in interface builder:
This shows a nice selection UI whose style I can modify and events I can react to:
I want to turn this off, but only for certain cells. I've seen this and many similar questions, but they refer to a different type of selection in UITableView. UITableViewCellSelectionStyle.None and willSelectRowAtIndexPath do not allow me to block this type of selection.
Did you try to implement
func tableView(_ tableView: UITableView,
canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
in your delegate ?
I believe it will allow you to obtain the results you are trying to achieve.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if(indexPath.row == index of cell you don't want the selection for)
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = [a objectAtIndex:indexPath.row];
return cell;
}
For example:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *a = #[#"md",#"dh",#"kkd",#"dkkls"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if(indexPath.row == 2)
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = [a objectAtIndex:indexPath.row];
return cell;
}
it won't show selection for "kkd" in your tableview

UITableView Static cells - Selection color not working

I have a problem regarding my static cells. This is my tableview structure:
http://i.stack.imgur.com/1gq1y.png (I cant post images)
The cell background color is Gray and the contentView background color is ClearColor. The cell is not using a custom UITableViewCell subclass.
I set the Selection to Blue in the storyboad. However, when I run it, the output is Gray
I tried doing it manually in the didSelectRowAtIndexPath with this code:
currentCell.contentView.backgroundColor = self.view.tintColor;
but it turns out like this: http://i.stack.imgur.com/Zfatl.png
The Label in the Cell doesn't change to white and the Accessory background isn't changing. Please help. Thank you so much!
I am doing this selection this way. I have static header cells as 0-index rows in tableview's sections
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Did select row \(indexPath.row) in section \(indexPath.section)")
if indexPath.row > 0 {
let cell = tableView.cellForRow(at: indexPath)
cell?.selectionStyle = .gray
}
}
Add the following code to your TableView: cellForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Write code for create your cell and properties regarding that cell
//add this line
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor blueColor];
[cell setSelectedBackgroundView:bgColorView];
return cell;
}
add cell selection stylecolor as stylenone in cellForRowAtIndexPath method.
cell.selectionStyle = UITableViewCellSelectionStyleNone;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Write code for create your cell and properties regarding that cell
//add this line
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Note that in iOS 7, using
[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
will not work as expected, because in iOS 7 this is now gray, even if
you pass the constant above. See:
https://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html#//apple_ref/c/tdef/UITableViewCellSelectionStyle
Vern Jensen's answer:
https://stackoverflow.com/a/19257253/2575115

UICollectionView prevent cell re-use only for first cell

Using UICollectionView with a custom UICollectionViewCell, I am trying to add some extra information only to the first cell. For this I am overriding the GetCell method
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
This works fine and the first cell displays with the extra information. The problem is the cell is being re-used again in the CollectionView and the extra information is displayed again there.
How can I prevent re-use of the first cell in collection view?
Thanks!
Few options:
override prepareToReuse method of your UICollectionViewCell, and reset
what you want in that method
use different reuseIdentifiers for first
and others cells
use different prototypes/classes for first and other
cells
To use different reuse identifiers:
If you do it in the storyboard via protorypes, create another prototype for a first cell and do something like this in your UITableViewDatasource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
if (indexPath.row == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:#"FirstTableCell" forIndexPath:indexPath];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"UsualTableCell" forIndexPath:indexPath];
}
return cell;
}

Why is -didDeselectRowAtIndexPath not being called?

I created a fresh project (Xcode 4, Master-Detail application) just to see if I'm doing something wrong, but I still have the same problem. I want to call -reloadData when the user deselects a cell, so this is my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"%s", __PRETTY_FUNCTION__);
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"%s", __PRETTY_FUNCTION__);
[tableView reloadData];
}
-(NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"%s", __PRETTY_FUNCTION__);
return indexPath;
}
The problem is that didDeselectRowAtIndexPath and willDeselectRowAtIndexPath don't seem to be called. Is this the expected behavior? The docs for tableView:didDeselectRowAtIndexPath: state
Tells the delegate that the specified row is now deselected.
so I guess that it should work as I thought.
If you call deselectRowAtIndexPath:animated:, the delegate methods tableView:willDeselectRowAtIndexPath: and tableView:didDeselectRowAtIndexPath: message are not sent.
the documentation of tableView:willDeselectRowAtIndexPath: also says that
This method is only called if there is an existing selection when the
user tries to select a different row. The delegate is sent this method
for the previously selected row. You can use
UITableViewCellSelectionStyleNone to disable the appearance of the
cell highlight on touch-down.
It not worked for we when I used UITableViewCellSelectionStyleNone.
One other quirk that I've found — in IOS 5.1, at any rate — is that if you call reloadData on the table, you won't get didDeselectRowAtIndexPath for any selected rows. In my case, I adjust the cell layout slightly depending on whether it's selected or not, so I needed to manually do that work prior to reloading the table data.
I know this is an old question but I just ran into the same problem.
If you use
[tableView reloadData]
Then The table data is reloaded and no rows are selected behind the scenes - meaning
only
didSelectRowAtIndexPath
is ever called. I hope this helps someone who comes across this problem.
A clean way of solving this problem is to do the following:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath)
// Do your cell setup work here...
//If your cell should be selected...
if cellShouldBeSelected {
tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.None)
}
return cell
}
This solves this entire problem of a cell not responding to being deselected after a tableView.reloadData()call happens.
When any cell is selected the first time, the -[UITableViewDelegate tableView:didDeselectRowAtIndexPath:] method is not called, but the -[UITableViewDelegate tableView:didSelectRowAtIndexPath:]. Just after selecting one more cell, the didDeselectRowAtIndexPath is called right after the didSelectRowAtIndexPath.
This is OK.
But if you have to show a cell as selected at the begining, (e.q. using UITableViewCellAccessoryCheckmark), then, after selecting another cell you probably want the didDeselectRowAtIndexPath method being called the first time, to deselect the previous cell.
The solution!
You have to call the -[UITableView selectRowAtIndexPath:animated:scrollPosition:] in the -[UITableViewDataSource tableView:cellForRowAtIndexPath:] to notify that a wanted cell is already selected.
Objective-C
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// saving the current selected row
SelectedRow = indexPath.row;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
#pragma mark - UITableViewDataSource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
// preventing selection style
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = "Some text";
if (indexPath.row == SelectedRow) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// just wanted to make it selected, but it also can scroll to the selected position
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
return cell;
}
Swift 3.1
// MARK: - UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)!
cell.accessoryType = UITableViewCellAccessoryType.checkmark
selectedRow = indexPath.row
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)!
cell.accessoryType = UITableViewCellAccessoryType.none
}
// MARK: - UITableViewDataSource
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
// preventing selection style
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.textLabel?.text = "some text"
if (indexPath.row == selectedRow) {
cell.accessoryType = UITableViewCellAccessoryType.checkmark
// just wanted to make it selected, but it also can scroll to the selected position
tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)
}
return cell
}
You just have to set the selection to be "Multiple Selection" as Xcode allow you to deselect the cells in this mode only.
Xcode Screenshot
Set allowsMultipleSelection for that tableview to TRUE
self.tableView.allowsMultipleSelection = YES;
For me it's started working by adding ->super.setSelected(selected, animated: animated)
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)//This was missing
}
I think it's just simple mistake!
Why don't you use following:
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
Instead of using just "tableView" in that line?
I guess, and pretty sure that above line would give you the solution! hope this helped you, if you looked back at your old question!!!
Kudos! :)
First of all, you have to set allowsMultipleSelection is true and set delegate by below code
self.tableView.allowsMultipleSelection = true
self.tableView.delegate = self
If you use tableView.reloadData() in didSelectRowAt delegate method, remove this.
in your custom cell, use selected method.
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
//write your code here for selection method
}
By this method, your cell state is selected. If you again click on selected cell, then didDeSelect delegate method will call automatically.
One source of this issue is setting isSelected directly on the table view cell, rather than telling the table view to select the cell via selectRow(at:animated:scrollPosition:) or deselect it via deselectRow(at:animated:).
The cell's isSelected property is not the source of truth that the table view uses to determine whether to call the delegate's didDeselect method (although a cell whose isSelected is set does seem to prevent the table view from calling the delegate's didSelect method—meaning that the cell can get in a state where it is impossible to select or deselect via the UI).

Resources