wake-up-neo.com

Animieren einer benutzerdefinierten UITableViewCell beim Aufrufen des Bearbeitungsmodus

Hintergrund

Erstmal vielen Dank an Atebits für ihren sehr informativen Blogpost Schnelles Scrollen in Tweetie mit UITableView . In dem Beitrag wird ausführlich erläutert, wie die Entwickler aus den UITableViews in Tweetie möglichst viel Scrollen erzielen konnten.

Tore

Beginnend mit dem Quellcode, der aus dem Blogpost ( original ) ( my github repo ) verlinkt ist:

  1. Lassen Sie eine UITableView, die diese benutzerdefinierten Zellen verwendet, in den Bearbeitungsmodus wechseln, und legen Sie die Benutzeroberfläche zum Löschen eines Elements aus der Tabelle bereit. ( github commit )

  2. Bewegen Sie den Text der Zelle beiseite, während die Löschkontrolle von links nach innen verschoben wird. Dies ist vollständig, obwohl der Text ohne Animation vor- und zurückspringt. ( github commit )

  3. Wenden Sie die Animation auf die Textbewegung in Ziel 2 an, um eine reibungslose Benutzererfahrung zu gewährleisten. Dies ist der Schritt, bei dem ich feststeckte.

Die Frage

Wie kann man diese Animation am besten in Ziel 3 einführen? Es wäre schön, wenn dies auf eine Art und Weise erfolgen könnte, die die Logik von meinem last commit hält, weil ich die Option lieben würde, nur den widersprüchlichen Teil der Ansicht zu verschieben, während andere, nicht widersprüchliche Teile (z. B. rechts) -justierter Text) bleiben an derselben Stelle oder verschieben eine andere Anzahl von Pixeln. Wenn dies nicht möglich ist, wäre es eine praktikable Lösung, den letzten Commit rückgängig zu machen und ihn durch eine Option zu ersetzen, die die gesamte Ansicht nach rechts schiebt.

Ich freue mich über jede Hilfe, die jeder bieten kann, von schnellen Hinweisen und Ideen bis hin zu Code-Snippets oder Github-Commits. Gerne können Sie mein Repo wenn Sie möchten. Ich werde mich weiter mit dieser Frage beschäftigen, um sicherzustellen, dass jede erfolgreiche Lösung für github festgelegt und hier vollständig dokumentiert wird. Vielen Dank für deine Zeit!

Gedanken aktualisiert

Ich habe seit meinem ersten Beitrag viel darüber nachgedacht und festgestellt, dass das Verschieben einiger Textelemente relativ zu den anderen in der Ansicht einige der ursprünglichen Leistungsziele, die im ursprünglichen Blogpost gelöst wurden, rückgängig machen kann. An diesem Punkt denke ich an eine Lösung, bei der die gesamte einzelne Unteransicht zu ihrer neuen Position animiert wird, möglicherweise die beste.

Zweitens: Wenn dies auf diese Weise erfolgt, kann es vorkommen, dass die Unteransicht eine benutzerdefinierte Farbe oder einen Hintergrund mit Farbverlauf hat. Hoffentlich kann dies auf eine Weise geschehen, dass sich der Hintergrund in seiner normalen Position ungesehen genug nach links erstreckt, sodass der benutzerdefinierte Hintergrund in der gesamten Zelle immer noch sichtbar ist, wenn die Ansicht nach rechts verschoben wird.

49
Adam Alexander

Dank Craigs Antwort die mir in die richtige Richtung zeigte, habe ich eine Lösung dafür. Ich habe mein commit zurückgesetzt, das die Textposition basierend auf dem Bearbeitungsmodus verschoben und durch eine neue Lösung ersetzt hat die die gesamte Inhaltsansicht bei jedem Aufruf von layoutSubviews an die richtige Position setzt, was zu einer automatischen Ansicht führt Animation beim Wechseln zum und vom Bearbeitungsmodus:

- (void)layoutSubviews
{
    CGRect b = [self bounds];
    b.size.height -= 1; // leave room for the separator line
    b.size.width += 30; // allow extra width to slide for editing
    b.Origin.x -= (self.editing) ? 0 : 30; // start 30px left unless editing
    [contentView setFrame:b];
    [super layoutSubviews];
}

Auf diese Weise konnte ich die in ABTableViewCell.m gefundene setFrame: override entfernen, da ihre frühere Logik und meine Ergänzungen jetzt in layoutSubviews gefunden werden. 

Ich habe einen hellgrauen Hintergrund für die Zellen festgelegt, um zu überprüfen, ob ein benutzerdefinierter Hintergrund ordnungsgemäß funktioniert, ohne dass wir dahinter sehen können, wenn er sich vor und zurück bewegt, und es scheint gut zu funktionieren.

Nochmals vielen Dank an Craig und alle anderen, die sich damit befasst haben.

GitHub-Commit für diese Lösung: ( link )

24
Adam Alexander

Wie bewegen Sie den Text aktuell? Oder genauer: In welcher UITableViewCell-Methode führen Sie die Verschiebung durch?

Nach meiner Erfahrung wird das Überschreiben der layoutSubviews-Methode und das Setzen des Frames hier automatisch in eine Animation eingebettet.

Z.B:

- (void)layoutSubviews {
    if (self.editing) {
        [titleLabel setFrame:CGRectMake(62, 6, 170, 24)];
    }
    else {
        [titleLabel setFrame:CGRectMake(30, 6, 200, 24)];
    }
    [super layoutSubviews];
}
10
Craig Otis

Um die Bearbeitung in Ihrer benutzerdefinierten Zelle vollständig zu steuern, sollten Sie die Methode willTransitionToState in Ihrer UITableViewCell-Unterklasse überschreiben und die Statusmaske überprüfen

- (void)willTransitionToState:(UITableViewCellStateMask)state
{
    NSString *logStr = @"Invoked";
    if ((state & UITableViewCellStateShowingEditControlMask)
        != 0) {
        // you need to move the controls in left
        logStr = [NSString stringWithFormat:@"%@
                  %@",logStr,@"UITableViewCellStateShowingEditControlMask"];
    }
    if ((state & UITableViewCellStateShowingDeleteConfirmationMask)
        != 0) {
        // you need to hide the controls for the delete button
        logStr = [NSString stringWithFormat:@"%@
                  %@",logStr,@"UITableViewCellStateShowingDeleteConfirmationMask"];
    }
    NSLog(@"%@",logStr);
    [super willTransitionToState:state];
}

sie können auch layoutSubviews überschreiben

- (void)layoutSubviews {
    // default place for label
    CGRect alarmTimeRect = CGRectMake(37, 7, 75, 30);
    if (self.editing && !self.showingDeleteConfirmation) {
        // move rect in left
        alarmTimeRect = CGRectMake(77, 7, 75, 30);
    }
    [alarmTimeLabel setFrame:alarmTimeRect];
    [super layoutSubviews];
}
9
UIBuilder

Um auch mit dem Wischen umzugehen: (self.editing &&!

8
ben

Ich hatte gerade auch diese Frage: Wie animiere ich einen benutzerdefinierten Bearbeitungsmodus? Ich mochte die Lösung hier nicht wirklich, also entschied ich mich, ein wenig nachzudenken und eine andere Lösung zu finden. Ich weiß nicht, ob es besser ist, aber ich ziehe das vor. Also habe ich beschlossen, es hier zu teilen:

Überladen Sie in der benutzerdefinierten Zelle (von UITableViewCell erben) einfach setEditing:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];

    if (animated) {
        [UIView beginAnimations:@"setEditingAnimation" context:nil];
        [UIView setAnimationDuration:0.3];
    }

    if (editing) {
        /* do your offset and resize here */
    } else {
        /* return to the original here*/
    }

    if (animated)
        [UIView commitAnimations];
}

Ich überprüfe nicht, ob der Bearbeitungswert derselbe ist, aber so habe ich es gemacht. 

3
Sauleil

Es gibt tatsächlich vier Editzustände.

UITableViewCellStateDefaultMask = 0

UITableViewCellStateShowingEditControlMask = 1 << 0 = 0b01 = 1 durch Setzen von tableView.edit = YES

UITableViewCellStateShowingDeleteConfirmationMask = 1 << 1 = 0b10 = 2 durch Wischen zum Löschen

UITableViewCellStateShowingEditControlMask und UITableViewCellStateShowingDeleteConfirmationMask = (1 << 1) & (1 << 0) = 0b11 = 3 durch Setzen von tableView.edit = YES und Drücken der Schaltfläche "Stop"

Was mich verwirrt ist, dass beim Übergang von Zustand 3 zu Zustand 1 kein Selektor aufgerufen wird, der self.showingDeleteConfirmation nicht verwendet, um das Layout zu ändern in iOS7 In Zustand 3 habe ich eine Instanzvariable hinzugefügt, um sie zu implementieren. Es funktioniert großartig für mich.

-(void)willTransitionToState:(UITableViewCellStateMask)state{
    [super willTransitionToState:state];

    //Custom delete button from
    //http://stackoverflow.com/questions/19159476/uitableviewcelldeleteconfirmationcontrol-issue
    if((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask){
        [self recurseAndReplaceSubViewIfDeleteConfirmationControl:self.subviews];
        [self performSelector:@selector(recurseAndReplaceSubViewIfDeleteConfirmationControl:) withObject:self.subviews afterDelay:0];
    }

    _swipeDelete = NO;

    if(state==2){
        //Swipe to delete confirm
        _swipeDelete = YES;
    }

    if(state==3){
        //Edit state to delete confirm
    }
}

- (void)layoutSubviews{

    [super layoutSubviews];

    self.contentView.frame = CGRectMake(10, 5.0, 300, self.frame.size.height - 10);

    if(self.editing){
        self.contentView.frame = CGRectMake(40, 5.0, 270, self.frame.size.height - 10);
    }

    if(_swipeDelete){
        self.contentView.frame = CGRectMake(10, 5.0, 300, self.frame.size.height - 10);
    }
}
0
Henry