I am trying to expand my UITableViewCell and I can expand cells. But I want to collapse the UITableViewCell which are not selected.
What I am trying in code:
var expandedCells = [Int]()
#IBOutlet weak var tableVieww:UITableView!
#IBAction func buttonPressed(_ sender: AnyObject) {
// If the array contains the button that was pressed, then remove that button from the array
if expandedCells.contains(sender.tag) {
expandedCells = expandedCells.filter({ $0 != sender.tag})
}
// Otherwise, add the button to the array
else {
expandedCells.append(sender.tag)
}
// Reload the tableView data anytime a button is pressed
tableVieww.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! exampleCell
cell.myButton.tag = indexPath.row
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// Set the row height based on whether or not the Int associated with that row is contained in the expandedCells array
if expandedCells.contains(indexPath.row) {
return 212
} else {
return 57
}
}
You can maintain a variable for maintaining the selected index as below,
var expandedIndexPath: IndexPath?
Then update your tableView delegate as follows,
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
expandedIndexPath = indexPath // Update the expandedIndexPath with the selected index
tableView.reloadData() // Reload tableview to reflect the change
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// Check wether expanded indexpath is the current index path and updated return the respective height
if expandedIndexPath == indexPath {
return 212
} else {
return 57
}
}
This should work fine.
1) First Create Bool Array variable
var isExpandArr = Array<Bool>()
2) Insert true at 0 index in ViewLoad()
isExpandArr.insert(true, at: 0)
3) Put Into cellForRowAt
cell.ToggleBT.addTarget(self, action: #selector(handleToggleBtn), for:.touchUpInside)
cell.ToggleBT.tag = indexPath.row
if isExpandArr[indexPath.row] == true{
cell.bottomrView.isHidden = false
}else{
cell.bottomrView.isHidden = true
}
4) set heightForRowAt
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return isExpandArr[indexPath.row] ? 204 : 60
}
5) put function
func handleToggleBtn(sender: UIButton){
print(sender.tag)
if isExpandArr.contains(true){
print("yes")
if let unwrappedIndex = isExpandArr.index(of: true){
isExpandArr[unwrappedIndex] = false
isExpandArr[sender.tag] = true
}
}
table.reloadData()
}
in #swift 2.3
Hope this will also helpful
For collapse and expand the header
define the variable above the viewDidLoad or within the class block
var headerIcon: UIImageView = UIImageView()
var sectionTitleArray : NSMutableArray = NSMutableArray()
var sectionContentEventTitleDict : NSMutableDictionary = NSMutableDictionary()
var sectionEventImagesDict : NSMutableDictionary = NSMutableDictionary()
var arrayForBool : NSMutableArray = NSMutableArray()
var arrFirstSectionItemTitle = ["Section 1 item Name 1","Section 1 item Name 2","Section 1 item Name 3","Section 1 item Name 4","Section 1 item Name 5","Section 1 item Name 6","Section 1 item Name 7"]
var arrFirstSectionItemImages = ["Section_1_icon_1","Section_1_icon_2","Section_1_icon_3","Section_1_icon_4","Section_1_icon_5","Section_1_icon_6","Section_1_icon_7"]
var arrSecondSectionItemTitle = ["Section 2 item Name 1","Section 2 item Name 2","Section 2 item Name 3","Section 2 item Name 4"]
var arrSecondSectionItemImages = ["Section_1_icon_1","Section_2_item_icon_2","Section_2_item_icon_3","Section_1_item_icon_4","Section_1_item_icon_5","Section_1_item_icon_6","Section_1_item_icon_7"]
var arrData: Array<Dictionary<String,AnyObject>> = Array<Dictionary<String,AnyObject>>()
#IBOutlet weak var tableList: UITableView!
in viewDidLoad() method write these lines of code
tableList.delegate = self
tableList.dataSource = self
tableList.backgroundColor = UIColor.getRGBColor(240, g: 240, b: 240)
let customView = UIView(frame: CGRectMake(0, 0, 200, 80))
customView.backgroundColor = UIColor.getRGBColor(240, g: 240, b: 240)
let customLine = UIView(frame: CGRectMake(0, 0, tblAllQuestion.frame.size.width, 1))
customLine.backgroundColor = UIColor.getRGBColor(240, g: 240, b: 240)
customView.addSubview(customLine)
tableList.tableFooterView = customView
now write the delegate and datasource methods as following:
//MARK: UITableViewDelegate AND UITableViewDataSource METHOD WITH SECTION
for number of sections to be collapsed and expand
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
print_debug(sectionTitleArray.count)
return sectionTitleArray.count
}
cell method:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CELL_IDENTIFIER", forIndexPath: indexPath)as! CellAllQuestionFiqhVC
//let cellIdentifier = "CellAllQuestionFiqhVC"
// cell = self.tableList.dequeueReusableCellWithIdentifier(cellIdentifier)
let manyCells : Bool = arrayForBool .objectAtIndex(indexPath.section).boolValue
if (!manyCells) {
// cell.textLabel.text = #"click to enlarge";
}
else{
let group = self.arrData[indexPath.section]
let data: Array<Dictionary<String,AnyObject>> = group["data"]as! Array<Dictionary<String,AnyObject>>
cell.configCell(data[indexPath.row], instance: self)
}
return cell
}
number cell in a section:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(arrayForBool.objectAtIndex(section).boolValue == true){
let count1 = arrData[section]["data"]!
if count1.count != nil {
return count1.count
}
}
return 0;
}
the height of the section
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
The height of the cell:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(arrayForBool.objectAtIndex(indexPath.section).boolValue == true){
return 100
}
return 2;
}
to set header tappable:
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, 40))
headerView.backgroundColor = UIColor.whiteColor()//Constant.kAPP_COLOR
headerView.tag = section
let headerString = UILabel(frame: CGRectMake(40/*tableView.frame.size.width/2-30*/, 10, tableView.frame.size.width, 18))
let headerLine = UIView(frame: CGRectMake(0, 39, tableView.frame.size.width, 1))
//UILabel(frame: CGRect(x: 20, y: 10, width: tableView.frame.size.width-10, height: 30)) as UILabel
//headerLine.text = sectionTitleArray.objectAtIndex(section) as? String
headerLine.backgroundColor = UIColor.getRGBColor(240, g: 240, b: 240)
headerView .addSubview(headerLine)
headerIcon = UIImageView(frame: CGRect(x: tblAllQuestion.bounds.maxX-30, y: 10, width: 8, height: 12)) as UIImageView
headerIcon.image = UIImage(named: "right_arrow")
headerView.addSubview(headerIcon)
let headerTapped = UITapGestureRecognizer(target: self, action: #selector(sectionHeaderTapped))
headerView.addGestureRecognizer(headerTapped)
return headerView
}
for rotate section icon on tapped on:
func rotateSectionIconOnTapped(indexTapped: Int) {
isActiveMap = false
if arrayForBool.objectAtIndex(indexTapped) as! NSObject == true {
print("toggle the icon at degree 90")
headerIcon.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
}
else if arrayForBool.objectAtIndex(indexTapped) as! NSObject == false {
print("toggle the ico at degree 0")
headerIcon.transform = CGAffineTransformMakeRotation(0)
}
}
action for section header tapped:
func sectionHeaderTapped(recognizer: UITapGestureRecognizer) {
//filterByCategoryIsOn = false
print("Tapping working")
print(recognizer.view?.tag)
//if recognizer.view!.tag != 2 {
let indexPath : NSIndexPath = NSIndexPath(forRow: 0, inSection:(recognizer.view?.tag as Int!)!)
if (indexPath.row == 0) {
for (indexx, bl) in arrayForBool.enumerate() {
if recognizer.view!.tag != indexx {
let index : NSIndexPath = NSIndexPath(forRow: 0, inSection:(indexx))
arrayForBool.replaceObjectAtIndex(index.section, withObject: false)
let range = NSMakeRange(index.section, 1)
let sectionToReload = NSIndexSet(indexesInRange: range)
self.tableList.reloadSections(sectionToReload, withRowAnimation:UITableViewRowAnimation.Fade)
}
}
var collapsed = arrayForBool.objectAtIndex(indexPath.section).boolValue
print_debug(collapsed)
collapsed = !collapsed;
print_debug(collapsed)
arrayForBool.replaceObjectAtIndex(indexPath.section, withObject: collapsed)
print(arrayForBool)
//reload specific section animated
let range = NSMakeRange(indexPath.section, 1)
let sectionToReload = NSIndexSet(indexesInRange: range)
self.tableList.reloadSections(sectionToReload, withRowAnimation:UITableViewRowAnimation.Fade)
rotateSectionIconOnTapped(recognizer.view!.tag)
}
}
get action for didselect row at index path :
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print_debug(indexPath)
print_debug(indexPath.row)
print_debug(indexPath.section)
if indexPath.section == 0 {
}
else if indexPath.section == 1 {
}
}
Related
Expanding and Collapsing is working fine tableview, Only facing issue while didselect row is tapped, I'm getting same index evry time after selecting a row. I'm getting the same out put, I want to pass the data to next view but output isn't working properly.
Here's My Details...
My OutPut
My Model
struct ItemList {
var name: String
var items: [String]
var collapsed: Bool
init(name: String, items: [String], collapsed: Bool = false) {
self.name = name
self.items = items
self.collapsed = collapsed
}
}
My ViewController Class
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var sections = [ItemList]()
var items: [ItemList] = [
ItemList(name: "Mac", items: ["MacBook", "MacBook Air"]),
ItemList(name: "iPad", items: ["iPad Pro", "iPad Air 2"]),
ItemList(name: "iPhone", items: ["iPhone 7", "iPhone 6"])
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
}
TableView Extension
extension ViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerHeading = UILabel(frame: CGRect(x: 5, y: 10, width: self.view.frame.width, height: 40))
let imageView = UIImageView(frame: CGRect(x: self.view.frame.width - 30, y: 20, width: 20, height: 20))
if items[section].collapsed{
imageView.image = UIImage(named: "collapse")
}else{
imageView.image = UIImage(named: "expand")
}
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 60))
let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(headerViewTapped))
tapGuesture.numberOfTapsRequired = 1
headerView.addGestureRecognizer(tapGuesture)
headerView.backgroundColor = UIColor.red
headerView.tag = section
headerHeading.text = items[section].name
headerHeading.textColor = .white
headerView.addSubview(headerHeading)
headerView.addSubview(imageView)
return headerView
}
func numberOfSections(in tableView: UITableView) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
let itms = items[section]
return !itms.collapsed ? 0 : itms.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = items[indexPath.section].items[indexPath.row]
return cell
}
#objc func headerViewTapped(tapped:UITapGestureRecognizer){
print(tapped.view?.tag)
if items[tapped.view!.tag].collapsed == true{
items[tapped.view!.tag].collapsed = false
}else{
items[tapped.view!.tag].collapsed = true
}
if let imView = tapped.view?.subviews[1] as? UIImageView{
if imView.isKind(of: UIImageView.self){
if items[tapped.view!.tag].collapsed{
imView.image = UIImage(named: "collapsed")
}else{
imView.image = UIImage(named: "expand")
}
}
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let row = items[indexPath.row]
print("IndexPath :- \(row.name)")
}
}
If you look at the way you are setting the text in your cells in cellForRowAt:
cell.textLabel?.text = items[indexPath.section].items[indexPath.row]
You are saying:
get the ItemList object for indexPath.section from items array
get the String from that object's items array of this indexPath.row
However, in your didSelectRowAt:
let row = items[indexPath.row]
print("IndexPath :- \(row.name)")
You are saying:
get the ItemList object for indexPath.row from items array
print the .name property of that object
So, change your didSelectRowAt code to match your cellForRowAt logic:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedString = items[indexPath.section].items[indexPath.row]
print("IndexPath :- \(selectedString)")
// or, for a little more clarity
let sectionObject = items[indexPath.section]
let rowItem = sectionObject.items[indexPath.row]
print("IndexPath :- \(indexPath) // Section :- \(sectionObject.name) // Item :- \(rowItem)")
}
I added an arrow to fold the section when clicked, when I fold the last section (e.g. setting the row height to 0 in cellForRow, all the rows in the last section get mixed up, as can be seen in the image below:
Can anyone suggest any reason why this should happen if I'm setting the height of the row to 0?
Here's the relevant code:
viewForHeaderInSection:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section == 0 {
let profileCompletion = clientFields?.profileCompletion ?? 0
headerView.profileComplete.text = "Profile".localized() + " \(profileCompletion)% " + "Complete".localized()
headerView.profileProgress.progress = Float(profileCompletion) * 0.01
headerView.profileProgress.progressTintColor = Constants.Client.getProfileCompletenessColor(profileCompletion)
headerView.delegate = self
headerView.section = section
headerView.isOpen = self.sectionsStatuses[section].shouldDisplaySection
return headerView
}
else {
let height = (section == 0) ? FIRST_HEADER_HEIGHT : HEADER_HEIGHT
let nib = UINib(nibName: "ClientDetailsSectionHeaderCell", bundle: nil)
guard let returnedView = nib.instantiate(withOwner: self, options: nil)[0] as? ClientDetailsSectionHeaderCell else {
return UIView()
}
returnedView.delegate = self
returnedView.section = section
returnedView.isOpen = self.sectionsStatuses[section].shouldDisplaySection
returnedView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: height)
returnedView.heightConstraint.constant = height
returnedView.mainView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
returnedView.mainView.backgroundColor = Constants.ParentForm.headerBgColor
// Draw separators
if DRAW_SECTION_SEPARATORS || DRAW_SECTION_TOP_SEPARATOR {
returnedView.createTopSeparator(color: Constants.ParentForm.separatorColor)
}
if DRAW_SECTION_SEPARATORS || DRAW_SECTION_BOTTOM_SEPARATOR {
returnedView.createBottomSeparator(color: Constants.ParentForm.separatorColor)
}
if isSectionTitleHidden == false {
let xOffset = HEADER_X_OFFSET
let yOffset = section == 0 ? FIRST_HEADER_Y_OFFSET : HEADER_Y_OFFSET
returnedView.title.frame = CGRect(x: xOffset, y: yOffset, width: view.frame.size.width - xOffset, height: height - yOffset)
returnedView.title.text = self.sectionsArray[section].uppercased().localized()
returnedView.title.font = Constants.ParentForm.headerFont
returnedView.title.textColor = Constants.ParentForm.headerTextColor
returnedView.title.sizeToFit()
}
return returnedView
}
}
heightForRow
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if sectionsStatuses[indexPath.section].shouldDisplaySection {
return super.tableView(tableView, heightForRowAt: indexPath)
}
return CGFloat(0)
}
cellForRow
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if self.sectionsArray[indexPath.section] != "ADDRESSES" {
if let clientFields = self.clientFields {
self.dataMap = Utils.convertObjectToMap(item: clientFields)
let birthdayDate = clientFields.birthdayDateString
self.dataMap["birthdayDate"] = birthdayDate
let createdDate = clientFields.createdDateString
self.dataMap["createdDate"] = createdDate
}
}
else {
if let clientAddresses = self.clientAddresses, clientAddresses.count > 0 {
self.dataMap = Utils.convertObjectToMap(item: clientAddresses[Int(floor(Double(indexPath.row) / 8.0))])
}
}
return super.tableView(tableView, cellForRowAt: indexPath)
}
protocol function
func openCloseSection(openSection: Bool, section: Int) {
self.sectionsStatuses[section].shouldDisplaySection = openSection
self.tableView.reloadData()
}
ClientDetailsSectionHeaderCell
import UIKit
protocol SectionViewerProtocol {
func openCloseSection(openSection: Bool, section: Int)
}
class ClientDetailsSectionHeaderCell: UITableViewCell {
#IBOutlet weak var mainView: UIView!
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
#IBOutlet weak var accessoryButton: UIButton!
#IBOutlet weak var title: UILabel!
var section = 0
var delegate: SectionViewerProtocol?
var isOpen: Bool? {
didSet {
if let isOpen = self.isOpen {
accessoryButton.setImage(UIImage(named: isOpen ? "fill588": "fill589"), for: .normal)
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
}
#IBAction func openCloseSection(_ sender: UIButton) {
if let isOpen = self.isOpen {
self.isOpen = !isOpen
delegate?.openCloseSection(openSection: !isOpen, section: section)
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Try setting clipsToBounds of your cell or any enclosing UIView to true.
I have tried n number of solutions, but still no luck. I designed my own Custom cell for Header of a Section. So my table renders properly.
Then for each header cell in func viewForHeaderInSection(), I've added tap gesture to handle click on header. But every time I click on any header it disappears from the table. I haven't written any code of deleting sections.
func numberOfSections(in tableView: UITableView) -> Int {
return ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray.count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "AccordianHeaderPrototypeCell") as! AccordianHeaderPrototypeCell
let cellinfo = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section]
cell.headingLabel.text = cellinfo.title
cell.arrowImage.tag = kHeaderSectionTag + section
cell.arrowImage.image = Constants.DOWNARROW_IMAGE
cell.tag = section
let headerTapGesture = UITapGestureRecognizer()
headerTapGesture.addTarget(self, action: #selector(self.sectionHeaderWasTouched(_:)))
cell.addGestureRecognizer(headerTapGesture)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.expandedSectionHeaderNumber == section) {
return ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section].contentArray.count
} else {
return 0;
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductDetailingsPrototypeCell", for: indexPath) as! ProductDetailingsPrototypeCell
cell.separatorInset = .zero
let cellinfo = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[indexPath.section].contentArray[indexPath.row]
cell.descriptionLabel.attributedText = cellinfo.html2Attributed
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
#objc func sectionHeaderWasTouched(_ sender: UITapGestureRecognizer) {
let headerView = sender.view as! AccordianHeaderPrototypeCell
let section = headerView.tag
let eImageView = headerView.viewWithTag(kHeaderSectionTag + section) as? UIImageView
if (self.expandedSectionHeaderNumber == -1) {
self.expandedSectionHeaderNumber = section
tableViewExpandSection(section, imageView: eImageView!)
} else {
if (self.expandedSectionHeaderNumber == section) {
tableViewCollapeSection(section, imageView: eImageView!)
} else {
let cImageView = self.view.viewWithTag(kHeaderSectionTag + self.expandedSectionHeaderNumber) as? UIImageView
tableViewCollapeSection(self.expandedSectionHeaderNumber, imageView: cImageView!)
tableViewExpandSection(section, imageView: eImageView!)
}
}
}
func tableViewCollapeSection(_ section: Int, imageView: UIImageView) {
let sectionData = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section].contentArray
self.expandedSectionHeaderNumber = -1
if (sectionData.count == 0) {
return
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (0.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
self.itemsTableView!.beginUpdates()
self.itemsTableView!.deleteRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.itemsTableView!.endUpdates()
}
}
func tableViewExpandSection(_ section: Int, imageView: UIImageView) {
let sectionData = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section].contentArray
if (sectionData.count == 0) {
self.expandedSectionHeaderNumber = -1
return
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (180.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
self.expandedSectionHeaderNumber = section
self.itemsTableView.beginUpdates()
self.itemsTableView.insertRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.itemsTableView.endUpdates()
}
}
Adding two images to explain what happens before and after click.
I have placed a tableview2 in tableview1 Cell, Now when I click on the tableview2 cell I need to navigate to a new viewController. Please help me... I was struggling with one whole day :(
here is the code, the second table view is placed in SegmentedCell...
when i am trying to push, its unable to go next controller..
import UIKit
import XMSegmentedControl
import Alamofire
import SwiftyJSON
class segmentedCell: UITableViewCell, XMSegmentedControlDelegate, UITableViewDelegate, UITableViewDataSource{
let byndrColor : UIColor = UIColor( red: 224/255, green: 0/255, blue: 115/255, alpha: 1.0 )
let fontStyle = UIFont(name: "Lato-bold", size: 12)
#IBOutlet weak var segmentedControl: XMSegmentedControl!
#IBOutlet weak var feedTableView: UITableView!
var getApi = UIApplication.shared.delegate as! AppDelegate
var course_id = String()
var materialListObjects = [MaterialsInSingleCourseGetSet]()
var assignmentExamAndQuizListObjects = [AssignmentAndExamsQuizGetSet]()
override func awakeFromNib() {
super.awakeFromNib()
feedTableView.delegate = self
feedTableView.dataSource = self
segmentedControl.delegate = self
segmentedControl.segmentTitle = ["LATEST", "MATERIALS", "COURSEWORK", "PROGRESS"]
segmentedControl.font = fontStyle!
segmentedControl.selectedItemHighlightStyle = XMSelectedItemHighlightStyle.BottomEdge
segmentedControl.backgroundColor = UIColor.white
segmentedControl.tint = UIColor.black
segmentedControl.highlightTint = byndrColor
segmentedControl.highlightColor = byndrColor
segmentedControl.edgeHighlightHeight = 2
segmentedControl.selectedSegment = 0
let share = UIApplication.shared.delegate as! AppDelegate
materialListObjects = share.materialListInSingleCourse as! [MaterialsInSingleCourseGetSet]
assignmentExamAndQuizListObjects = share.assignmentsExamsAndQuizListInSingleCourse as! [AssignmentAndExamsQuizGetSet]
// Initialization code
}
func xmSegmentedControl(xmSegmentedControl: XMSegmentedControl, selectedSegment: Int) {
if xmSegmentedControl == segmentedControl {
print("SegmentedControl1 Selected Segment: \(selectedSegment)")
switch segmentedControl.selectedSegment
{
case 0:
feedTableView.reloadData()
case 1:
feedTableView.reloadData()
case 2:
feedTableView.reloadData()
case 3:
feedTableView.reloadData()
default :
break
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if segmentedControl.selectedSegment == 0
{
return 0
}
else
if segmentedControl.selectedSegment == 1
{
return materialListObjects.count
}
else
if segmentedControl.selectedSegment == 2
{
return assignmentExamAndQuizListObjects.count
}
else
{
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if segmentedControl.selectedSegment == 0
{
let cell = Bundle.main.loadNibNamed("TypeOneCell", owner: self, options: nil)?.first as! TypeOneCell
return cell
}
else
if segmentedControl.selectedSegment == 1
{
if materialListObjects[indexPath.row].type == "file"
{
let cell = Bundle.main.loadNibNamed("materialCellOne", owner: self, options: nil)?.first as! materialCellOne
cell.materialNameLabel.text = materialListObjects[indexPath.row].title
let image = materialListObjects[indexPath.row].title
cell.contentImage.image = image.documentType(givenType: image)
return cell
}else
{
let cell = Bundle.main.loadNibNamed("materialCellTwo", owner: self, options: nil)?.first as! materialCellTwo
cell.materialNameLabel.text = materialListObjects[indexPath.row].title
cell.contentImage.image = #imageLiteral(resourceName: "material_hyperlink")
return cell
}
}
else
if segmentedControl.selectedSegment == 2
{
let cell = Bundle.main.loadNibNamed("CourseWorkCell", owner: self, options: nil)?.first as! CourseWorkCell
print("assignment title : \(assignmentExamAndQuizListObjects[indexPath.row].title)")
cell.titleLabel.text = assignmentExamAndQuizListObjects[indexPath.row].title
if assignmentExamAndQuizListObjects[indexPath.row].type == ""
{
cell.contentImage.image = #imageLiteral(resourceName: "assignment_large")
}else
{
cell.contentImage.image = #imageLiteral(resourceName: "exam_inline")
}
var time = assignmentExamAndQuizListObjects[indexPath.row].start
time = time.dateRange(dateString: time)
time = time.days(givenDate: time)
cell.timeLabel.text = time
return cell
}
else
if segmentedControl.selectedSegment == 3
{
let cell = Bundle.main.loadNibNamed("TypeOneCell", owner: self, options: nil)?.first as! TypeOneCell
return cell
}
else
{
let cell = Bundle.main.loadNibNamed("TypeOneCell", owner: self, options: nil)?.first as! TypeOneCell
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if segmentedControl.selectedSegment == 2
{
return 70
}
else
{
return 100
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRect.zero)
let label = UILabel(frame: CGRect(x: 8, y: 8, width: 150, height: 20))
view.addSubview(label)
label.font = UIFont(name: "Lato-Heavy", size: 17)
if segmentedControl.selectedSegment == 1
{
switch section {
case 0:
label.text = "All Materials"
case 1:
label.text = "From Your Courses"
default:
break
}
}
else
if segmentedControl.selectedSegment == 2
{
switch section {
case 0:
label.text = "All CourseWork"
case 1:
label.text = "From Your Courses"
default:
break
}
}
else
{
}
return view
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
//How to perform from here
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if segmentedControl.selectedSegment == 1
{
let storyboard = UIStoryboard(name: "Main", bundle : nil)
let nextViewController = storyboard.instantiateViewController(withIdentifier: "QuickLook") as! QuickLook
if materialListObjects[indexPath.row].type == "url"
{
nextViewController.id = materialListObjects[indexPath.row].body
nextViewController.type = "url"
}
else
{
nextViewController.id = materialListObjects[indexPath.row].id
}
nextViewController.course_id = String(describing: materialListObjects[indexPath.row].course_id)
let naviControl = UINavigationController(rootViewController: nextViewController)
naviControl.pushViewController(nextViewController, animated: true)
}
}
}
I have created a similar scenario as yours and this is how you can get it working.
1. View Hierarchy
I have used tag property to uniquely identify both UITableViews, i.e.
Outer tableView tag = 0
Inner tableView tag = 1
2. Now implement UITableViewDataSource, UITableViewDelegate methods for both the tableViews. Set the dataSource and delegate of both the tableViews as the ViewController.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if tableView.tag == 0
{
return 1
}
else if tableView.tag == 1
{
return 5
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if tableView.tag == 0
{
return tableView.dequeueReusableCell(withIdentifier: "outercell", for: indexPath)
}
else if tableView.tag == 1
{
return tableView.dequeueReusableCell(withIdentifier: "innercell", for: indexPath)
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if tableView.tag == 1
{
//TODO: Write your code for navigating to another ViewController here
print("Inner cell tapped")
}
}
Edit:
In the Interface Builder, you can find a tag attribute corresponding to each element in the attributes inspector, i.e.
For outer tableView set it to 0 and for inner tableView set it to 1.
Let me know if you still face any issues. Happy Coding..🙂
Use performSegue(withIdentifier: "ViewController", sender: self); in didSelectrow method of you tableView2.
I'm building a simple messenger app that uses a tableview to display the messages. Each cell contains text and a stretchable background image. When messages are added to the tableview, they do change height to accommodate the text. However, whenever a single-line message is entered, the table view cell appears to be way too long for just a single line of text.
I think it has to do with the initial height and width of the tableviewcell, but I am not sure. How can I fix this to ensure the text bubble image encompasses the text but does not expand too much over it?
Screenshot of single and multi-lined texts:
Screenshot of long single-lined text for comparison:
I am using auto layout, if it helps.
ViewController code:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
var texts: [String] = ["Hey, how are you?", "Good, you?", "Great!"]
var user: [Int] = [1, 0, 1]
let screenSize = UIScreen.main.bounds
#IBOutlet weak var tableView: UITableView!
#IBAction func sendMessage(_ sender: Any) {
if textBox.text != ""
{
let str:String = textBox.text
let retstr:String = insert(seperator: "\n", afterEveryXChars: 27, intoString: str)
let rand:UInt32 = arc4random_uniform(2)
addText(text: String(retstr), user: Int(rand))
}
}
#IBOutlet weak var textBox: UITextView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.texts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (self.user[indexPath.row]==1)
{
let cell:CustomCell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomCell
cell.myCellLabel.text = self.texts[indexPath.row]
cell.myCellLabel.textAlignment = NSTextAlignment.left
cell.myCellLabel.sizeToFit()
cell.myBackgroundImage.image = UIImage(named: "bubbleReversed")?.resizableImage(withCapInsets: UIEdgeInsetsMake(60, 50, 60, 50))
return cell
}
else
{
let cell:CustomCellOther = self.tableView.dequeueReusableCell(withIdentifier: "cell2") as! CustomCellOther
cell.myCellLabel.text = self.texts[indexPath.row]
cell.myCellLabel.textAlignment = NSTextAlignment.right
cell.myCellLabel.sizeToFit()
cell.myBackgroundImage.image = UIImage(named: "bubble")?.resizableImage(withCapInsets: UIEdgeInsetsMake(60, 50, 60, 50))
return cell
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = 10.0
tableView.rowHeight = UITableViewAutomaticDimension
tableView.reloadData()
}
func addText(text:String, user:Int)
{
if (self.texts.count > 20)
{
self.texts.remove(at: 0)
self.user.remove(at: 0)
}
self.texts.append(text)
self.user.append(user)
tableView.reloadData()
let indexPath = NSIndexPath(row: self.texts.count-1, section: 0)
tableView.scrollToRow(at: indexPath as IndexPath, at: .top, animated: true)
}
func insert(seperator: String, afterEveryXChars: Int, intoString: String) -> String {
var output = ""
intoString.characters.enumerated().forEach { index, c in
if index % afterEveryXChars == 0 && index > 0 {
output += seperator
}
output.append(c)
}
return output
}
}
My tableviewcell classes just contain a UIImageView and a label.