似乎很多人已经触及了重叠MKAnnotation视图的问题,并在缩放结束时和viewdidload上优雅地展开了它们。所以我想我只是想咬紧牙关并开出一个解决方案,但在此之前,我想在算法上提出建议。以前有关此主题的帖子没有提供可行的解决方案:
ios sdk MKMapView overlapping pins? Laying out overlapping rectangles
还有更多......
所以我想到的功能是这样的:(注意所有的CGRects都是相同的大小)
-(NSArray *)spreadOutTheseViews:(NSArray *)arrayofCGRects{
////////////////////////////////////
//find out who overlaps with who..
////////////////////////////////////
NSMutableArray *arrayOfArraysOfRects = [[NSMutableArray alloc] init];
// 1. make an array to let you know which Rects have already been added to one of the sets
int n = (int)[arrayofCGRects count];
NSMutableArray *addedAlready = [[NSMutableArray alloc] init];
for (id obj in arrayofCGRects ) {
[addedAlready addObject:@0];
}
// 2. go through and add them if they overlap
for (int i=0; i<[arrayofCGRects count]; i++) {
if ([[addedAlready objectAtIndex:i] isEqualToValue:@(0)]) {
CGRect rect1 = [[arrayOfArraysOfRects objectAtIndex:i] CGRectValue];
[arrayOfArraysOfRects addObject:[[NSMutableArray alloc] initWithObjects:@(i), nil]];
[addedAlready insertObject:@(1) atIndex:i];
for (int j=0; j<[arrayofCGRects count]; j++){
if (i!=j && [[addedAlready objectAtIndex:j] isEqualToValue:@(0)] ) {
CGRect rect2 = [[arrayOfArraysOfRects objectAtIndex:j] CGRectValue];
if (CGRectIntersectsRect(rect1,rect2)){
// check if they are overlapping, if so, add it to
[[arrayOfArraysOfRects lastObject] addObject:@(j)];
[addedAlready insertObject:@(1) atIndex:j];
}
}
}
}
}
NSMutableArray *arrayofCGPoints = [[NSMutableArray alloc] init];
//3. now that we have "clusters" of overlapping rects.. push them away from each other..
for(NSArray *indexArray in arrayOfArraysOfRects){
if ([indexArray count]==1){
// just simply add the CGPoint
CGRect rect = [[arrayofCGRects objectAtIndex:(NSInteger)[indexArray firstObject]] CGRectValue];
[arrayofCGPoints addObject:[NSValue valueWithCGPoint:rect.origin] ];
}else{
// heart of the algo..
// Idea 1: get the average of the CGPoints to find the center of all of them, then find a ring with a specific radius that we can put them all on. Note this is a packing problem that I really dont have a better solution for..
}
}
return arrayofCGPoints;
}
非常感谢任何帮助..
答案 0 :(得分:0)
嗯,这不是最漂亮的解决方案..但我现在有一些工作,万一有人觉得这很有用..如果你有一个更优雅的解决方案,还请发帖!
-(NSArray *)spreadOutTheseViews:(NSArray *)arrayofCGRects{
bool doAnyOverlapStill = true;
int counter=0;
NSMutableArray *newArrayOfCGRects = [[NSMutableArray alloc] initWithArray:arrayofCGRects];
while (doAnyOverlapStill) {
NSLog([NSString stringWithFormat:@"number of iters %d",counter]);
for (int i=0; i<[arrayofCGRects count]; i++) {
CGRect rect1 = [[newArrayOfCGRects objectAtIndex:i] CGRectValue];
for (int j=0; j<=i; j++){
if (i!=j) {
CGRect rect2 = [[newArrayOfCGRects objectAtIndex:j] CGRectValue];
bool intersect = CGRectIntersectsRect(rect1,rect2);
if (intersect){
if (counter%4==0) {
// LEFT
NSLog(@"LEFT");
// which ever one is on the left, move it further to the left
double neededDistanceAdjustment = 5+MAX(rect1.size.width,rect2.size.width) - fabsf(rect2.origin.x - rect1.origin.x);
if (rect1.origin.x < rect2.origin.x) {
// move rect 1 left (subtract)
rect1.origin.x -= neededDistanceAdjustment;
[newArrayOfCGRects removeObjectAtIndex:i];
[newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect1] atIndex:i];
}else{
// move rect 2 left (subtract)
rect2.origin.x -= neededDistanceAdjustment;
[newArrayOfCGRects removeObjectAtIndex:j];
[newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect2] atIndex:j];
}
}else if (counter%4==1) {
// UP
NSLog(@"UP");
double neededDistanceAdjustment = 5+MAX(rect1.size.height,rect2.size.height) - fabsf(rect2.origin.y - rect1.origin.y);
if (rect1.origin.y < rect2.origin.y) {
// move rect 1 up (subtract)
rect1.origin.y -= neededDistanceAdjustment;
[newArrayOfCGRects removeObjectAtIndex:i];
[newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect1] atIndex:i];
}else{
// move rect 2 up (subtract)
rect2.origin.y -= neededDistanceAdjustment;
[newArrayOfCGRects removeObjectAtIndex:j];
[newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect2] atIndex:j];
}
}else if (counter%4==2) {
//RIGHT
NSLog(@"RIGHT");
double neededDistanceAdjustment = 5+MAX(rect1.size.width,rect2.size.width) - fabsf(rect2.origin.x - rect1.origin.x);
if (rect1.origin.x > rect2.origin.x) {
// move rect 1 right (add)
rect1.origin.y += neededDistanceAdjustment;
[newArrayOfCGRects removeObjectAtIndex:i];
[newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect1] atIndex:i];
}else{
// move rect 2 right (add)
rect2.origin.y += neededDistanceAdjustment;
[newArrayOfCGRects removeObjectAtIndex:j];
[newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect2] atIndex:j];
}
}else if (counter%4==3) {
// DOWN
NSLog(@"DOWN");
double neededDistanceAdjustment = 5+MAX(rect1.size.height,rect2.size.height) - fabsf(rect2.origin.y - rect1.origin.y);
if (rect1.origin.y > rect2.origin.y) {
// move rect 1 down (add)
rect1.origin.y += neededDistanceAdjustment;
[newArrayOfCGRects removeObjectAtIndex:i];
[newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect1] atIndex:i];
}else{
// move rect 2 down (add)
rect2.origin.y += neededDistanceAdjustment;
[newArrayOfCGRects removeObjectAtIndex:j];
[newArrayOfCGRects insertObject:[NSValue valueWithCGRect:rect2] atIndex:j];
}
}
// update newArrayOfCGRects
counter++;
}
}
}
}
if (counter>100) {
NSLog(@"error!!");
return arrayofCGRects;
}
doAnyOverlapStill = [self doRectsOverlap:newArrayOfCGRects];
if (!doAnyOverlapStill) {
return newArrayOfCGRects;
}
}
return arrayofCGRects;
}