Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reorder uitableviewcell without showing reorder control?

I'm using spliviewcontroller for my ipad application. I've also implemented reordering for the uitableview which on the left of spliview. What i want to achieve is user can reorder the tableCell but need not touch on the three white bars. User should be able to touch anywhere on cell and reorder it. Is it possible?

like image 679
Kavya Indi Avatar asked Oct 07 '11 06:10

Kavya Indi


3 Answers

The class below will hide the reorder control and make the whole UITableViewCell touchable for reordering. Additionally, it takes care of re-resizing the content view to its original size, which is important for autolayout.

@interface UITableViewCellReorder : UITableViewCell
{
    __weak UIView *_reorderControl;
}

@implementation UITableViewCellReorder

#define REORDER_CONTROL_CLASSNAME @"UITableViewCellReorderControl"

/*
 Override layoutSubviews to resize the content view's frame to its original size which is the size 
 of the cell. This is important for autolayout!
 Do not call this method on super, as we don't need any further layouting wihtin the cell itself.
 */

- (void)layoutSubviews
{
    self.contentView.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
    [self setAndHideReorderControl];
}

/*
 Find the reorder control, store a reference and hide it.
 */

- (void) setAndHideReorderControl
{
    if (_reorderControl)
        return;

    // > iOS 7
    for(UIView* view in [[self.subviews objectAtIndex:0] subviews])
        if([[[view class] description] isEqualToString:REORDER_CONTROL_CLASSNAME])
            _reorderControl = view;

    // < iOS 7
    if (!_reorderControl)
        for(UIView* view in self.subviews)
            if([[[view class] description] isEqualToString:REORDER_CONTROL_CLASSNAME])
                _reorderControl = view;

    if (_reorderControl)
    {
        [_reorderControl setHidden:YES];
    }
}


#pragma mark - Touch magic

/*
 Just perform the specific selectors on the hidden reorder control to fire touch events on the control.
 */

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_reorderControl && [_reorderControl respondsToSelector:@selector(beginTrackingWithTouch:withEvent:)])
    {
        UITouch * touch = [touches anyObject];
        [_reorderControl performSelector:@selector(beginTrackingWithTouch:withEvent:) withObject:touch withObject:event];
    }

    [super touchesBegan:touches withEvent:event];
    [self.nextResponder touchesBegan:touches withEvent:event];
}

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_reorderControl && [_reorderControl respondsToSelector:@selector(continueTrackingWithTouch:withEvent:)])
    {
        UITouch * touch = [touches anyObject];
        [_reorderControl performSelector:@selector(continueTrackingWithTouch:withEvent:) withObject:touch withObject:event];
    }

    [super touchesMoved:touches withEvent:event];
    [self.nextResponder touchesMoved:touches withEvent:event];
}

- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_reorderControl && [_reorderControl respondsToSelector:@selector(cancelTrackingWithEvent:)])
    {
        [_reorderControl performSelector:@selector(cancelTrackingWithEvent:) withObject:event];
    }

    [super touchesCancelled:touches withEvent:event];
    [self.nextResponder touchesCancelled:touches withEvent:event];
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (_reorderControl && [_reorderControl respondsToSelector:@selector(endTrackingWithTouch:withEvent:)])
    {
        UITouch * touch = [touches anyObject];
        [_reorderControl performSelector:@selector(endTrackingWithTouch:withEvent:) withObject:touch withObject:event];
    }

    [super touchesEnded:touches withEvent:event];
    [self.nextResponder touchesEnded:touches withEvent:event];
}

@end
like image 172
Thomas Avatar answered Sep 30 '22 03:09

Thomas


Yes! Check out: http://b2cloud.com.au/how-to-guides/reordering-a-uitableviewcell-from-any-touch-point

like image 23
BoxCat Avatar answered Sep 30 '22 01:09

BoxCat


I know it's an old question, but here's a Swift helper that should help future adventure seekers.

/*
    THIS IS A HACK!
    It uses undocumented controls and class names, and will need to be revised with every iOS release.

    Usage:
        Call the 'transform' method after the cell is displayed - i.e. tableView(tableView: UITableView!, willDisplayCell cell: UITableViewCell! ...

    Adopted from:
        http://b2cloud.com.au/how-to-guides/reordering-a-uitableviewcell-from-any-touch-point

    In case of failure: 
        - print names of all subviews
        - find the new 'UITableViewCellReorderControl' and reflect changes to the code below
*/
struct MovableTableViewCell {
    static func transform(cell:UITableViewCell) {
        var reorder = cell.getSubviewByName("UITableViewCellReorderControl")

        if (reorder == nil) {
            println("UITableViewCellReorderControl was not found. Reorder control will remain unchanged.")
            return
        }

        // resized grip
        var resized = UIView(frame: CGRectMake(0, 0, CGRectGetMaxX(reorder!.frame), CGRectGetMaxY(reorder!.frame)))
        resized.addSubview(reorder!)
        cell.addSubview(resized)

        // remove image
        for img:AnyObject in reorder!.subviews {
            if (img is UIImageView) {
                (img as UIImageView).image = nil
            }
        }

        // determine diff and ratio
        var diff = CGSizeMake(resized.frame.width - reorder!.frame.width, resized.frame.height - reorder!.frame.height)
        var ratio = CGSizeMake(resized.frame.width / reorder!.frame.width, resized.frame.height / reorder!.frame.height)

        // transform!
        var transform = CGAffineTransformIdentity
        transform = CGAffineTransformScale(transform, ratio.width, ratio.height)
        transform = CGAffineTransformTranslate(transform, -diff.width / 2.0, -diff.height / 2.0)
        resized.transform = transform
    }
}


extension UIView {
    func getSubviewByName(name:String) -> UIView? {

        if (object_getClassName(self) == name.bridgeToObjectiveC().UTF8String) {
            return self
        }

        for v in (self.subviews as Array<UIView>) {
            var child = v.getSubviewByName(name)

            if (child != nil) {
                return child
            }
        }

        return nil
    }
}
like image 38
ANaimi Avatar answered Sep 30 '22 03:09

ANaimi