【问题标题】:UIScrollView with rearrangable buttons带有可重新排列按钮的 UIScrollView
【发布时间】:2013-07-05 15:17:41
【问题描述】:

我需要实现一个带有许多按钮的弹出菜单。我已经创建了弹出窗口并动态添加了按钮。现在我需要像 iPhone 主屏幕那样重新排列按钮。 当发生长按手势时,按钮需要使用关闭按钮开始动画(就像我们尝试从手机中删除应用程序时出现的那样)。此外,我需要通过拖动来重新排列按钮的位置。我已经为按钮的外观和关闭按钮添加了动画,但我正在努力寻找一种重新排列按钮位置的方法。我进行了很多搜索,发现了许多有关此功能的链接,但其中大多数都非常冗长和复杂。我只想要一个可以快速实施的快速/简单的。 有什么想法吗?

【问题讨论】:

  • 如果您使用 UICollectionView 而不仅仅是 UIScrollView,这会容易得多。 “更容易” == “内置功能”。
  • @我需要支持ios 4.3及以上版本:(
  • 老兄,放下它们。 david-smith.org/iosversionstats 除非您真的绝对需要支持非常旧的设备,否则请放弃它们。随着 iOS7 即将推出,我现在只支持 iOS6.0+。
  • 如果你对老式 iOS 非常感兴趣,你也可以使用PSTCollectionView

标签: iphone ios objective-c uiscrollview uibutton


【解决方案1】:

我有同样的问题,我用下面的代码解决了我的问题。

1) 从 Document 文件夹中获取所有图片
2) 在滚动视图中设置它
3) 将 UILongPressGestureRecognizer 放在 Imageview 上。并显示十字按钮。
4) 如果删除,则重复步骤 2 至 4。


无需安排整个项目,只需从滚动视图中删除所有项目并重新填充即可。

    //Document Directory
    #define kAppDirectoryPath   NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)

    #pragma mark - File Functions - Document/Cache Directory Functions
    - (void)createDocumentDirectory:(NSString*)pStrDirectoryName
    {
        NSString *dataPath = [self getDocumentDirectoryPath:pStrDirectoryName];

        if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
            [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:NULL];
    }

    - (NSString*)getDocumentDirectoryPath:(NSString*)pStrPathName
    {
        NSString *strPath = @"";
        if(pStrPathName)
            strPath = [[kAppDirectoryPath objectAtIndex:0] stringByAppendingPathComponent:pStrPathName];

        return strPath;
    }



    -(void)setScrollviewItem {

        NSArray* subviews = [[NSArray alloc] initWithArray: scrollObj.subviews];
        for (UIView* view in subviews) {
            if ([view isKindOfClass:[UIImageView class]]) {
                [view removeFromSuperview];
            }
            if ([view isKindOfClass:[UIButton class]]) {
                [view removeFromSuperview];
            }
        }
        [subviews release];

        [arrSaveImage removeAllObjects];  
        NSError *error = nil;
        NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[slef getDocumentDirectoryPath:@"MyPhotos"] error:&error];// MyPhoto is my Directory Name.
        if (!error) {
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self ENDSWITH '.png'"];
            NSArray *imagesOnly = [dirContents filteredArrayUsingPredicate:predicate];

            for (int i=0;i<[imagesOnly count]; i++) {
                [arrSaveImage addObject:[imagesOnly objectAtIndex:i]];
            }
        }

        int px=0;
        for (int i = 0; i < [arrSaveImage count]; i++) {
            UIImageView *imgBackScroll=[[UIImageView alloc] init];
            NSString *strPath=[self getDocumentDirectoryPath:@"MyPhotos"];
            strPath=[NSString stringWithFormat:@"%@/%@",strPath,[arrSaveImage objectAtIndex:i]];
            imgBackScroll.image=[UIImage imageWithData:[NSData dataWithContentsOfFile:strPath]];
            imgBackScroll.frame=CGRectMake(px+5, 10, 90, 80);
            imgBackScroll.layer.cornerRadius = 5.0;
            imgBackScroll.layer.masksToBounds = YES;
            imgBackScroll.tag=i;
            imgBackScroll.userInteractionEnabled = YES;
            [scrollObj addSubview:imgBackScroll];

            UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];//This is your Cross delete button on corner
            //[btn setTitle:@"-" forState:UIControlStateNormal];
            [btn setImage:[UIImage imageNamed:@"CrossDelete.png"] forState:UIControlStateNormal];
            [btn addTarget:self action:@selector(deleteButton:) forControlEvents:UIControlEventTouchUpInside];
            btn.frame=CGRectMake(imgBackScroll.frame.origin.x-2, 0, 15, 15);
            btn.hidden=YES;
            btn.tag=i;

            [scrollObj addSubview:btn];


            UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(startWobbling:)];
            longPressGesture.view.tag=i;
            [imgBackScroll addGestureRecognizer:longPressGesture];

            [imgBackScroll release];
            [longPressGesture release];

            px=px+95;
        }
        scrollObj.contentSize = CGSizeMake(px, scrollObj.frame.size.height);
    }



    -(void) startWobbling:(UILongPressGestureRecognizer*)gesture{
           CGAffineTransform leftWobble = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(-5.0));
            CGAffineTransform rightWobble = CGAffineTransformRotate(CGAffineTransformIdentity, RADIANS(5.0));

            gesture.view.transform = leftWobble;  // starting point

            [UIView beginAnimations:@"wobble" context:gesture.view];
            [UIView setAnimationRepeatAutoreverses:YES]; // important
            [UIView setAnimationRepeatCount:11];
            [UIView setAnimationDuration:0.25];
            [UIView setAnimationDelegate:self];
            [UIView setAnimationDidStopSelector:@selector(wobbleEnded:finished:context:)];

            gesture.view.transform = rightWobble; // end here & auto-reverse

            [UIView commitAnimations];

        NSArray* subviews = [[NSArray alloc] initWithArray: scrollObj.subviews];
        for (UIView* view in subviews) {

            if ([view isKindOfClass:[UIButton class]]) {
                if (view.tag==gesture.view.tag) {
                    view.hidden=NO;
                }
            }
        }
        [subviews release];
    }


    //When Delete button pressed

    -(IBAction)deleteButton:(id)sender {
        UIButton *bt=(UIButton *)sender;
     self.strDeleteFilePath=[FunctionManager getDocumentDirectoryPath:@"MyPhotos"];
        self.strDeleteFilePath=[NSString stringWithFormat:@"%@/%@",strDeleteFilePath,[arrSaveImage objectAtIndex:bt.tag]];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Are you sure you want to delete this photo" delegate:self cancelButtonTitle:@"Delete" otherButtonTitles:@"Cancel", nil];
        [alert show];
        [alert release];
    }

    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
        if (buttonIndex == 0){
            NSFileManager *fileManager = [NSFileManager defaultManager];
            NSError *error = nil;
            if(![fileManager removeItemAtPath:self.strDeleteFilePath error:&error]) {
                NSLog(@"Delete failed:%@", error);
            } else {
                NSLog(@"image removed: %@",strDeleteFilePath);
            }
            [self setScrollviewItem];
        }
    }

【讨论】:

    【解决方案2】:

    我尝试了许多库并发现了一个很棒且实用的解决方案:UzysGridView

    这非常简单且易于定制。

    【讨论】:

      【解决方案3】:

      查看这些示例代码,

      https://github.com/gmoledina/GMGridView

      http://mobile.tutsplus.com/tutorials/iphone/uicollectionview-layouts/

      希望这些示例代码能满足您的需求..

      【讨论】:

        【解决方案4】:

        UICollectionView 做得更有效。

        如果您不想使用 UICollectionView,请尝试继承 UIScrollView 并覆盖 layoutSubview 方法 - 每当您需要重新排列按钮时,请调用 setNeedsLayout。

        示例(未测试):

        - (void)layoutSubviews
        {
        [super layoutSubviews];
        
        CGFloat x = 0;
        CGFloat y = 0;
        
        CGFloat buttonWidth = 100;
        CGFloat buttonHeight = 100;
        CGFloat spaceBetweenButtons = 10;
        
        for (UIButton *button in self.subviews)
        {
            if ([button isKindOfClass:[UIButton class]])
            {
                button.frame = CGRectMake(x, y, buttonWidth, buttonHeight);
        
                x+=buttonWidth+spaceBetweenButtons;
        
                if (x + buttonWidth > self.frame.size.width)
                {
                    x = 0;
                    y += spaceBetweenButtons+ buttonHeight;
                }
            }
        }
        
        self.contentSize = CGPointMake(0, y);
        }
        
        - (void)rearrange
        {
        [UIView animateWithDuration:0.2 animations:^{
            [self setNeedsLayout];
        }];    
        }
        

        【讨论】:

        • 这是否提供了重新排列按钮的动画?
        • 你可以用 [UIView animateWithDuration:] 方法包装重新排列方法。
        • 我不知道该怎么做。你能帮帮我吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-25
        • 1970-01-01
        • 1970-01-01
        • 2010-11-01
        • 2022-08-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多