Estoy creando una aplicación que permite al usuario seleccionar fechas a partir de un UITableView. El formato tableview es estática y se agrupan. He mirado a través de muchas preguntas, incluyendo este, tratando de averiguar cómo hacer esto – pero nada parece funcionar óptimo. Apple calendario de aplicación cuenta con una muy suave y bonita animación que ninguno de los ejemplos que he sido a través de han conseguido recrear.

Este es mi resultado deseado:

La expansión y contracción de UITableViewCells con DatePicker

Podría alguien que me señale un tutorial o explicar cómo puedo realizar un suave animación con la más concisa y sencilla de hacerlo, como el que vemos en la aplicación de calendario?

Gracias mucho!

Erik

  • es su formato tableview estática o prototipo?
  • es estático y se agrupan en formato tableview
InformationsquelleAutor Erik | 2015-04-16

6 Comentarios

  1. 36

    Supongo que usted está utilizando el storyboard, el ejemplo es con UIPickerView:
    Crear un tableviewcell derecho en virtud de la celda que contiene el campo de texto que desea rellenar y fijar las células de la altura de la fila para 216.0 en el inspector y agregar un UIPickerView a esa celda.

    La expansión y contracción de UITableViewCells con DatePicker

    Conecte el UIPickerView a través de la Toma de corriente para su viewcontroller y añadir la siguiente propiedad a la ViewController.h:

    @property (weak, nonatomic) IBOutlet UIPickerView *statusPicker;
    @property BOOL statusPickerVisible;

    En su ViewController.m ¿en viewWillAppear

    self.statusPickerVisible = NO;
    self.statusPicker.hidden = YES;
    self.statusPicker.translatesAutoresizingMaskIntoConstraints = NO;

    Agregar dos métodos:

    - (void)showStatusPickerCell {
        self.statusPickerVisible = YES;
        [self.tableView beginUpdates];
        [self.tableView endUpdates];
        self.statusPicker.alpha = 0.0f;
        [UIView animateWithDuration:0.25 
                     animations:^{
                         self.statusPicker.alpha = 1.0f;
                     } completion:^(BOOL finished){
                         self.statusPicker.hidden = NO;
                     }];];
    }
    
    - (void)hideStatusPickerCell {    
        self.statusPickerVisible = NO;
        [self.tableView beginUpdates];
        [self.tableView endUpdates];
        [UIView animateWithDuration:0.25
                     animations:^{
                         self.statusPicker.alpha = 0.0f;
                     }
                     completion:^(BOOL finished){
                         self.statusPicker.hidden = YES;
                     }];
    }

    En heightForRowAtIndexPath

    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        CGFloat height = self.tableView.rowHeight;
        if (indexPath.row == 1){
            height = self.statusPickerVisible ? 216.0f : 0.0f;
        }
        return height;
    }

    En didSelectRowAtIndexPath

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        if (indexPath.row == 0) {
            if (self.statusPickerVisible){
                [self hideStatusPickerCell];
            } else {
                [self showStatusPickerCell];
            }
        }
        [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
    }
    • Muy bonita respuesta. Hizo esto ahora, la animación de la célula expansión se ve bien, pero el pickerView es invisible por alguna razón
    • Parece que el valor de alfa se queda en 0, incluso en la realización de bloque de la animación (NSLog). Parece [de la célula.contentView addSubview:auto.statusPicker]; no funciona correctamente
    • La eliminación de la addSubview y removeFromSubview métodos de trabajo
    • bien que funciona 🙂 me ha quitado la addSubview y afines de ejemplo.
    • de niza. Me puse a trabajar con varias secciones y funciona impecable con la misma interacción con el usuario como apple en su app. Las animaciones son muy agradable, mucho más suave que otros ejemplos
    • Estoy un poco confundido en cuanto a qué es exactamente en el guión – como usted no puede poner un UIPicker dentro de una célula (que puede ser mi falta de comprensión). Cómo es exactamente su guión organizado?
    • Estoy recibiendo el siguiente error: The datePicker outlet is invalid. Outlets cannot be connected to repeating content
    • Actualización: he tenido que incrustar el tableVC en un contenedor de vista para establecer la vista de tabla para las células de la estáticas (más de un selector de fecha no puede ser conectado). Por favor, consulte stackoverflow.com/questions/22364230/…
    • He añadido el UIPicker/UIDatePicker directamente en el contenido de la vista de mi UITableViewCell. Creo que voy a necesitar tener un UITableViewController si usted tiene la intención de utilizar las células de la estáticas, pero prototipo de trabajo de las células en tableViews dentro de lo «normal» subclases UIViewControllers
    • Hay un problema aquí: cuando el selector está visible y rápidamente presiona dos veces, se han ampliado vacío selector de celda. Para evitar este problema, debe agregar la terminación en showStatusPickerCell y establecer allí mismo.statusPicker.hidden = NO;
    • Thx, he actualizado como lo sugieren

  2. 30

    Las 2 respuestas anteriores me permitió resolver este problema. Ellos se merecen el crédito, yo estoy añadiendo a esto un recordatorio para mí mismo – formato de resumen.

    Esta es mi versión de las anteriores respuestas.

    1. Como se señaló anteriormente – añadir el selector a la celda en la que desea mostrar /ocultar.

    2. Agregar restricciones para el seleccionador en el interface builder – centro X /centro de S /igual /mismo ancho de la celda en la vista de contenido

    3. Conectar el selector para que usted VC

    @IBOutlet weak var dobDatePicker: UIDatePicker!

    Que bien podría arrastre de control y agregar un método que registra los cambios de fecha

    @IBAction func dateChanged(sender: UIDatePicker) { 
        //updates ur label in the cell above
        dobLabel.text = "\(dobDatePicker.date)"
    }

    4. En viewDidLoad

    dobDatePicker.date = NSDate()
    dobLabel.text = "\(dobDatePicker.date)" //my label in cell above
    dobDatePicker.hidden = true

    5. Ajuste de alturas de celda, en mi ejemplo la celda que quiero es ampliar la sección 0, fila 3… establecer a qué celda a la que desea expandir /ocultar. Si usted tiene muchas células con distintas alturas esto permite que.

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    
        if indexPath.section == 0 && indexPath.row == 3 {
            let height:CGFloat = dobDatePicker.hidden ? 0.0 : 216.0
            return height
        }
    
        return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
    }

    6. La selección de la celda de arriba para ampliar la de abajo, de nuevo esta a la celda que le toque para mostrar la celda de abajo.

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    
    let dobIndexPath = NSIndexPath(forRow: 2, inSection: 0)
    if dobIndexPath == indexPath {
    
        dobDatePicker.hidden = !dobDatePicker.hidden
    
        UIView.animateWithDuration(0.3, animations: { () -> Void in
            self.tableView.beginUpdates()
            //apple bug fix - some TV lines hide after animation
            self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
            self.tableView.endUpdates()
        })
    }
    }

    La expansión y contracción de UITableViewCells con DatePicker

    • Eso fue increíble, pero si queremos hacer la misma celda ampliable entonces, ¿cómo proceder?
    • A mi colapso de la animación no es nada fácil. Mientras que el cierre puedo ver el primer texto «Lun, Feb 1 …» obtiene el primer trunca?
  3. 18

    He implementado @thorb65 la respuesta en Swift, y funciona como un encanto. Incluso si puedo configurar dos selectores de fecha (por ejemplo, «inicio» y «final» como en el calendario), y el conjunto de ellos, de forma que la apertura de uno se contrae automáticamente cuando con expaning el otro (es decir, «uno abierto en un tiempo máximo» de la política, como el Calendario), la (concurrente) animaciones son todavía suave.

    Una cosa que he luchado con, sin embargo, es encontrar el autodiseño de restricciones. El siguiente me dio el mismo comportamiento que el Calendario.aplicación:

    1. Colapso de abajo a arriba (selector de fecha contenido no se mueva)

    Restringe de UIDatePicker hacia sí mismo:

    • Altura

    Restringe de UIDatePicker contra UITableViewCell la vista de contenido:

    • Espacio para Contenedor Margen
    • Espacio al final para Contenedor Margen
    • Superior del Espacio de Contenedores Margen

    Animación resultante

    «Espacio inferior a un Contenedor de Margen» es explícitamente a la izquierda, para hacer cumplir fija de altura a lo largo de la animación (esto recrea Calendario.aplicación del comportamiento, donde la vista de la tabla de la célula «se abre» para revelar los inmutable, de altura fija selector de fecha debajo).

    1. Colapso de abajo a arriba (selector de fecha mueve de manera uniforme)

    Restringe de UIDatePicker hacia sí mismo:

    • Altura

    Restringe de UIDatePicker contra UITableViewCell la vista de contenido:

    • Espacio para Contenedor Margen
    • Espacio al final para Contenedor Margen
    • Centro verticalmente en el contenedor exterior

    Animación resultante

    Cuenta de la diferencia, las limitaciones que hacer en el contraer/expandir animación.

    EDICIÓN: Este es el código swift

    Propiedades:

    //"Start Date" (first date picker)
    @IBOutlet weak var startDateLabel: UILabel!
    @IBOutlet weak var startDatePicker: UIDatePicker!
    var startDatePickerVisible:Bool?
    
    //"End Date" (second date picker)
    @IBOutlet weak var endDateLabel: UILabel!
    @IBOutlet weak var endDatePicker: UIDatePicker!
    var endDatePickerVisible:Bool?
    
    private var startDate:NSDate
    private var endDate:NSDate
    //Backup date labels' initial text color, to restore on collapse 
    //(we change it to control tint while expanded, like calendar.app)  
    private var dateLabelInitialTextColor:UIColor!

    UIViewController métodos:

    override func viewDidLoad()
    {
        super.viewDidLoad()
    
        //Set pickers to their initial values (e.g., "now" and "now + 1hr" )
        startDatePicker.date = startDate
        startDateLabel.text = formatDate(startDate)
    
        endDatePicker.date = endDate
        endDateLabel.text = formatDate(endDate)
    
        //Backup (unselected) date label color    
        dateLabelInitialTextColor = startDateLabel.textColor
    }
    
    override func viewWillAppear(animated: Bool)
    {
        super.viewWillAppear(animated)
    
        startDatePickerVisible = false
        startDatePicker.hidden = true
    
        endDatePickerVisible = false
        endDatePicker.hidden = true
    }

    UITableViewDelegate Métodos:

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
    {
        var height:CGFloat = 44 //Default
    
        if indexPath.row == 3 {
            //START DATE PICKER ROW
            if let startDatePickerVisible = startDatePickerVisible {
                height = startDatePickerVisible ? 216 : 0
            }
        }
        else if indexPath.row == 5 {
            //END DATE PICKER ROW
            if let endDatePickerVisible = endDatePickerVisible {
                height = endDatePickerVisible ? 216 : 0
            }
        }
    
        return height
    }
    
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
    {
        switch indexPath.row {
    
        case 2:
            //[ A ] START DATE
    
            //Collapse the other date picker (if expanded):
            if endDatePickerVisible! {
                hideDatePickerCell(containingDatePicker: endDatePicker)
            }
    
            //Expand:
            if startDatePickerVisible! {
                hideDatePickerCell(containingDatePicker: startDatePicker)
            }
            else{
                showDatePickerCell(containingDatePicker: startDatePicker)
            }
    
        case 4:
            //[ B ] END DATE
    
            //Collapse the other date picker (if expanded):
            if startDatePickerVisible!{
                hideDatePickerCell(containingDatePicker: startDatePicker)
            }
    
            //Expand:
            if endDatePickerVisible! {
                hideDatePickerCell(containingDatePicker: endDatePicker)
            }
            else{
                showDatePickerCell(containingDatePicker: endDatePicker)
            }
    
        default:
            break
        }
    
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }

    Control Selector De Fecha Acciones:

    @IBAction func dateChanged(sender: AnyObject)
    {
        guard let picker = sender as? UIDatePicker else {
            return
        }
    
        let dateString = formatDate(picker.date)
    
        if picker == startDatePicker {
            startDateLabel.text = dateString
        }
        else if picker == endDatePicker {
            endDateLabel.text = dateString
        }
    }

    Auxiliar Métodos: (animación, formato de fecha)

    @IBAction func dateChanged(sender: AnyObject)
    {
        guard let picker = sender as? UIDatePicker else {
            return
        }
    
        let dateString = formatDate(picker.date)
    
        if picker == startDatePicker {
            startDateLabel.text = dateString
        }
        else if picker == endDatePicker {
            endDateLabel.text = dateString
        }
    }
    
    func showDatePickerCell(containingDatePicker picker:UIDatePicker)
    {
        if picker == startDatePicker {
    
            startDatePickerVisible = true
    
            startDateLabel.textColor = myAppControlTintColor
        }
        else if picker == endDatePicker {
    
            endDatePickerVisible = true
    
            endDateLabel.textColor = myAppControlTintColor
        }
    
        tableView.beginUpdates()
        tableView.endUpdates()
    
        picker.hidden = false
        picker.alpha = 0.0
    
        UIView.animateWithDuration(0.25) { () -> Void in
    
            picker.alpha = 1.0
        }
    }
    
    func hideDatePickerCell(containingDatePicker picker:UIDatePicker)
    {
        if picker == startDatePicker {
    
            startDatePickerVisible = false
    
            startDateLabel.textColor = dateLabelInitialTextColor
        }
        else if picker == endDatePicker {
    
            endDatePickerVisible = false
    
            endDateLabel.textColor = dateLabelInitialTextColor
        }
    
        tableView.beginUpdates()
        tableView.endUpdates()
    
        UIView.animateWithDuration(0.25,
            animations: { () -> Void in
    
                picker.alpha = 0.0
            },
            completion:{ (finished) -> Void in
    
                picker.hidden = true
            }
        )
    }
    • se debe añadir el código swift aquí… o que yo pueda añadir a mi respuesta y mentioring usted 🙂
    • Yo, buen punto.
    • Tal vez yo no lo veo, pero parece que la formatDate método es el que falta?! Aparte de eso, esta es una gran respuesta que proporciona una solución bonita! Gracias por compartir
    • Sí, es sólo un muy pequeño método que envuelve una NSDateFormatter y devuelve la cadena con formato.
    • Me lo imaginaba 🙂
    • Esto funciona muy bien. Estoy usando esto en una tabla estática con cinco celdas. Los datos de la celda está en la parte inferior, con la selección de la celda a la derecha por encima de ella. Estoy teniendo un pequeño problema con este funcionamiento cuando el dispositivo está en el modo de paisaje. Cuando me expanda el selector de fecha de la célula, la tabla no se desplaza hacia arriba y el selector de fecha está fuera de la parte inferior de la pantalla. Cómo puedo forzar la vista de tabla para desplazarse hacia arriba cuando el selector de fecha se muestra?
    • UITableView tiene un par de métodos para que se pueda desplazar mediante programación a una posición determinada; leer la documentación.
    • Gracias! Las limitaciones son muy importante cómo se ve la animación cuando el colapso de la célula con el selector de fecha. Con los que las limitaciones de todo, sólo se desplaza hacia arriba cuando se derrumbe. He descubierto que si se establece este conjunto de restricciones en lugar de obtener una más uniforme colapso de animación: – centrar verticalmente selector de fecha en el contenido celular de vista de Conjunto que conduce & trailing restricciones al contenedor margen de Altura de selector de fecha de Esa manera, cuando el colapso de la fecha selector también se mueve hacia arriba (en lugar de sólo la célula se mueve arriba).

  4. 2

    He estado trabajando en esto también, y pensé que podría compartir mi solución, que se deriva de los ya proporcionados aquí.

    Lo que he notado es que hay una gran cantidad de código en el resto de los ejemplos específicos de los elementos individuales, y, entonces, lo que hice fue crear un ‘manager’ de la clase a tratar con él de cualquier elemento.

    Aquí es lo que yo hice:

    La CellShowHideDetail almacena los detalles sobre el elemento que desee mostrar u ocultar. Estos detalles incluyen el celular de la misma, y también la celda que va a ser aprovechado para alternar entre mostrar y ocultar:

    public class CellShowHideDetail
    {
        var item: UIView
        var indexPath_ToggleCell: IndexPath
        var indexPath_ItemCell: IndexPath
        var desiredHeight: CGFloat
    
        init(item: UIView, indexPath_ToggleCell: IndexPath, indexPath_ItemCell: IndexPath, desiredHeight: CGFloat)
        {
            self.item = item
            self.indexPath_ToggleCell = indexPath_ToggleCell
            self.indexPath_ItemCell = indexPath_ItemCell
            self.desiredHeight = desiredHeight
    
            //By default cells are not expanded:
            self.item.isHidden = true
        }
    }

    Nota que UIView es una clase padre de la mayoría (todos?) Elementos de interfaz de usuario.

    A continuación tenemos el gerente, la cual tramitará como muchos de estos artículos como te gusta:

    import Foundation
    import UIKit
    
    public class CellShowHideManager
    {
        var cellItems: [CellShowHideDetail]
    
        init()
        {
            cellItems = []
        }
    
        func addItem(item: CellShowHideDetail)
        {
            cellItems.append(item)
        }
    
        func getRowHeight(indexPath: IndexPath) -> (match: Bool, height: CGFloat)
        {
            for item in cellItems
            {
                if indexPath.section == item.indexPath_ItemCell.section
                    && indexPath.row == item.indexPath_ItemCell.row
                {
                    return (match: true, height: item.item.isHidden ? 0.0 : item.desiredHeight)
                }
            }
    
            return (match: false, height: 0)
        }
    
        func rowSelected(indexPath: IndexPath) -> Bool
        {
            var changesMade = false
    
            for item in cellItems
            {
                if item.indexPath_ToggleCell == indexPath
                {
                    item.item.isHidden = !item.item.isHidden
    
                    changesMade = true
                }
                else
                {
                    if item.item.isHidden == false
                    {
                        changesMade = true
                    }
    
                    item.item.isHidden = true
                }
            }
    
            return changesMade
        }
    }

    Usted puede fácilmente crear un CellShowHideManager en cualquier UITableViewController clase, agregue en los elementos que desea alternar capaz de:

    var showHideManager = CellShowHideManager()
    
    override func viewDidLoad()
        {
            super.viewDidLoad()
    
            let item1ToShowHide = CellShowHideDetail(item: datePicker, indexPath_ToggleCell: IndexPath(row: 0, section: 0), indexPath_ItemCell: IndexPath(row: 1, section: 0), desiredHeight: 232.0)
    
            let item2ToShowHide = CellShowHideDetail(item: selection_Picker, indexPath_ToggleCell: IndexPath(row: 0, section: 1), indexPath_ItemCell: IndexPath(row: 1, section: 1), desiredHeight: 90.0)
    
            //Add items for the expanding cells:
            showHideManager.addItem(item: item1ToShowHide)
            showHideManager.addItem(item: item2ToShowHide)
        }

    Finalmente acaba de anular estas dos TableView métodos de la siguiente manera:

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
        {
            let showHideResult = showHideManager.getRowHeight(indexPath: indexPath)
    
            if showHideResult.match
            {
                return showHideResult.height
            }
            else
            {
                return super.tableView(tableView, heightForRowAt: indexPath)
            }
        }
    
        override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
        {
    
            if showHideManager.rowSelected(indexPath: indexPath)
            {
                UIView.animate(withDuration: 0.3, animations: { () -> Void in
                    self.tableView.beginUpdates()
    
                    //apple bug fix - some TV lines hide after animation
                    //self.tableView.deselectRowAt(indexPath, animated: true)
                    self.tableView.endUpdates()
                })
            }
        }

    Y se debe trabajar muy bien!

  5. 1

    Estoy compartiendo mi respuesta:

    Que lo estoy haciendo todo sin guión

    Swift 3

    1.1 añadir el selector de fecha

    var travelDatePicker: UIDatePicker = {
                let datePicker = UIDatePicker()
                datePicker.timeZone = NSTimeZone.local
                datePicker.backgroundColor = UIColor.white
                datePicker.layer.cornerRadius = 5.0
                datePicker.datePickerMode = .date
                datePicker.addTarget(self, action: #selector(TableViewController.datePickerValueChanged(_:)), for: .valueChanged)
                return datePicker
            }()

    1.2 y su método de

    func datePickerValueChanged(_ sender: UIDatePicker){
    
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd"
            let dateString = dateFormatter.string(from: travelDatePicker.date)
            self.shareCell.textLabel?.text = "\(dateString)"
    
            print("changed")
            print("Selected value \(dateString)")
        }

    2. a continuación, en la loadView mostrar la fecha en la celda de arriba con formato

            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd"
            let dateString = dateFormatter.string(from: travelDatePicker.date)
            self.shareCell.textLabel?.text = "\(dateString)"
            travelDatePicker.isHidden = true

    3. agregar selector de fecha para la célula

    self.datePickerCell.backgroundColor = UIColor.red
            self.datePickerCell.addSubview(self.travelDatePicker)
            self.travelDatePicker.frame = CGRect(x: 0, y: 0, width: 500, height: 216)
            self.datePickerCell.accessoryType = UITableViewCellAccessoryType.none

    4. ajuste la altura de la celda

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                if indexPath.section == 1 && indexPath.row == 1{
                    let height: CGFloat = travelDatePicker.isHidden ? 0.0 : 216.0
                    return height
                }
                return 44.0
            }
    1. y, finalmente, establecer la instrucción if en el didSelectAt

    si(indexPath.sección == 1 && indexPath.vta == 0) {

        travelDatePicker.isHidden = !travelDatePicker.isHidden
    
        UIView.animate(withDuration: 0.3, animations: { () -> Void in
            self.tableView.beginUpdates()
            //apple bug fix - some TV lines hide after animation
            self.tableView.deselectRow(at: indexPath, animated: true)
            self.tableView.endUpdates()
        })
    }

    Código completo está aquí con otros elementos que acaban de obtener una sensación de trabajo de la aplicación

    import Foundation
    import UIKit
    class TableViewController: UITableViewController {
    var firstNameCell: UITableViewCell = UITableViewCell()
    var lastNameCell: UITableViewCell = UITableViewCell()
    var shareCell: UITableViewCell = UITableViewCell()
    var datePickerCell: UITableViewCell = UITableViewCell()
    var cityToCell: UITableViewCell = UITableViewCell()
    var cityFromCell: UITableViewCell = UITableViewCell()
    var firstNameText: UITextField = UITextField()
    var lastNameText: UITextField = UITextField()
    var travelDatePicker: UIDatePicker = {
    let datePicker = UIDatePicker()
    datePicker.timeZone = NSTimeZone.local
    datePicker.backgroundColor = UIColor.white
    datePicker.layer.cornerRadius = 5.0
    datePicker.datePickerMode = .date
    datePicker.addTarget(self, action: #selector(TableViewController.datePickerValueChanged(_:)), for: .valueChanged)
    return datePicker
    }()
    override func loadView() {
    super.loadView()
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    let dateString = dateFormatter.string(from: travelDatePicker.date)
    self.shareCell.textLabel?.text = "\(dateString)"
    travelDatePicker.isHidden = true
    //set the title
    self.title = "User Options"
    //construct first name cell, section 0, row 0
    self.firstNameCell.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5)
    self.firstNameText = UITextField(frame: self.firstNameCell.contentView.bounds.insetBy(dx: 15, dy: 0))
    self.firstNameText.placeholder = "First Name"
    self.firstNameCell.addSubview(self.firstNameText)
    //construct last name cell, section 0, row 1
    self.lastNameCell.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5)
    self.lastNameText = UITextField(frame: self.lastNameCell.contentView.bounds.insetBy(dx: 15, dy: 0))
    self.lastNameText.placeholder = "Last Name"
    self.lastNameCell.addSubview(self.lastNameText)
    //construct share cell, section 1, row 0
    self.shareCell.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5)
    self.shareCell.accessoryType = UITableViewCellAccessoryType.checkmark
    self.datePickerCell.backgroundColor = UIColor.red
    self.datePickerCell.addSubview(self.travelDatePicker)
    self.travelDatePicker.frame = CGRect(x: 0, y: 0, width: 500, height: 216)
    self.datePickerCell.accessoryType = UITableViewCellAccessoryType.none
    self.cityToCell.textLabel?.text = "Kiev"
    self.cityToCell.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5)
    self.cityToCell.accessoryType = UITableViewCellAccessoryType.none
    self.cityFromCell.textLabel?.text = "San Francisco"
    self.cityFromCell.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5)
    self.cityFromCell.accessoryType = UITableViewCellAccessoryType.none
    }
    func datePickerValueChanged(_ sender: UIDatePicker){
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    let dateString = dateFormatter.string(from: travelDatePicker.date)
    self.shareCell.textLabel?.text = "\(dateString)"
    print("changed")
    print("Selected value \(dateString)")
    }
    //Return the number of sections
    override func numberOfSections(in tableView: UITableView) -> Int {
    return 2
    }
    //Return the number of rows for each section in your static table
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    switch(section) {
    case 0: return 2    //section 0 has 2 rows
    case 1: return 4    //section 1 has 1 row
    default: fatalError("Unknown number of sections")
    }
    }
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.section == 1 && indexPath.row == 1{
    let height: CGFloat = travelDatePicker.isHidden ? 0.0 : 216.0
    return height
    }
    return 44.0
    }
    //Return the row for the corresponding section and row
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch(indexPath.section) {
    case 0:
    switch(indexPath.row) {
    case 0: return self.firstNameCell   //section 0, row 0 is the first name
    case 1: return self.lastNameCell    //section 0, row 1 is the last name
    default: fatalError("Unknown row in section 0")
    }
    case 1:
    switch(indexPath.row) {
    case 0: return self.shareCell       //section 1, row 0 is the share option
    case 1: return self.datePickerCell
    case 2: return self.cityToCell
    case 3: return self.cityFromCell
    default: fatalError("Unknown row in section 1")
    }
    default: fatalError("Unknown section")
    }
    }
    //Customize the section headings for each section
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch(section) {
    case 0: return "Profile"
    case 1: return "Social"
    default: fatalError("Unknown section")
    }
    }
    //Configure the row selection code for any cells that you want to customize the row selection
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //Handle social cell selection to toggle checkmark
    if(indexPath.section == 1 && indexPath.row == 0) {
    //deselect row
    tableView.deselectRow(at: indexPath as IndexPath, animated: false)
    //toggle check mark
    if(self.shareCell.accessoryType == UITableViewCellAccessoryType.none) {
    self.shareCell.accessoryType = UITableViewCellAccessoryType.checkmark;
    } else {
    self.shareCell.accessoryType = UITableViewCellAccessoryType.none;
    }
    }
    if(indexPath.section == 1 && indexPath.row == 0) {
    travelDatePicker.isHidden = !travelDatePicker.isHidden
    UIView.animate(withDuration: 0.3, animations: { () -> Void in
    self.tableView.beginUpdates()
    //apple bug fix - some TV lines hide after animation
    self.tableView.deselectRow(at: indexPath, animated: true)
    self.tableView.endUpdates()
    })
    }
    }
    }
  6. 0

    Pensaba que iba a añadir mi granito de arena también. De hecho, estoy de programación en Xamarin y tuvo que hacer algunos pequeños ajustes para conseguir que funcione en el marco de Xamarin.

    Todos los principios son los mismos, pero como Xamarin utiliza una clase separada para el TableViewSource y, como tal, la gestión de los delegados es diferente. Por supuesto, usted siempre puede asignar UITableViewDelegates si usted desea, así como en el UIViewController, pero tenía curiosidad si yo pudiera llegar a trabajar de esta manera:

    Para iniciar con I subclases tanto el Selector de Fecha de la Célula (datePickerCell) y el selector de celdas (selectorCell). Nota de lado, yo estoy haciendo esta 100% mediante programación sin un Guión

    datePickerCell:

    using System;
    using UIKit;
    namespace DatePickerInTableViewCell 
    {
    public class CustomDatePickerCell : UITableViewCell
    {
    //========================================================================================================================================
    // PRIVATE CLASS PROPERTIES
    //========================================================================================================================================
    private UIDatePicker datePicker;
    private bool datePickerVisible;
    private Boolean didUpdateConstraints;
    //========================================================================================================================================
    // PUBLIC CLASS PROPERTIES
    //========================================================================================================================================
    public event EventHandler dateChanged;
    //========================================================================================================================================
    // Constructor
    //========================================================================================================================================
    ///<summary>
    ///Initializes a new instance of the <see cref="DatePickerInTableViewCell.CustomDatePickerCell"/> class.
    ///</summary>
    public CustomDatePickerCell (string rid) : base(UITableViewCellStyle.Default, rid)
    {
    Initialize ();
    }
    //========================================================================================================================================
    // PUBLIC OVERRIDES
    //========================================================================================================================================
    ///<summary>
    ///Layout the subviews.
    ///</summary>
    public override void LayoutSubviews ()
    {
    base.LayoutSubviews ();
    ContentView.AddSubview (datePicker);
    datePicker.Hidden   = true;
    AutoresizingMask    = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth;
    foreach (UIView view in ContentView.Subviews) {
    view.TranslatesAutoresizingMaskIntoConstraints = false;
    }
    ContentView.SetNeedsUpdateConstraints ();
    }
    ///<summary>
    ///We override the UpdateConstraints to allow us to only set up our constraint rules one time.  Since 
    ///we need to use this method to properly call our constraint rules at the right time we use a boolean
    ///as a flag so that we only fix our auto layout once.  Afterwards UpdateConstraints runs as normal. 
    ///</summary>
    public override void UpdateConstraints ()
    {
    if (NeedsUpdateConstraints () && !didUpdateConstraints) {
    setConstraints ();
    didUpdateConstraints = true;
    }
    base.UpdateConstraints ();
    }
    //========================================================================================================================================
    // PUBLIC METHODS
    //========================================================================================================================================
    ///<summary>
    ///Allows us to determine the visibility state of the cell from the tableViewSource.
    ///</summary>
    ///<returns><c>true</c> if this instance is visible; otherwise, <c>false</c>.</returns>
    public bool IsVisible()
    {
    return datePickerVisible;
    }
    ///<summary>
    ///Allows us to show the datePickerCell from the tableViewSource.
    ///</summary>
    ///<param name="tableView">Table view.</param>
    public void showDatePicker(ref UITableView tableView)
    {
    datePickerVisible   = true;
    tableView.BeginUpdates  ();
    tableView.EndUpdates    ();
    datePicker.Hidden   = false;
    datePicker.Alpha    = 0f;
    UIView.Animate(
    0.25, 
    ()=> { datePicker.Alpha = 1f;}
    );
    }
    public void hideDatePicker(ref UITableView tableView)
    {
    datePickerVisible   = false;
    tableView.BeginUpdates  ();
    tableView.EndUpdates    ();
    UIView.Animate(
    0.25, 
    ()=> { datePicker.Alpha = 0f;}, 
    ()=> {datePicker.Hidden = true;}
    );
    }
    //========================================================================================================================================
    // PRIVATE METHODS
    //========================================================================================================================================
    ///<summary>
    ///We make sure the UIDatePicker is center in the cell.
    ///</summary>
    private void setConstraints()
    {
    datePicker.CenterXAnchor.ConstraintEqualTo(ContentView.CenterXAnchor).Active = true;
    }
    ///<summary>
    ///Init class properties.
    ///</summary>
    private void Initialize()
    {
    datePicker              = new UIDatePicker ();
    datePickerVisible       = false;
    datePicker.TimeZone     = Foundation.NSTimeZone.LocalTimeZone;
    datePicker.Calendar     = Foundation.NSCalendar.CurrentCalendar;
    datePicker.ValueChanged += (object sender, EventArgs e) => {
    if(dateChanged != null) {
    dateChanged (datePicker, EventArgs.Empty);
    }
    };
    }
    }
    }   

    Selector De Celda

    using System;
    using UIKit;
    namespace DatePickerInTableViewCell 
    {
    ///<summary>
    ///
    ///</summary>
    public class CustomDatePickerSelectionCell : UITableViewCell
    {
    //========================================================================================================================================
    // PRIVATE CLASS PROPERTIES
    //========================================================================================================================================
    private UILabel prefixLabel;
    private UILabel dateLabel;
    private UILabel timeLabel;
    private Boolean didUpdateConstraints;
    private UIColor originalLableColor;
    private UIColor editModeLabelColor;
    //========================================================================================================================================
    // PUBLIC CLASS PROPERTIES
    //========================================================================================================================================
    //========================================================================================================================================
    // Constructor
    //========================================================================================================================================
    ///<summary>
    ///Initializes a new instance of the <see cref="DatePickerInTableViewCell.CustomDatePickerSelectionCell"/> class.
    ///</summary>
    public CustomDatePickerSelectionCell (string rid) : base(UITableViewCellStyle.Default, rid)
    {
    Initialize ();
    }
    //========================================================================================================================================
    // PUBLIC OVERRIDES
    //========================================================================================================================================
    ///<summary>
    ///We override the UpdateConstraints to allow us to only set up our constraint rules one time.  Since 
    ///we need to use this method to properly call our constraint rules at the right time we use a boolean
    ///as a flag so that we only fix our auto layout once.  Afterwards UpdateConstraints runs as normal. 
    ///</summary>
    public override void UpdateConstraints ()
    {
    if (NeedsUpdateConstraints () && !didUpdateConstraints) {
    setConstraints ();
    didUpdateConstraints = true;
    }
    base.UpdateConstraints ();
    }
    public override void LayoutSubviews ()
    {
    base.LayoutSubviews ();
    AutoresizingMask    = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth;
    timeLabel.TextAlignment = UITextAlignment.Right;
    prefixLabel.Text    = "On: ";
    dateLabel.Text      = DateTime.Now.ToString ("MMM d, yyyy");
    timeLabel.Text      = DateTime.Now.ToShortTimeString ();
    ContentView.AddSubviews (new UIView[]{ prefixLabel, dateLabel, timeLabel });
    foreach (UIView view in ContentView.Subviews) {
    view.TranslatesAutoresizingMaskIntoConstraints = false;
    }
    ContentView.SetNeedsUpdateConstraints ();
    }
    //========================================================================================================================================
    // PUBLIC METHODS
    //========================================================================================================================================
    public void willUpdateDateTimeLables(string date, string time)
    {
    dateLabel.Text = date;
    timeLabel.Text = time;
    }
    public void willEditDateTime()
    {
    dateLabel.TextColor = editModeLabelColor;
    timeLabel.TextColor = editModeLabelColor;
    }
    public void didEditDateTime()
    {
    dateLabel.TextColor = originalLableColor;
    timeLabel.TextColor = originalLableColor;
    }
    //========================================================================================================================================
    // PRIVATE METHODS
    //========================================================================================================================================
    private void Initialize()
    {
    prefixLabel         = new UILabel ();
    dateLabel       = new UILabel ();
    timeLabel       = new UILabel ();
    originalLableColor  = dateLabel.TextColor;
    editModeLabelColor  = UIColor.Red;
    }
    private void setConstraints()
    {
    var cellMargins = ContentView.LayoutMarginsGuide;
    prefixLabel.LeadingAnchor.ConstraintEqualTo (cellMargins.LeadingAnchor).Active      = true;
    dateLabel.LeadingAnchor.ConstraintEqualTo (prefixLabel.TrailingAnchor).Active       = true;
    timeLabel.LeadingAnchor.ConstraintEqualTo (dateLabel.TrailingAnchor).Active         = true;
    timeLabel.TrailingAnchor.ConstraintEqualTo (cellMargins.TrailingAnchor).Active      = true;
    dateLabel.WidthAnchor.ConstraintEqualTo (ContentView.WidthAnchor, 2f / 7f).Active   = true;
    prefixLabel.HeightAnchor.ConstraintEqualTo (ContentView.HeightAnchor, 1).Active     = true;
    timeLabel.HeightAnchor.ConstraintEqualTo (ContentView.HeightAnchor, 1).Active       = true;
    dateLabel.HeightAnchor.ConstraintEqualTo (ContentView.HeightAnchor, 1).Active       = true;
    }
    }
    }

    Así que como puedes ver tengo algunos métodos expuestos de cada celda para facilitar la comunicación necesaria. Yo a continuación, es necesario crear una instancia de estas células en mi tableViewSource. Tal vez hay un menor acoplamiento manera de hacer esto, pero yo no podía fácilmente averiguar eso. Creo que yo soy mucho menos experiencia en programación en iOS que mis predecesores arriba :). Dicho esto, con las células disponibles en el ámbito de la clase, se hace muy fácil llamar y tener acceso a las células en el RowSelected y GetHeightForRow métodos.

    TableViewSource

    using System;
    using UIKit;
    using System.Collections.Generic;
    namespace DatePickerInTableViewCell 
    {
    public class TableViewSource : UITableViewSource
    {
    //========================================================================================================================================
    // PRIVATE CLASS PROPERTIES
    //========================================================================================================================================
    private const string datePickerIdentifier           = "datePickerCell";
    private const string datePickerActivateIdentifier   = "datePickerSelectorCell";
    private const int datePickerRow                     = 1;
    private const int datePickerSelectorRow             = 0;
    private List<UITableViewCell> datePickerCells;
    private CustomDatePickerCell datePickerCell;
    private CustomDatePickerSelectionCell datePickerSelectorCell;
    //========================================================================================================================================
    // PUBLIC CLASS PROPERTIES
    //========================================================================================================================================
    //========================================================================================================================================
    // Constructor
    //========================================================================================================================================
    ///<summary>
    ///Initializes a new instance of the <see cref="DatePickerInTableViewCell.TableViewSource"/> class.
    ///</summary>
    public TableViewSource ()
    {
    initDemoDatePickerCells ();
    }
    //========================================================================================================================================
    // PUBLIC OVERRIDES
    //========================================================================================================================================
    public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
    {
    UITableViewCell cell = null;
    if (indexPath.Row == datePickerSelectorRow) {
    cell = tableView.DequeueReusableCell (datePickerActivateIdentifier);
    cell = cell ?? datePickerCells[indexPath.Row];
    return cell;
    }
    if (indexPath.Row == datePickerRow) {
    cell = tableView.DequeueReusableCell (datePickerIdentifier) as CustomDatePickerCell;
    cell = cell ?? datePickerCells[indexPath.Row];
    return cell;
    }
    return cell;
    }
    public override nint RowsInSection (UITableView tableview, nint section)
    {
    return datePickerCells.Count;
    }
    public override nfloat GetHeightForRow (UITableView tableView, Foundation.NSIndexPath indexPath)
    {
    float height = (float) tableView.RowHeight;
    if (indexPath.Row == datePickerRow) {
    height = datePickerCell.IsVisible () ? DefaultiOSDimensions.heightForDatePicker : 0f;
    }
    return height;
    }
    public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
    {
    if (indexPath.Row == datePickerSelectorRow) {
    if (datePickerCell != null) {
    if (datePickerCell.IsVisible ()) {
    datePickerCell.hideDatePicker (ref tableView);
    datePickerSelectorCell.didEditDateTime ();
    } else {
    datePickerCell.showDatePicker (ref tableView);
    datePickerSelectorCell.willEditDateTime ();
    }
    }
    }
    tableView.DeselectRow (indexPath, true);
    }
    //========================================================================================================================================
    // PUBLIC METHODS
    //========================================================================================================================================
    //========================================================================================================================================
    // PRIVATE METHODS
    //========================================================================================================================================
    private void willUpdateDateChanged(Object sender, EventArgs args)
    {
    var picker      = sender as UIDatePicker;
    var dateTime    = picker.Date.ToDateTime ();
    if (picker != null && dateTime != null) {
    var date = dateTime.ToString ("MMM d, yyyy");
    var time = dateTime.ToShortTimeString ();
    datePickerSelectorCell.willUpdateDateTimeLables (date, time);
    }
    }
    private void initDemoDatePickerCells()
    {
    datePickerCell              = new CustomDatePickerCell (datePickerIdentifier);
    datePickerSelectorCell      = new CustomDatePickerSelectionCell (datePickerActivateIdentifier);
    datePickerCell.dateChanged  += willUpdateDateChanged;
    datePickerCells             = new List<UITableViewCell> () {
    datePickerSelectorCell,
    datePickerCell
    };
    }
    }
    }

    La esperanza de que el código es bastante auto explicativo. El método toDateTime por cierto, es sólo un método de extensión para convertir NSDateTime a una .net objeto DateTime. La referencia puede ser encontrado aquí: https://forums.xamarin.com/discussion/27184/convert-nsdate-to-datetime y DefaultiOSDimensions es sólo una pequeña clase estática que puedo utilizar para realizar un seguimiento de las dimensiones típicas tales como cellHeight (44pts) o en el caso de heightForDatePicker; 216. Se parece a un gran trabajo para mí en mi simulador. Todavía tengo que probar en la que los dispositivos reales. Espero que ayude a alguien!

Dejar respuesta

Please enter your comment!
Please enter your name here