iOS 7 - Bir tablo görünümünde yerinde bir tarih seçiciyi nasıl görüntüleyebilirim?


121

WWDC 2013 videosunda Apple, seçicinin iOS 7'de bir tablo görünümünde yerinde görüntülenmesini önermektedir. Tablo görünümü hücreleri arasında bir görünüm nasıl eklenir ve canlandırılır?

Bunun gibi, Apple takvim uygulamasından:

Yerinde tarih seçici


Bu hangi WWDC videosu? Bunun neden iOS7'ye özgü olduğunu ve bunun önceki sürümlerde yapılamaması için bir neden varsa anlamaya çalışıyorum.
Clafou

4
Buldum, "iOS Kullanıcı Arayüzü Tasarımındaki Yenilikler" (teşekkürler ASCIIwwdc). Mantık, eski stilin doğru şekilde hizalı görünmemesi, ancak yeni düz görünümün öyle olmasıdır.
Clafou

Yanıtlar:


102

Apple, iOS7 ile örnek kodu yayınladı DateCell.

görüntü açıklamasını buraya girin

Tablo hücrelerinde tarih nesnelerinin biçimlendirilmiş görüntüsünü ve bu değerleri düzenlemek için UIDatePicker kullanımını gösterir. Bu tablonun temsilcisi olarak örnek, UIDatePicker denetimini açmak için "didSelectRowAtIndexPath" yöntemini kullanır.

İOS 6.x ve önceki sürümler için UIViewAnimation, UIDatePicker'ı ekranda yukarı ve ekran dışına kaydırmak için kullanılır. İOS 7.x için UIDatePicker, tablo görünümüne satır içi olarak eklenir.

UIDatePicker'ın eylem yöntemi, özel tablo hücresinin NSDate özelliğini doğrudan ayarlayacaktır. Ek olarak, bu örnek, özel hücrenin tarih biçimli görünümünü elde etmek için NSDateFormatter sınıfının nasıl kullanılacağını gösterir.

görüntü açıklamasını buraya girin

Örnek kodu buradan indirebilirsiniz: DateCell .


Apple'ın kodunda sorunlar var. Statik
tablonuzu

1
@AaronBratcher Cevabımda sadece Datecell'i tanıtıyorum ve asla tam olarak istediğiniz kodu almanızı beklemiyorsunuz. Gereksiniminize göre değiştirmeniz ve değiştirmeniz gerekir. Çözümünüz de iyidir, ancak diğer kodlardan ihtiyacınız olanı asla tam olarak alamayacağınızı unutmayın.
Nitin Gohel

3
en korkunç örnek kod. Onlar Komple Code'dan bir yöntem yaratmak için zaman bazı tavsiyeler yapabileceğini
Anirudha Agashe

2
Vay canına, Apple kodu .... peki, odağın tablo görünümü etkisinde olduğunu varsayalım. Umarım bu örnek projede hiç kimse kodundan ilham
Daniel

84

Aşağıda daha önce verdiğim cevabı kullanabilir veya bu görevi çok daha basit ve daha temiz hale getirmek için yaptığım bu yeni sınıfı Swift'de kullanabilirsiniz : https://github.com/AaronBratcher/TableViewHelper


Apple tarafından sağlanan kodu birkaç yönden sorunlu buluyorum:

  • TableView: cellForRowAtIndexPath yöntemini kullandıkları için statik bir tableView olamazsınız
  • Son tarih seçici hücresinin altında ek satırınız yoksa kod çöküyor

Statik hücre tabloları için, tarih seçici hücremi tarih görüntüleme hücresinin altında tanımlıyorum ve düzenleyip düzenlemediğimi belirten bir bayrağım var. Eğer öyleysem, uygun hücre yüksekliğini döndürürüm, aksi takdirde hücre yüksekliğini sıfır olarak döndürürüm.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row == 2) { // this is my picker cell
        if (editingStartTime) {
            return 219;
        } else {
            return 0;
        }
    } else {
        return self.tableView.rowHeight;
    }
}

Tarihi gösteren satır tıklandığında, bayrağı değiştiriyorum ve seçiciyi göstermek için güncelleme animasyonunu yapıyorum.

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row == 1) { // this is my date cell above the picker cell
        editingStartTime = !editingStartTime;
        [UIView animateWithDuration:.4 animations:^{
            [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:2 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView reloadData];
        }];
    }
}

Aynı tabloda birden fazla tarih / saat seçicim varsa, bayrakları tıklama üzerine uygun şekilde ayarlıyorum ve uygun satırları yeniden yüklüyorum. Statik tablomu tutabileceğimi, çok daha az kod kullanabileceğimi ve neler olduğunu anlamanın daha kolay olduğunu öğrendim.


Bu benim için çalıştı, ancak UITableView'da bir hata var gibi görünüyor. Yöntemimde satır yüksekliği doğru bir şekilde döndürülüyordu, ancak aslında istediğim zıt yüksekliği değiştirdi. Satırları iki kez yeniden yüklersem işe yaradı. (TableView reloadData'yı kullanmadım çünkü her şeyi yeniden yüklemek istemedim). Ayrıca animasyon bloğu gerekli değildi, kendi başına iyi canlandırıyor gibi görünüyor.
Chris Garrett

Metin seçici oluşturmak için örneği kullanan oldu mu? Öyleyse nasıl? Teşekkürler
TheGeezer

1
Kullanıcının bir tarih seçmek yerine metin girebilmesi için bir satırı ortaya çıkarmak mı istiyorsunuz? Eğer öyleyse, kod aynıdır. Sadece ortaya çıkan satırın içeriği farklıdır.
Aaron Bratcher

22
İOS7.1'de hücre sınırları dışındaki nesneleri gösteren bir hata var - yüksekliği 0 ve içinde seçici olan gibi. Çözüm, hücre için bir çıkış elde etmek ve hücreyi ayarlamaktır. ClipsToBounds = YES;
EmilDo

1
@Dunken - Yukarıdaki oylanan yorumda bir çözüm açıklanmıştır: stackoverflow.com/questions/18973573/… Satır sıfır yüksekliğe sahip olsa da, içerikler varsayılan olarak kırpılmaz, böylece bunları altta görebilirsiniz. takip eden satır.
Chris Nolet

18

Film şeridini ve statik bir tabloyu kullanarak aşağıdaki kodu kullanarak aynı sonucu elde etmeyi başardım. Bu harika bir çözüm çünkü çok sayıda garip şekilli hücreniz varsa veya dinamik olarak gösterilen / gizlenen birden çok hücreye sahip olmak istiyorsanız bu kod yine de çalışacaktır.

@interface StaticTableViewController: UITableViewController

@property (weak, nonatomic) IBOutlet UITableViewCell *dateTitleCell; // cell that will open the date picker. This is linked from the story board
@property (nonatomic, assign, getter = isDateOpen) BOOL dateOpen;

@end


@implementation StaticTableViewController

-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    // This is the index path of the date picker cell in the static table
    if (indexPath.section == 1 && indexPath.row == 1 && !self.isDateOpen){
        return 0;
    }
    return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
    [tableView beginUpdates];
    if (cell == self.dateTitleCell){
        self.dateOpen = !self.isDateOpen;
    }
    [tableView reloadData];
    [self.tableView endUpdates];
}

burada eksik olan başka bir şey var mı? Hücrelerin yüksekliği değişmiyor :)
DevC

2
İOS 7.1'den beri, Öznitelikler denetçisinde "Alt Görünümlere Kırp" seçeneğini de seçmelisiniz - eksik olan
buydu

Ayrıca, "self.dateOpen =! Self.isDateOpen;" satırı başlangıçta "self.isDateOpen =" yazmalı, "self.dateOpen =" değil
Peter Johnson

2
[tableView reloadData];Çağrı gerekli değildir. Şu anda satır seçimini devre dışı bırakıyor, ancak şu şekilde satırın seçimini kaldırmak daha iyi:[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
Barry Haanstra

Tarih hücresinin "açılıştan" sonra boş kalması gibi garip animasyon efektlerim vardı, ancak başlangıç ​​ve bitiş güncellemeleri kullanmak bunu çözdü. Şimdi güzel ve pürüzsüz. Teşekkürler datinc!
nh32rg

5

DateCell kaynağını Apple'dan aldım ve film şeridi dosyasını kaldırdım.

Film şeridi olmayan bir tane istiyorsanız, şu adrese bir göz atın: https://github.com/ajaygautam/DateCellWithoutStoryboard


@Ajay Teşekkürler, ben senin değiştirilmiş kodu kullandım ve değiştirmek istiyor UIDatePickerile UIPickerView. Birkaç şey denedim ve pickerViewher hücrede gösterebildim ancak her hücrede güncellenmiyor. Soru ve kodumu buraya gönderdim . Lütfen bir göz atın ve bana bir çözüm önerebilirseniz çok nazikçe davranırsınız.
Mughees Musaddiq

Sorunuzu gördüm ... çok fazla bilgi içeriyor ve pek bir şey açıklamıyor. Belki de bakmam için kodunuzu yükleyebilir / bir yere sıkıştırabilirsiniz. Hata ayıklayabilirim - kodu çalıştırabilirsem ...
Ajay Gautam

Teşekkürler, ben bir şekilde yerine başardı UIDatePickerile UIPickerViewancak hataların çift ile. 1. UIPickerViewTabloyu açıp kaydırdığınızda çöküyor . 2. UILabelDeğerler, üst satırlardaki Ayrıntılar etiketine atanırken, tablonun alt satırlarındaki Ayrıntıya otomatik olarak değer atar . İşte kodum
Mughees Musaddiq

Test Projesini bulabiliyor musunuz, Herhangi bir şans?
Mughees Musaddiq

Üzgünüm, biraz meşgulüm. Hala bu konuda yardıma mı ihtiyacınız var?
Ajay Gautam

5

Bununla ilgili en iyi öğreticilerden biri iOS 7 satır içi UIDatePicker - Bölüm 2'dir . Temel olarak burada statik tablo görünümü hücreleri kullanıyorum ve bazı ek yöntemler uyguluyorum. Bunun için Xamarin ve C # kullandım:

Aktif olmalısın Clip Subviews.

Yüksekliğin ayarlanması:

public override float GetHeightForRow (UITableView tableView, NSIndexPath indexPath)
{
    if (indexPath.Row == 4) {
        return (datePickerIsShowing) ? 206f : 0.0f;
    }

    return base.GetHeightForRow(tableView,indexPath);
}

Bir sınıf değişkeninden çok: private bool datePickerIsShowing = false;

Tarih seçiciyi göster:

private void showDatePickerCell(){
    datePickerIsShowing = true;
    this.TableView.BeginUpdates ();
    this.TableView.EndUpdates ();
    this.datePicker.Hidden = false;
    this.datePicker.Alpha = 0.0f;

    UIView.Animate (0.25, animation:
        () => {
            this.datePicker.Alpha = 1.0f;
        }
    );
} 

Tarih seçiciyi gizle:

private void hideDatePickerCell(){
    datePickerIsShowing = false;
    this.TableView.BeginUpdates ();
    this.TableView.EndUpdates ();

    UIView.Animate (0.25,
        animation: () => {
            this.datePicker.Alpha = 0.0f;
        },
        completion: () => {
            this.datePicker.Hidden = true;
        }
    );
} 

Ve bu işlevleri çağırmak:

public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
    if (indexPath.Row == 3) {
        if (datePickerIsShowing) {
            hideDatePickerCell ();
        } else {
            showDatePickerCell ();
        }
    }

    this.TableView.DeselectRow (indexPath, true);
}

2
Olumsuz oy verirseniz, belki neden olumsuz oy verdiğinizi açıklayabilirsiniz. Sitelere bağlantı göndermek yerine bazı kodlar da ekledim. Benim durumumda bu C #. Bunda neyin yanlış olduğunu bilmiyorum.
test

3

Bir tablo görünümüne satır içi seçici ekleme sürecini basitleştirmek için kendi özel görünüm denetleyicimi yaptım. Sadece alt sınıfa ayırın ve bazı basit kuralları takip edin ve tarih seçici sunumunu gerçekleştirir.

Nasıl kullanılacağını gösteren örnek bir projeyle birlikte burada bulabilirsiniz: https://github.com/ale84/ALEInlineDatePickerViewController


3

Apple'ın veri hücresi örneğinde, son veri hücresinin altında bir satıra sahip olmanız gereken veya bir hata aldığınız bir kusurun yanıtını buldum. CellForRowAtIndexPath yönteminde ItemData satırını değiştir

NSArray *itemsArray = [self.dataArray objectAtIndex:indexPath.section];
NSDictionary *itemData = nil;

if(![indexPath isEqual:self.datePickerIndexPath])
    itemData = [itemsArray objectAtIndex:modelRow];

Örnek kodu değiştirdikten sonra, altında bir hücre olmadan bir datePicker hücresi görüntüleyebiliyorum.

Stackoverflow'a yeni katıldım, eğer bu yanlış yerdeyse veya başka bir yerdeyse özür dilerim.


3

Aaron Bratcher'ın cevabı, birden çok bölümle kullanılması dışında işe yaradı. Animasyonlar biraz dalgalıydı ve sonraki bölümleri çok iyi kaydırmadı. Bunu düzeltmek için, sonraki bölümler kümesini yineledim ve satırları tarih seçicinin yüksekliği ile aynı miktarda aşağıya çevirdim.

DidSelectRowAtIndexPath'i şu şekilde düzenledim:

// Return Data to delegate: either way is fine, although passing back the object may be more efficient
// [_delegate imageSelected:currentRecord.image withTitle:currentRecord.title withCreator:currentRecord.creator];
// [_delegate animalSelected:currentRecord];
if (indexPath.section == 1 && indexPath.row == 0) { // this is my date cell above the picker cell
    editingStartTime = !editingStartTime;
    [UIView animateWithDuration:.4 animations:^{
        int height = 0;
        if (editingStartTime) {
            height = 162;
        }
        UITableViewCell* temp = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
        [temp setFrame:CGRectMake(temp.frame.origin.x, temp.frame.origin.y, temp.frame.size.width, height)];
        for (int x = 2; x < [tableView numberOfSections]; x++) {
            for (int y = 0; y < [tableView numberOfRowsInSection:x]; y++) {
                UITableViewCell* temp = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:y inSection:x]];
                int y_coord = temp.frame.origin.y-162;
                if (editingStartTime) {
                    y_coord = temp.frame.origin.y+162;
                }
                [temp setFrame:CGRectMake(temp.frame.origin.x, y_coord, temp.frame.size.width, temp.frame.size.height)];
            }
        }
    }completion:^(BOOL finished){
        [self.tableView reloadData];
    }];
}

Teşekkürler @ Timmahh, bölüm animasyonunu da dalgalı buldum. Çözümünüzü ilk Swift uygulamamda başarıyla kullandım! CellForRowAtIndexPath'in hücrelerin ekran dışında olduğu yerde nil döndürdüğünü buldum. Bundan kaçınmak için, alıcı hücresinden sonra gelen tüm hücrelerimi içeren bir IB çıkış koleksiyonu ekledim ve yeni y_coord'unuzla bunları yineledim. Yeni hücreler eklediğimde koleksiyonu güncel tutmak zorunda olduğum için bu esnek görünmüyor.
Josh

Haklısın. Aslında sorunu çözmüştüm ama yığın taşması oraya koyduğum kodu düzenlememe izin vermiyordu.
Timothy Logan

3

Önceki cevaplara ekleyerek,

Hem @datinc hem de @Aaron Bratcher çözümlerini denedim, ikisi de harika çalıştı, ancak gruplanmış statik bir tableView'da animasyon o kadar temiz değildi.

Biraz oynadıktan sonra benim için temiz ve harika çalışan bu koda ulaştım -

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row == 1)
    {
        if (self.isPickerOpened)
        {
            return 162;
        }
        else
        {
            return 0;
        }
    }
    else
    {
        return [super tableView:tableView heightForRowAtIndexPath:indexPath];
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0 && indexPath.row == 0) {
        [tableView beginUpdates];
        self.isPickerOpened = ! self.isPickerOpened;
        [super tableView:tableView heightForRowAtIndexPath:indexPath];
        [self.tableView endUpdates];
    }
}

Ana değişiklik kullanmaktır -

        [super tableView:tableView heightForRowAtIndexPath:indexPath];

satırı güncellemek için, bu şekilde tablo bölümlerinin ve hücrelerin geri kalanı hareketlendirilmez.

Umarım birine yardımcı olur.

Shani


Bu çok yardımcı oldu; teşekkür ederim! Özellikle Aaron Bratcher'ın gönderisiyle birlikte verilen [süper tableView] yönü bana iOS 9.2'de ihtiyacım olan sonuçları verdi. Tekrar teşekkürler!
Terrance Shaw

2

Önceki cevaplara ve @Aaron Bratcher çözümüne ekleniyor ...

İOS 9'dan beri dalgalı animasyonlar alıyordum ve tablonun yüklenmesi biraz zaman alıyordu ve sinir bozucu olacak kadar. Film şeridinden yükleme için yavaş olan tarih seçicilerine daralttım. Seçicileri film şeridinden ziyade programlı olarak eklemek yükleme performansını iyileştirdi ve bir yan ürün olarak animasyon daha akıcı oldu.

Tarih seçiciyi film şeridinden kaldırın ve yüksekliği önceki yanıtlarda olduğu gibi ayarladığınız boş bir hücreye sahip olun ve ardından viewDidLoad'da bir başlangıç ​​çağırın:

- (void)initialiseDatePickers
{
    self.isEditingStartTime = NO;
    self.startTimePickerCell.clipsToBounds = YES;

    UIDatePicker *startTimePicker = [[UIDatePicker alloc] init];
    [startTimePicker addTarget:self action:@selector(startTimePickerChanged:) forControlEvents:UIControlEventValueChanged];
    [self.startTimePickerCell addSubview:startTimePicker];
}

Sonra eylemi uygulayın, örneğin

- (IBAction)startTimePickerChanged:(id)sender
{
    NSLog(@"start time picker changed");
}

Bu, tabloyu öncekinden çok daha hızlı yükler. Ayrıca, animasyon satırını didSelectRowAtIndexPathonsuz (ymmv) sorunsuz bir şekilde canlandırdığı için kaldırırsınız.

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row == 1) { // this is my date cell above the picker cell
        editingStartTime = !editingStartTime;
    }
}

1

Bu cevabı animasyon olmadan kullanmak iOS 8.1'de doğru çalışıyor. Aşağıda Swift'e çevirdim:

import UIKit

class TableViewController: UITableViewController {

    var editingCell: Bool = false

    @IBOutlet weak var myCell: UITableViewCell!

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

        // Change the section and row to the title cell the user taps to reveal 
        // the cell below
        if (indexPath.section == 0 && indexPath.row == 2 && !editingCell) {
            return 0
        } else {
            return self.tableView.rowHeight
        }
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        self.tableView.deselectRowAtIndexPath(indexPath, animated: false);

        var cell = tableView.cellForRowAtIndexPath(indexPath)

        self.tableView.beginUpdates()
        if (cell == self.myCell) {
            editingType = !editingType;
        }
        self.tableView.endUpdates()
    }
}

1

Statik sabit sayılar olmadan problemi çözmenin başka bir yolu. Tüm hücreler statik ve dinamik tablo görünümlerinde kullanılabilir. Bu yöntem hem başlık hem de tarih seçici için tek hücre kullanır!

Btw, masanızda dilediğiniz kadar tarih seçiciye sahip olabilirsiniz!

Bir UITableViewCell alt sınıfı oluşturun :

Tüm tablo görünümü hücreleriniz bu sınıftan miras alınmalı ve her satır için hücre yüksekliğini manuel olarak ayarlamalısınız.

//
//  CPTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

@class CPTableViewCell;

#define kUIAnimationDuration 0.33f

@protocol CPTableViewCellDelegate <NSObject>

@required
- (void)tableViewCellDidChangeValue:(CPTableViewCell *)cell;
@optional
- (void)tableViewCellDidBecomeFirstResponder:(CPTableViewCell *)cell;
- (void)tableViewCellResignedFirstResponder:(CPTableViewCell *)cell;
@end

@interface CPTableViewCell : UITableViewCell

@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet CPTableViewCell *nextCell;
@property (nonatomic, weak) IBOutlet id<CPTableViewCellDelegate> delegate;

@property (nonatomic, copy) IBInspectable NSString *dataBindKey;
@property (nonatomic) IBInspectable CGFloat height;

@property (nonatomic, readonly) BOOL isFirstResponder;
@property (nonatomic) BOOL isEnabled;

- (void)commonInit;

- (id)value;
- (void)setValue:(id)value;

@end

//
//  CPTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTableViewCell ()
@end

@implementation CPTableViewCell

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (!self)
        return nil;

    [self commonInit];

    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (!self)
        return nil;

    [self commonInit];

    return self;
}

- (void)commonInit
{
    _isFirstResponder = NO;
    _isEnabled = YES;
}

- (BOOL)canBecomeFirstResponder
{
    return _isEnabled;
}

- (BOOL)becomeFirstResponder
{
    if ([_delegate respondsToSelector:@selector(tableViewCellDidBecomeFirstResponder:)])
        [_delegate tableViewCellDidBecomeFirstResponder:self];

    return _isFirstResponder = YES;
}

- (BOOL)resignFirstResponder
{
    if (_isFirstResponder)
    {
        if ([_delegate respondsToSelector:@selector(tableViewCellResignedFirstResponder:)])
            [_delegate tableViewCellResignedFirstResponder:self];

        _isFirstResponder = NO;
    }

    return _isFirstResponder;
}

- (id)value
{
    [self doesNotRecognizeSelector:_cmd];

    return nil;
}

- (void)setValue:(id)value
{
    [self doesNotRecognizeSelector:_cmd];
}

@end

CPTableViewCell'den bir CPDatePickerTableViewCell sınıfı oluşturun

//
//  CPDatePickerTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPDatePickerTableViewCell : CPTableViewCell

@property (nonatomic, copy) IBInspectable NSString *dateFormat;

@property (nonatomic, weak) IBOutlet UILabel *titleLabel;
@property (nonatomic, weak) IBOutlet UILabel *dateLabel;

@property (nonatomic, weak) IBOutlet UIDatePicker *datePicker;

@end

//
//  CPDatePickerTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPDatePickerTableViewCell.h"

#define kCPDatePickerTableViewCellPickerHeight 162.f

@interface CPDatePickerTableViewCell () <UITextFieldDelegate, UIPickerViewDelegate>
{
    NSDateFormatter *_dateFormatter;
    BOOL _isOpen;
}
@end

@implementation CPDatePickerTableViewCell

- (void)awakeFromNib
{
    [super awakeFromNib];

    _dateFormatter = [NSDateFormatter new];
    [_dateFormatter setDateFormat:_dateFormat];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _dateLabel.text = [_dateFormatter stringFromDate:_datePicker.date];
    _datePicker.alpha = 0.f;
    _isOpen = NO;
}

- (BOOL)becomeFirstResponder
{
    if (_isOpen == NO)
    {
        self.height += kCPDatePickerTableViewCellPickerHeight;
    }
    else
    {
        self.height -= kCPDatePickerTableViewCellPickerHeight;
    }

    [UIView animateWithDuration:kUIAnimationDuration animations:^{
        _datePicker.alpha = _isOpen ? 0.0f : 1.0f;
    }];

    [self.tableView beginUpdates];
    [self.tableView endUpdates];

    _isOpen = !_isOpen;

    [self.tableView endEditing:YES];

    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
    if (_isOpen == YES)
    {
        self.height -= kCPDatePickerTableViewCellPickerHeight;

        [UIView animateWithDuration:kUIAnimationDuration animations:^{
            _datePicker.alpha = 0.0f;
        }];

        [self.tableView beginUpdates];
        [self.tableView endUpdates];

        _isOpen = NO;
    }

    return [super resignFirstResponder];
}

- (id)value
{
    return _datePicker.date;
}

- (void)setValue:(NSDate *)value
{
    _datePicker.date = value;
    _dateLabel.text = [_dateFormatter stringFromDate:_datePicker.date];
}

- (IBAction)datePickerValueChanged:(UIDatePicker *)sender
{
    [_dateLabel setText:[_dateFormatter stringFromDate:_datePicker.date]];

    [self.delegate tableViewCellDidChangeValue:self];
}

@end

Görünüm denetleyicinizde bu iki temsilci yöntemi uygulayın

#pragma mark - UITableViewDelegate methods

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CPTableViewCell *cell = (CPTableViewCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath];

    return [cell height];
}

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    CPTableViewCell *cell = (CPTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];

    if ([cell canBecomeFirstResponder])
    {
        [cell becomeFirstResponder];
    }

    if (cell != _selectedCell)
    {
        [_selectedCell resignFirstResponder];
    }

    _selectedCell = cell;

    return YES;
}

Arabirim oluşturucuda kısıtlamaların nasıl ayarlanacağı örneği

Arayüz oluşturucu

Ek olarak, UITextField ve UITextView için özel hücre sınıfları yazdım, burada tableView: didSelectRowAtIndexPath: hücre seçildiğinde çağrılır!

CPTextFieldTableViewCell

//
//  CPTextFieldTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTextFieldTableViewCell : CPTableViewCell

@property (nonatomic, weak) IBOutlet UITextField *inputTextField;

@end

//
//  CPTextFieldTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTextFieldTableViewCell.h"

@interface CPTextFieldTableViewCell () <UITextFieldDelegate>
@end

@implementation CPTextFieldTableViewCell

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _inputTextField.userInteractionEnabled = NO;
    _inputTextField.delegate = self;
}

- (BOOL)becomeFirstResponder
{
    _inputTextField.userInteractionEnabled = YES;

    [_inputTextField becomeFirstResponder];

    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
    _inputTextField.userInteractionEnabled = NO;

    return [super resignFirstResponder];
}

- (void)setIsEnabled:(BOOL)isEnabled
{
    [super setIsEnabled:isEnabled];

    _inputTextField.enabled = isEnabled;
}

- (id)value
{
    return _inputTextField.text;
}

- (void)setValue:(NSString *)value
{
    _inputTextField.text = value;
}

#pragma mark - UITextFieldDelegate methods

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self.delegate tableViewCellDidChangeValue:self];
}

@end

CBTextViewTableViewCell

Hücre yüksekliği dinamiktir ve metin yeni satıra kaydırıldığında satır büyür!

//
//  CBTextViewTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTextViewTableViewCell : CPTableViewCell

@property (nonatomic, weak) IBOutlet UITextView *inputTextView;

@end

//
//  CBTextViewTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTextViewTableViewCell.h"

@interface CPTextViewTableViewCell () <UITextViewDelegate>
{
    UITextView *_heightTextView;
}

@end

@implementation CPTextViewTableViewCell

@synthesize height = _height;

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _inputTextView.userInteractionEnabled = NO;
    _inputTextView.delegate = self;
    _inputTextView.contentInset = UIEdgeInsetsZero;
    _inputTextView.scrollEnabled = NO;
}

- (CGFloat)height
{
    if (!_heightTextView)
    {
        CGRect frame = (CGRect) {
            .origin = CGPointMake(0.f, 0.f),
            .size = CGSizeMake(_inputTextView.textInputView.frame.size.width, 0.f)
        };

        _heightTextView = [[UITextView alloc] initWithFrame:frame];
        _heightTextView.font = [UIFont systemFontOfSize:_inputTextView.font.pointSize];
        _heightTextView.textColor = UIColor.whiteColor;
        _heightTextView.contentInset = UIEdgeInsetsZero;
    }

    _heightTextView.text = _inputTextView.text;

    CGSize size = [_heightTextView sizeThatFits:CGSizeMake(_inputTextView.textInputView.frame.size.width, FLT_MAX)];

    return size.height > _height ? size.height + _inputTextView.font.pointSize : _height;
}

- (BOOL)becomeFirstResponder
{
    _inputTextView.userInteractionEnabled = YES;

    [_inputTextView becomeFirstResponder];

    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
    _inputTextView.userInteractionEnabled = NO;

    return [super resignFirstResponder];
}

- (void)setIsEnabled:(BOOL)isEnabled
{
    [super setIsEnabled:isEnabled];

    _inputTextView.editable = isEnabled;
}

- (id)value
{
    return _inputTextView.text;
}

- (void)setValue:(NSString *)value
{
    _inputTextView.text = value;

    [_inputTextView setNeedsLayout];
    [_inputTextView layoutIfNeeded];
}

#pragma mark - UITextViewDelegate methods

- (void)textViewDidChange:(UITextView *)textView
{
    [self.delegate tableViewCellDidChangeValue:self];

    [self.tableView beginUpdates];
    [self.tableView endUpdates];
}

@end

0

Swift sürümünde DateCell'i kullanmanın en kolay yolu: Bu örneği kullanın .

  1. Bu örneği açın ve test edin (Swift 2'ye Dönüştürmek için Xcode Yapın)
  2. " DateCellTableViewController.swift " sınıfını projenize sürükleyin .

  3. "Main.storyboard" u açın ve " DateCell " ViewController Nesnesini Kopyalayın ve onu film şeridinize yapıştırın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.