iOS — добавление нескольких UIButton внутри UIScrollView не прокручивается плавно

Я добавляю (400+) UIButtons в UIScrollview, когда я прокручиваю simulator, он работает хорошо, но в iPad он прокручивается медленно.

Вот что я делаю.

- (void)viewDidLoad {
[scrollView setContentSize:CGSizeMake(180 * 24 , 22 * 40 + 200)];
for (int e=0; e<12; e++) {
    for(int i=0;i<24;i++)
    {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.titleLabel.font = [UIFont systemFontOfSize:12.0f];
        [btn setBackgroundColor:[UIColor colorWithRed:248.0/255.0 green:248.0/255.0 blue:248.0/255.0 alpha:1]];


        CALayer *layer = btn.layer;
        layer.cornerRadius = 5.f;
        layer.masksToBounds = YES;
        layer.borderWidth = 1.f;
        layer.borderColor = [[UIColor colorWithRed:190.0/255.0 green:190.0/255.0 blue:190.0/255.0 alpha:1] CGColor];

        CGRect rect = btn.frame;
        rect.size.height = 40;
        rect.size.width = 50;
        rect.origin.x =  100 * i;
        rect.origin.y = 40 * e;
        btn.frame = rect;

        CAGradientLayer *shineLayer = [CAGradientLayer layer];
        shineLayer.frame = layer.bounds;
        shineLayer.colors = [NSArray arrayWithObjects:
                             (id)[UIColor colorWithWhite:0.9f alpha:0.5f].CGColor,
                             (id)[UIColor colorWithWhite:0.9f alpha:0.7f].CGColor,
                             (id)[UIColor colorWithWhite:0.9f alpha:1.f].CGColor,
                             (id)[UIColor colorWithWhite:0.9f alpha:1.f].CGColor,
                             (id)[UIColor colorWithWhite:0.9f alpha:1.f].CGColor,nil];
        [layer addSublayer:shineLayer];

        UILabel *lblDes = [[UILabel alloc] initWithFrame:CGRectMake(0,0,50,40)];
        lblDes.backgroundColor = [UIColor clearColor];
        lblDes.numberOfLines = 3;
        lblDes.textColor = [UIColor colorWithRed:4.0/255.0 green:106.0/255.0 blue:200.0/255.0 alpha:1];
        lblDes.textAlignment = UITextAlignmentCenter;
        lblDes.text = @"adf";
        lblDes.tag = -1;
        lblDes.font = [UIFont systemFontOfSize:11.f];

        [btn addSubview:lblDes];
        [scrollView addSubview:btn];
    }
}
[super viewDidLoad];  // Do any additional setup after loading the view, typically from a nib. }

person heaven    schedule 16.10.2012    source источник
comment
Симулятор iOS работает быстрее, чем реальное устройство, потому что использует ресурсы компьютера.   -  person Mutawe    schedule 16.10.2012
comment
Как объяснил Йоссеф, вы не можете сравнивать скорость симулятора со скоростью вашего устройства. Симулятор не замедляется, чтобы имитировать iPad! Поэтому очень важно протестировать все также на устройстве. Мне действительно интересно, действительно ли необходимо добавить 400+ UIButtons на экран, что за этим стоит?   -  person NDY    schedule 16.10.2012
comment
Спасибо, я вижу это, но я не знаю, как мне быть?   -  person heaven    schedule 16.10.2012


Ответы (2)


Симулятор iOS работает на Mac, что намного быстрее, чем на реальном устройстве.

Все зависит от Ваших требований (зачем Вам столько кнопок),

Я бы предложил добавить UIView как subview, а потом в drawRect — рисовать нужные вещи. Затем вы можете использовать распознаватель жестов, чтобы узнать место, где пользователь нажал. (согласно tdubik)

Другим решением может быть tableView. (у которого есть возможность повторно использовать ячейки. Вы можете добавить кнопку в каждую ячейку).

Если tableView - это не то, что вы ищете, а drawRect слишком прост (поскольку он будет без эффектов выбора) - у вас может быть один скрытый UIButton, который (в выделенном состоянии) затем может быть размещен соответственно там, где пользователь коснулся и удален, когда пользователь удаляет касания с экрана.

ИЗМЕНИТЬ

При использовании drawrect — затем вы можете добавить распознаватель жестов для подвида, в котором элементы рисуются с помощью drawrect:

CustomViewClass *mView = [CustomViewClass alloc] init];

...

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]
    initWithTarget:self action:@selector(handleTap:)];

singleTap.delegate = self;

singleTap.numberOfTapsRequired = 1;

singleTap.numberOfTouchesRequired = 1;

[mView addGestureRecognizer:singleTap];

а потом :

- (void)handleTap:(UITapGestureRecognizer *)tap
{
    CGPoint mPoint = [tap locationInView:tap.view];

    int mOffset = 0; //beginning offset where buttons will start.

    for(int i = 0; i < 20; i++) //how many rows of buttons? 20? 
    { 
        mOffset += 20; //your custom drawn button height + offset from previous button

        if(mPoint.y < mOffset) //now check - if y tapped position is lower than current button.y + its height, then we know what button we tapped.
        {
            //do something - we found button row!!
            break;
        }
    }

    mOffset = 0; //beginning x offset

    for(int i = 0; i < 20; i++) //how many columns buttons? 20? 
    { 
        mOffset += 20; //your custom drawn button width + offset from previous button

        if(mPoint.x < mOffset) //now check - if x tapped position is lower than current button.x + its width, then we know what button we tapped.
        {
            //do something - we found button column!! at this point we know which button was tapped.
            break;
        }
    }
}

Если у вас есть двухмерный массив кнопок, добавьте такую ​​же проверку для координат x.

person Guntis Treulands    schedule 16.10.2012
comment
Я использую drawRect для рисования прямоугольника и хочу создать на нем события как [button addTarget: self action: @ selector (btnPlay) forControlEvents: UIControlEventTouchUpInside]; Как это сделать - person heaven; 17.10.2012
comment
CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(контекст, 2.0); CGContextSetStrokeColorWithColor(контекст, [UIColor colorWithRed:190,0/255,0 зеленый:190,0/255,0 синий:190,0/255,0 альфа:1].CGColor); Прямоугольник CGRect = CGRectMake(50,0,60,40); CGContextAddRect(контекст, прямоугольник); CGContextStrokePath (контекст); - person heaven; 17.10.2012
comment
Вас интересует только вызов функции по нажатию соответствующей кнопки? - person Guntis Treulands; 17.10.2012
comment
Нажмите и нарисуйте прямоугольник, как кнопку. - person heaven; 17.10.2012
comment
Уважаемый Treulands, можете ли вы помочь с этой проблемой... это код для меня -› mediafire.com/?t5xj3nz9yyr2d8d< /а> - person heaven; 17.10.2012
comment
Большое спасибо за вашу помощь, еще одна вещь, как можно присвоить тег каждому прямоугольнику, поэтому мне придется вызывать тег для редактирования или удаления - person heaven; 17.10.2012
comment
Невозможно. Нужно понимать, что то, что сделано в drawRect — это одна большая куча артов. Когда нарисовано, это в основном изображение. Вам нужно перерисовать снова с необходимыми изменениями, чтобы что-то изменить. Вы можете сохранить координаты в массиве, чтобы вам было легче узнать, какой элемент следует изменить или что-то в этом роде. Но, как было сказано ранее - если вам удастся выполнить все ваши требования в drawrect - это будет работать ооочень гладко!!! - person Guntis Treulands; 17.10.2012

Профилируйте свое приложение в инструментах, чтобы убедиться, что именно кнопки являются причиной медлительности.

Вместо UIButton создайте производные классы UIView с установленным распознавателем жестов или просто UIControl. Лучшим подходом будет рисовать ваши представления с помощью метода drawRect.

person Tomasz Dubik    schedule 16.10.2012
comment
Я не понимаю, что вы имеете в виду, можете ли вы привести пример увеличения скорости прокрутки на iPad? - person heaven; 16.10.2012
comment
Как предложил tdubik. Вы должны профилировать свое приложение. Однако в вашем коде ясно видно, что память не управляется должным образом. Вы должны написать [lblDes release]; btn = nil; после добавления btn к scrollview. - person Hemang; 16.10.2012