Tutorial sobre cómo arrastrar y soltar elementos de UITableView a UITableView [cerrado]


He estado golpeando mi cabeza en este por un tiempo y me di cuenta. Quiero retribuir a la comunidad ya que he recibido mucha ayuda de este sitio web :).

Estoy tratando de copiar un elemento de un UITableView a otro UITableView y la información que he visto en la web sobre cómo hacer esto ha sido incompleta en el mejor de los casos. Lo descubrí por mi cuenta, así que describiré mi pequeña arquitectura.

  • Master UIView
    • UIView con UITableView
      • UITableViewCell personalizado
        • UIView personalizado que se copia (objeto Person en mi caso)
    • UIView con UITableView
      • UITableViewCell personalizado
        • UIView personalizado que se copia (objeto Person en mi caso)

El objeto person que tengo en UITableView es el objeto que quiero arrastrar y soltar de una tabla a otra. Tuve el más difícil averiguar cómo hacer estallar el elemento fuera de la mesa y arrastrarlo en un solo movimiento suave. Durante mucho tiempo, me tomaría dos toques para realizar la operación.

Comenzando con el objeto Person, este es un objeto simple que contiene una imagen. Tuve que implementar mi propio método touchesMoved para cambiar la posición central de la Persona cuando se está produciendo un arrastre.

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    if( m_moveable == YES ){
        UITouch *touch = [touches anyObject];
        CGPoint location = [touch locationInView:self.superview];

        if( 0 < location.x-50 && location.x+50 < 768 ){ 
            if( 0 < location.y-50 && location.y+150 < 1004 ){
                self.center = location;
            }
        }
    }
}

Establezco la bandera userInteractionEnabled del objeto Person en NO on initialization para que cualquier los clics en la tabla no serían atrapados por el objeto Person. El objeto de la Persona en ese caso se movería dentro de la tabla que derrota el propósito.

El siguiente objeto es mi UITableViewCell personalizado. Este objeto es responsable de capturar el primer toque del usuario. Lo que se supone que debe hacer es coger este toque y "pop" la Persona hacia fuera. La Persona es una de las subviews que pertenece a la UITableViewCell personalizada.

 - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UIView *parent = self.superview.superview.superview;    

    Person *s = nil;
    for( UIView *child in self.subviews ){
        if( [child isKindOfClass:[Person class]] ){
            s = child;
            s removeFromSuperview];
            break;
        }        
    }

    if( s != nil ){
        self.userInteractionEnabled = NO;
        s.userInteractionEnabled = YES;
        UITableView *subParent = self.superview;   //EDIT #1
        subParent.scrollEnabled = NO;              //EDIT #1

        [parent addSubview:s];
        //[self touchesEnded:touches withEvent:event]; //EDIT #1
    }
}

Es importante tener en cuenta el indicador userInteractionEnabled getting volteado en el método anterior. Antes del tacto, el objeto Persona está "fuera de los límites" al tacto de una persona. Después de que la celda personalizada capta un movimiento, la Persona se libera agregándola a la vista del padre y luego se activa (userInteractionEnabled=YES). El objeto de la persona entonces "nace" y puede manejar los toques del movimiento en él es propio.

Esto tiene una falla menor en que el objeto Person parpadea en la esquina superior izquierda, pero luego cae inmediatamente al dedo del usuario.

La parte final de este diseño es que el maestro UIView necesita manejar una "transición táctil"."Cuando el usuario toca la mesa y el objeto Person sale, la aplicación debe darse cuenta de que el enfoque debe eliminarse de la mesa y dirigirse hacia el objeto Person. La forma en que se hizo esto es que el método hitTest en el UIView maestro se sobrecargó con lo siguiente.

- (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *rv = nil;
    for(UIView *child in self.subviews){
        if( [child isKindOfClass:[Person class]] ){
            rv = child;
            child.center = point;
            break;
        }
    }
    if( rv == nil ){
        rv = [super hitTest:point withEvent:event];
    }   
    return rv;
}

La forma en que funciona este código es que cuando la Persona sale de la mesa, no tiene un toque centrado en ello. El toque es "propiedad" de la UITableView de la que la Persona salió. El método hitTest es la clave para reenfocar ese toque. Regularmente, el sistema comprueba para ver qué UIView es el foco de un toque. El sistema llama al método hitTest para identificar ese UIView. Cuando la Persona está conectada a la vista maestra, esta función hitTest itera a través de todas las subviews y detecta la presencia de la Persona y la devuelve como el objeto tocado "dominante". Cualquier movimiento de su dedo será reportado inmediatamente a la Persona y no al UITableView.

Esto es tripas de la implementación. Tener un UITableView "atrapar" el objeto en movimiento es simple ahora y lo dejaré para que lo pruebes! Si usted tiene alguna pregunta, por favor, publicarlo!

EDITAR #1 Dejar caer el objeto Persona está resultando más difícil de lo que pensé :). Tuve que agregar una línea para evitar que UITableView se desplace cuando el padre se está moviendo porque UITableView está succionando todos los eventos del movimiento.
La función touchesEnded se activa en la clase UITableViewCell personalizada.
mj

Author: Vadim Kotov, 2010-08-14

1 answers

Hola he logrado crear arrastrar y soltar una fila en una UITableView en otra fila de la misma tabla. Creé un UIImageView que representa el elemento en movimiento (que no se eliminó de la tabla) y lo adjunté al UIView más frontal para hacerlo arrastrable en toda la pantalla. Aquí están algunos post sobre los dolores que enfrenté:

  1. UITableView: Arrastre una fila a otra
  2. UITableView: desplazando programáticamente la vista de contenido
  3. UITableView: los gestos personalizados hacen que no se desplace más

Espero que esto pueda ayudar ^^

 7
Author: rano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:32:42