UITableView section index spacing on iOS 7
Solution 1
One of possible solutions here - is to add empty string just after each adding of real title to your section index title array and returning index divided by 2 at your tableView: sectionForSectionIndexTitle: atIndex:
method.
This trick slightly increase distance between successive titles, but doesn't completely solve this problem.
Solution 2
Here is a implementation of Anton Malmygin answer, you can add more space by just adding more empty itens on the array:
First, let's create an array with the fake index.
NSArray *array = self.mydataArray; // here are your true index
self.sectionsTitle = [NSMutableArray array];
int n = array.count;
// In IOS 7 all index of the items are clumped together in the middle,
// making the items difficult to tap.
// As workaround we added "fake" sections index
// reference: https://stackoverflow.com/questions/18923729/uitableview-section-index-spacing-on-ios-7
for (int i = 0; i < n; i++){
[self.sectionsTitle addObject:array[i]];
[self.sectionsTitle addObject:@""];
}
Then, you can implement tableview delegate methods with the following approach:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
// In IOS 7 all index of the items are clumped together in the middle,
// making the items difficult to tap.
// As workaround we added "fake" sections index
// reference: https://stackoverflow.com/questions/18923729/uitableview-section-index-spacing-on-ios-7
if ([sectionsTitle[section] isEqualToString:@""]){
return 0;
}
return x; // return your desire section height
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
// In IOS 7 all index of the items are clumped together in the middle,
// making the items difficult to tap.
// As workaround we added "fake" sections index
// reference: https://stackoverflow.com/questions/18923729/uitableview-section-index-spacing-on-ios-7
if ([sectionsTitle[section] isEqualToString:@""]){
return nil;
}else{
// return your desire header view here,
// if you are using the default section header view,
// you don't need to implement this method
return // return your custom view
}
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.sectionsTitle;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
// In IOS 7 all index of the items are clumped together in the middle,
// making the items difficult to tap.
// As workaround we added "fake" sections index
// reference: https://stackoverflow.com/questions/18923729/uitableview-section-index-spacing-on-ios-7
if ([title isEqualToString:@""]){
return -1;
}
return [sectionsTitle indexOfObject:title];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// In IOS 7 all index of the items are clumped together in the middle,
// making the items difficult to tap.
// As workaround we added "fake" sections index
// reference: https://stackoverflow.com/questions/18923729/uitableview-section-index-spacing-on-ios-7
if ([sectionsTitle[section] isEqualToString:@""]){
return 0;
}
return // your logic here;
}
And here is the result:
Solution 3
There is a slightly easier way to complete Anton's suggestion, also it can be expanded to any number of indexes per section (instead of just having two as Anton suggested). So you add the number of extra index titles you want. In this example I used 4.
So first you add the things to an indexTitles
array, in viewDidLoad
or whatever.
NOTE: This can also be done dynamically if you are adding content to the tableView
asynchronously, that's why I added the if statement, so as long as its not the first
one it will replace the empty strings with periods. This is so there will be no stray
periods at the end
@property (nonatomic, strong) NSArray *indexTitles;
- (void) addIndexTitle:(NSString *) indexTitle {
if ([self.indexTitles count]) {
NSInteger last = self.indexTitles.count;
self.indexTitles[last - 1] = @".";
self.indexTitles[last - 2] = @"."; // Change the number of these depending
self.indexTitles[last - 3] = @"."; // on the number of lines in the index titles
}
[self.indexTitles addObject:indexTitle];
[self.indexTitles addObject:@""]; // Add different strings here for multiline
[self.indexTitles addObject:@""]; // index titles
[self.indexTitles addObject:@""];
}
Now we can just use the modulo operator depending on how many strings we have per index Title.
- (NSInteger) tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
index = index - index % 4; // This is the index of the section you want
NSInteger newIndex = index;
// do any other processing here (if need be) to determine the correct index here
return newIndex;
}
Don't forget to declare the the section index titles for the tableView.
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.indexTitles;
}
Here is one that I made that loads the content dynamically:
Solution 4
i found a workaround:
- (void)setIndexUIForTableView:(UITableView*)tableView{
//UI the index view
for(UIView *view in [tableView subviews]) {
if([view respondsToSelector:@selector(setIndexColor:)]) {
[view performSelector:@selector(setIndexColor:) withObject:[UIColor clientblack]];
if ([view respondsToSelector:@selector(setFont:)]) {
[view performSelector:@selector(setFont:) withObject:[UIFont systemFontOfSize:15.0]];
[view performSelector:@selector(setBackgroundColor:) withObject:[UIColor clientsidebarGray]];
}
}
}
}
add below into your method and after data is loaded
[self setIndexUIForTableView:tableview];
[tableview reloadData];
Solution 5
Here is something I played with and works. It follows Anton M's advice, uses Swift 2 and ios 9.
Let's say you have the following section indexes:
let indexes: [String] = ["A", "B", "C", "D", "E"]
So that everyone is on the same page, A is at index 0. B is at index 1 and so on.
Lets assume you want two spaces between indexes. Then define your section indexes as:
let indexes: [String] = ["A", "", "", "B", "", "", "C", "", "", "D", "", "", "E"]
So now, A is still at index 0 but B is now at index 3, C is at 6, D is at 9 and E is at 12.
All you need is to figure out the offset in the sectionForSectionIndexTitle. What you are after is the index of a real title as this is what you have in your table. Therefore:
override func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
return index / 3
}
So, for every extra space you need between the indexes you need to add 1 to the enumerator of the above expression. You can easily test this in Playground.
Related videos on Youtube
Comments
-
Senior almost 2 years
On iOS 6, my UITableView's section index would distribute all of its items evenly across the height of the table view. In iOS 7 all of the items are clumped together in the middle, making the items difficult to tap. Is there any way to space them out?
-
Matthew Burke over 10 yearsI don't think you can, unless you write your own control. The section index is implemented by an object of class UITableViewIndex and there doesn't seem to be any properties, methods to affect how the lines are spaced (see github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/…). I would file a request at bugreport.apple.com (and also post it to openradar.appspot.com
-
Senior over 10 yearsCool. See openradar.appspot.com/radar?id=6744206756282368 for reference.
-
Jatin over 10 yearshow did you resolve it?
-
DogCoffee over 10 yearsanyone come up with decent fix yet ?
-
denis631 almost 9 years@Senior so there is no solution found yet ?
-
-
Senior over 10 yearsHave you used this for positioning the labels?
-
Jatin over 10 yearsI used this for increasing the font size and positioning the labels properly by doing a reload twice.....once in cellforrowatindexpath and once when the data arrives
-
Jared Egan over 10 yearsThis is a silly hack, but is an easy fix and works well if you can predict the amount of section titles you want to show. I don't know why Apple choose to change this control in this way!
-
Guilherme Torres Castro over 10 yearsI just create an answer with the implementation of @Anton Malmygin solution.