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;
}

