Customizing Section indexes in UITableView in iphone application
It doesn't look like standard index view is customizable.
In my application I just created custom index view instead of standard one. Basically all you need to do here is track touch position in that view and scroll UITableView accordingly. You may also need to add some visual effects - change view's background color on touch and highlight current section title.
Custom UITableView section index
I ended up using a custom view. It's not possible to customize the table index.
Adding section index headers for A to Z UITableView scrolling
Should we be sorting the Array into an alphabetised Array in some sort? So that it has multiple sections?
Yes.
You added the delegate methods for the section index, but you didn't show any code that actually performed the collation.
Here's some sample code from NSHipster showing how to use UILocalizedIndexedCollation
to collate an array of objects (e.g., contacts) into an array of sections of objects (e.g., contacts grouped by section):
let collation = UILocalizedIndexedCollation.currentCollation()
var sections: [[AnyObject]] = []
var objects: [AnyObject] = [] {
didSet {
let selector: Selector = "localizedTitle"
sections = Array(count: collation.sectionTitles.count, repeatedValue: [])
let sortedObjects = collation.sortedArrayFromArray(objects, collationStringSelector: selector)
for object in sortedObjects {
let sectionNumber = collation.sectionForObject(object, collationStringSelector: selector)
sections[sectionNumber].append(object)
}
self.tableView.reloadData()
}
}
You'll also want to update your remaining tableView delegates to use the sections
array:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return sections.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let contact = sections[indexPath.section][indexPath.row]
...
}
FYI, you can simplify your delegate code by assigning the collation property to your view controller, instead of repeatedly declaring a local variable for the (current) collation inside each delegate method. For example:
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String {
return collation.sectionTitles[section]
}
Adding index list and section headers to translated tableview
There are a few ways to accomplish this. One of the simplest is to use the delegate functions provided with UITableView.
For organizational purposes I'd start by creating a class to represent sections. Something like this:
class GhostSection {
// a title for this section
var sectionTitle: String
// a list of items for this particular section
var items: [Ghost] = []
init(title: String, items: [Ghost]) {
sectionTitle = title
self.items = items
}
}
Then update the list
variable to use the sections instead of a raw list of items:
var tabledata = [GhostSections]()
Ideally I'd create my GhostSection from a json object, but if it must be done manually then something like this would work:
// setup the table data to use GhostSection instances for each section
var tabledata = [
GhostSection(title: "a", items: [Ghost(name:"an".localized, sort:"sort.an".localized, id:"0101")]),
GhostSection(title: "b", items: [Ghost(name:"bc".localized, sort:"sort.bc".localized, id:"0102")]),
GhostSection(title: "c", items: [Ghost(name:"cd".localized, sort:"sort.cd".localized, id:"0103")])
]
I'd have numberOfSections(in tableView: UITableView)
return the tabledata count, which would be the count of the total number of sections:
func numberOfSections(in tableView: UITableView) -> Int {
return tabledata.count
}
and the numberOfRowsInSection
return the list count for each items
array on each GhostSection
in your tabledata array:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tabledata[section].items.count
}
Then I'd update cellForRow(at indexPath)
to return the info for the right cell in that section:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "library", for: indexPath)
// this gets the section data, then gets the item from that section
var data = list[indexPath.section].items[indexPath.row]
cell.textLabel?.text = data.name
return cell
}
I also like to create my headers as reusable nib views, so the ListHeaderView just has a title label in it:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// this loads the view from the nib
guard let view = ListHeaderView.fromNib() as? ListHeaderView else {
return nil
}
// get the section object for this current section
let data = tabledata[section]
// and set the title label text here from our section object
view.titleLabel.text = data.sectionTitle
return view
}
// if you want to also have a custom footer you can do that here...
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return UIView()
}
// and let the header height be dynamic, or return a set height here...
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableViewAutomaticDimension
}
In case you want to use this approach here's how I implemented the fromNib()
function so you can instantiate any view that has an associated .xib file:
public extension UIView {
public static func fromNib() -> UIView? {
let nibName = String(describing: self)
let bundle = Bundle(for: self)
let nib = UINib(nibName: nibName, bundle: bundle)
guard let view = nib.instantiate(withOwner: nil, options: nil).first as? UIView else {
print("Unable to instantiate nib named: \(nibName) in bundle: \(String(describing: bundle)) -- nib: \(String(describing: nib))")
return nil
}
return view
}
}
Also note it's a good idea to get in the habit of using camel case for class/object names with the first letter capitalized IF you want to keep with current conventions. So instead of naming your class ghost
get in the habit of doing Ghost
. For variables the convention is also camel case but start with a lowercase.
How to get custom section index titles as in Contacts app in iPhone
Got solution,
i followed this link: https://developer.apple.com/documentation/uikit/uilocalizedindexedcollation
class ObjectTableViewController: UITableViewController {
let collation = UILocalizedIndexedCollation.currentCollation()
var sections: [[AnyObject]] = []
var objects: [AnyObject] = [] {
didSet {
let selector: Selector = "localizedTitle"
sections = Array(count: collation.sectionTitles.count, repeatedValue: [])
let sortedObjects = collation.sortedArrayFromArray(objects, collationStringSelector: selector)
for object in sortedObjects {
let sectionNumber = collation.sectionForObject(object, collationStringSelector: selector)
sections[sectionNumber].append(object)
}
self.tableView.reloadData()
}
}
// MARK: UITableViewDelegate
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String {
return collation.sectionTitles[section]
}
override func sectionIndexTitlesForTableView(tableView: UITableView) -> [String] {
return collation.sectionIndexTitles
}
override func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
return collation.sectionForSectionIndexTitleAtIndex(index)
}
}
UITableview Sections Indexing Click Event
You can use the tableView(_:sectionForSectionIndexTitle:at:) method to return the appropriate section index when a index title is clicked.
let sectionArr = ["a","a","b","c","d","d"]
func numberOfSections(in tableView: UITableView) -> Int {
return sectionArr.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionArr[section]
}
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return Array(Set(sectionArr))//["a","b","c","d"]
}
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
if let index = sectionArr.firstIndex(where: { $0 == title }) {
return index//0 for a, 2 for b, 3 for c, 4 for d
}
return 0
}
Related Topics
Scroll Uitextfield Above Keyboard in a Uitableviewcell on a Regular Uiviewcontroller
How to Implement the Hashable Protocol in Swift for an Int Array (A Custom String Struct)
Workaround on the Threads Limit in Grand Central Dispatch
Toggling Privacy Settings Will Kill the App
Ios14 Introducing Errors with @State Bindings
Setneedslayout VS. Setneedsupdateconstraints and Layoutifneeded VS Updateconstraintsifneeded
Cannot Install Cocoa Pods After Uninstalling, Results in Error
Core Data - Failed to Load Optimized Model at Path
Example of Nsattributedstring with Two Different Font Sizes
Dyld: Symbol Not Found: _Nsurlauthenticationmethodclientcertificate When Trying to Run iOS App
Decoding JSON Web Tokens in Swift
How to Apply Uiappearance Proxy Properties to Uilabel
Google Sign-In Crashes on iOS 9 Attempting to Call Canopenurl
How to Run an Action When a State Changes
Objective-C Find Caller of Method
How to Make a Background Image Scale to Screen Size in Swift