Как сохранить повернутый UIView внутри другого UIView? (кадр не может быть использован) - PullRequest
3 голосов
/ 02 сентября 2011

Я хочу иметь подвижный / масштабируемый / вращающийся вид внутри другого вида. Внутренний вид может выходить за рамки внешнего вида, но я хочу сохранить его часть во внешнем, чтобы не потерять внутренний вид.

Я упростил проблему в этом проекте xcode https://github.com/nextorlg/Intersection.

Если бы внутренний вид был только подвижным и масштабируемым, проблема была бы уже решена, но когда внутренний вид поворачивает это решение, это не хорошо, потому что кадр содержит вид, но это не сам вид.

При каждом преобразовании, выполняемом для внутреннего вида, я использую эту функцию для проверки новой позиции вида. Если она недействительна, я возвращаю последнее преобразование (это код подвижного вида https://github.com/nextorlg/Intersection/blob/master/intersec/MovableView.m)

-(BOOL) validInset {
    CGRect outerLimit = CGRectMake(0, 0, self.superview.frame.size.width, self.superview.frame.size.height);
    CGRect intersectionRect = CGRectIntersection(self.frame, outerLimit);
    NSLog(@"self.frame:%f,%f,%f,%f", self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
    NSLog(@"outer.frame:%f,%f,%f,%f", outerLimit.origin.x, outerLimit.origin.y, outerLimit.size.width, outerLimit.size.height);
    NSLog(@"intersec.frame:%f,%f,%f,%f", intersectionRect.origin.x, intersectionRect.origin.y, intersectionRect.size.width, intersectionRect.size.height);
    NSLog(@"========================");
    if ( CGRectIsNull(intersectionRect) ||
         intersectionRect.size.width < INSET ||
         intersectionRect.size.height < INSET ) {
         return NO;
    }
    else {
        return YES;
    }
}

Вопрос в том, как я могу быть уверен, что внутренний вид не будет потерян за внешним видом, когда первый повернут на несколько (например, 45) градусов и утащен в угол?

Один комментарий, я хочу оставить только несколько пикселей внутри внешнего вида, потому что внутренний вид может быть больше (масштабирован), чем внешний.

Я рекомендую вам загрузить и запустить проект, чтобы лучше понять проблему, трудно понять это, просто прочитав это.

Спасибо!

1 Ответ

1 голос
/ 07 сентября 2011

Как вы сказали, ваш метод будет работать нормально только тогда, когда внутренний вид не вращается.

Самый простой способ, который я знаю для решения вашей проблемы, - это просто проверить, находится ли центр или вершина одного из представлений внутри другого.

-(BOOL) validInset {
    // Get the vertices of A (outerLimit)
    CGRect outerLimit = self.superview.bounds;
    CGPoint pointA[] = {
        CGPointMake(outerLimit.origin.x,   outerLimit.origin.y    ),
        CGPointMake(outerLimit.size.width, outerLimit.origin.y    ),
        CGPointMake(outerLimit.size.width, outerLimit.size.height ),
        CGPointMake(outerLimit.origin.x,   outerLimit.size.height )};
    // Adjust outerLimit's borders
    pointA[0].x += INSET, pointA[0].y += INSET;
    pointA[1].x -= INSET, pointA[1].y += INSET;
    pointA[2].x -= INSET, pointA[2].y -= INSET;
    pointA[3].x += INSET, pointA[3].y -= INSET;
    // Get the vertices of B (innerView)
    CGRect innerView = self.bounds;
    CGPoint pointB[] = {
        CGPointMake(innerView.origin.x,   innerView.origin.y    ),
        CGPointMake(innerView.size.width, innerView.origin.y    ),
        CGPointMake(innerView.size.width, innerView.size.height ),
        CGPointMake(innerView.origin.x,   innerView.size.height )};
    // Test if the center of B is inside A or vice versa
    CGPoint center, converted;
    center = CGPointMake(pointB[0].x + (pointB[1].x - pointB[0].x)/2, pointB[0].y + (pointB[2].y - pointB[0].y)/2);
    if( converted = [self convertPoint:center toView:self.superview],
        converted.x >= pointA[0].x && 
        converted.x <= pointA[1].x &&
        converted.y >= pointA[0].y &&
        converted.y <= pointA[2].y ) return YES;
    center = CGPointMake(pointA[0].x + (pointA[1].x - pointA[0].x)/2, pointA[0].y + (pointA[2].y - pointA[0].y)/2);
    if( converted = [self convertPoint:center toView:self.superview],
        converted.x >= pointA[0].x && 
        converted.x <= pointA[1].x &&
        converted.y >= pointA[0].y &&
        converted.y <= pointA[2].y ) return YES;
    // Test if vertices of B are inside A or vice versa
    for (int i = 0; i < 4; i++) {
        if( converted = [self convertPoint:pointB[i] toView:self.superview],
            converted.x >= pointA[0].x && 
            converted.x <= pointA[1].x &&
            converted.y >= pointA[0].y &&
            converted.y <= pointA[2].y ) return YES;
        if( converted = [self.superview convertPoint:pointA[i] toView:self],
            converted.x >= pointB[0].x && 
            converted.x <= pointB[1].x &&
            converted.y >= pointB[0].y &&
            converted.y <= pointB[2].y ) return YES;
    }
    return NO;
}

Этот код поможет справиться с преобразованиями, которые вы используете в своем примере, но это не универсальный ответ.

Ответ на этот вопрос, не связанный с iphone, найден здесь .

И вы также можете прочитать некоторые сведения о пересечении прямоугольника и точки здесь .

редактирование:

Для преобразований, которые можно применить к UIView, для проверки вершин и центра будет достаточно для большинства случаев.

Два известных исключения :

  • при ч 1 <ч <sub>2 / 2 и ш 1 / 2> ш 2 (или ч 2 1 / 2 и ш 2 / 2> ш 1 ),
  • при 2 * ш 2 <ч <sub>2 / 2 и r 1 > ш 2 (или 2 * ш 1 1 / 2 и r 2 > w 1 );

, где

  • r = расстояние между центром UIView и вершиной;
  • w = длина самой короткой стороны UIView;
  • h = длина самой длинной стороны UIView.

Если вы столкнулись с одним из этих случаев, вам следует использовать другой метод, например, тот, который указан в первой ссылке .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...