Android TV FocusFinder寻焦流程分析(二)

2019-02-20  本文已影响0人  朝花夕拾_llp

寻焦算法分析:

// source = focusedRect
// rect1 = mOtherRect
// rect2 = mBestCandidateRect
//以向左寻焦为例
boolean isBetterCandidate(int direction, Rect source, Rect rect1, Rect rect2) {
    // to be a better candidate, need to at least be a candidate in the first
    // place :)
    //1.判断rect1是否在source左边
    if (!isCandidate(source, rect1, direction)) {
        return false;
    }

    // we know that rect1 is a candidate.. if rect2 is not a candidate,
    // rect1 is better
    //2.判断react2是否在source左边,如果不是,则选择react1
    if (!isCandidate(source, rect2, direction)) {
        return true;
    }

    //3.根据方向上是否重叠和距离判断谁更合适
    // if rect1 is better by beam, it wins
    if (beamBeats(direction, source, rect1, rect2)) {
        return true;
    }
    
    //4.交换react1和react1继续比较
    // if rect2 is better, then rect1 cant' be :)
    if (beamBeats(direction, source, rect2, rect1)) {
        return false;
    }
    
    //5.继续距离上的比较
    // otherwise, do fudge-tastic comparison of the major and minor axis
    return (getWeightedDistanceFor(
                    majorAxisDistance(direction, source, rect1),
                    minorAxisDistance(direction, source, rect1))
            < getWeightedDistanceFor(
                    majorAxisDistance(direction, source, rect2),
                    minorAxisDistance(direction, source, rect2)));
}

//判断destRect在direction方向是不是候选
boolean isCandidate(Rect srcRect, Rect destRect, int direction) {
    switch (direction) {
        case View.FOCUS_LEFT:
            return (srcRect.right > destRect.right || srcRect.left >= destRect.right) 
                    && srcRect.left > destRect.left;
        case View.FOCUS_RIGHT:
            ...
    }
    ...
}

boolean beamBeats(int direction, Rect source, Rect rect1, Rect rect2) {
    final boolean rect1InSrcBeam = beamsOverlap(direction, source, rect1);
    final boolean rect2InSrcBeam = beamsOverlap(direction, source, rect2);

    //1.如果rect2在对应的方向上,或者rect1不在。则rect1不比rect2合适
    // if rect1 isn't exclusively in the src beam, it doesn't win
    if (rect2InSrcBeam || !rect1InSrcBeam) {
        return false;
    }

    // we know rect1 is in the beam, and rect2 is not

    // if rect1 is to the direction of, and rect2 is not, rect1 wins.
    // for example, for direction left, if rect1 is to the left of the source
    // and rect2 is below, then we always prefer the in beam rect1, since rect2
    // could be reached by going down.
    
    //2.如果react2和source重叠了,则react1合适
    //isToDirectionOf()判断的是两个react没有重叠,并且react2在source的左边
    if (!isToDirectionOf(direction, source, rect2)) {
        return true;
    }

    //3.如果是左右方向,react1胜出
    // for horizontal directions, being exclusively in beam always wins
    if ((direction == View.FOCUS_LEFT || direction == View.FOCUS_RIGHT)) {
        return true;
    }        

    // for vertical directions, beams only beat up to a point:
    // now, as long as rect2 isn't completely closer, rect1 wins
    // e.g for direction down, completely closer means for rect2's top
    // edge to be closer to the source's top edge than rect1's bottom edge.
    
    //4.其他方向的情况
    return (majorAxisDistance(direction, source, rect1)
            < majorAxisDistanceToFarEdge(direction, source, rect2));
}

boolean beamsOverlap(int direction, Rect rect1, Rect rect2) {
    switch (direction) {
        case View.FOCUS_LEFT:
        case View.FOCUS_RIGHT:
            return (rect2.bottom > rect1.top) && (rect2.top < rect1.bottom);
        case View.FOCUS_UP:
        case View.FOCUS_DOWN:
            return (rect2.right > rect1.left) && (rect2.left < rect1.right);
    }
    throw new IllegalArgumentException("direction must be one of "
            + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
}

boolean isToDirectionOf(int direction, Rect src, Rect dest) {
    switch (direction) {
        case View.FOCUS_LEFT:
            return src.left >= dest.right;
        case View.FOCUS_RIGHT:
           ...
    }
    ...
}

//13就是一个计算因子,direction方向上的距离在整个距离的计算中占据更大的比重
int getWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance) {
    return 13 * majorAxisDistance * majorAxisDistance
            + minorAxisDistance * minorAxisDistance;
}
image
image
上一篇 下一篇

猜你喜欢

热点阅读