FileDocCategorySizeDatePackage
FocusFinderTest.javaAPI DocAndroid 5.1 API21657Thu Mar 12 22:22:12 GMT 2015android.view

FocusFinderTest

public class FocusFinderTest extends android.test.AndroidTestCase

Fields Summary
private FocusFinderHelper
mFocusFinder
Constructors Summary
Methods Summary
private voidassertBeamBeats(int direction, android.graphics.Rect srcRect, android.graphics.Rect rect1, android.graphics.Rect rect2)


        String directionStr = validateAndGetStringFor(direction);
        String assertMsg = String.format(
                "expecting %s to beam beat %s w.r.t %s in direction %s",
                rect1, rect2, srcRect, directionStr);
        assertTrue(assertMsg, mFocusFinder.beamBeats(direction, srcRect, rect1, rect2));
    
private voidassertBeamsDontOverlap(int direction, android.graphics.Rect rect1, android.graphics.Rect rect2)

        String directionStr = validateAndGetStringFor(direction);
        String assertMsg = String.format("Expected beams not to overlap in direction %s "
                + "for rectangles %s and %s", directionStr, rect1, rect2);
        assertFalse(assertMsg, mFocusFinder.beamsOverlap(direction, rect1, rect2));
    
private voidassertBeamsOverlap(int direction, android.graphics.Rect rect1, android.graphics.Rect rect2)

        String directionStr = validateAndGetStringFor(direction);
        String assertMsg = String.format("Expected beams to overlap in direction %s "
                + "for rectangles %s and %s", directionStr, rect1, rect2);
        assertTrue(assertMsg, mFocusFinder.beamsOverlap(direction, rect1, rect2));
    
private voidassertBetterCandidate(int direction, android.graphics.Rect srcRect, android.graphics.Rect expectedBetter, android.graphics.Rect expectedWorse)
Assert that particular rect is a better focus search candidate from a source rect than another.

param
direction The direction of focus search.
param
srcRect The src rectangle.
param
expectedBetter The candidate that should be better.
param
expectedWorse The candidate that should be worse.


        String directionStr = validateAndGetStringFor(direction);
        String assertMsg = String.format(
                "expected %s to be a better focus search candidate than "
                        + "%s when searching "
                        + "from %s in direction %s",
                expectedBetter, expectedWorse, srcRect, directionStr);

        assertTrue(assertMsg,
                mFocusFinder.isBetterCandidate(direction, srcRect,
                        expectedBetter, expectedWorse));

        assertMsg = String.format(
                "expected %s to not be a better focus search candidate than "
                        + "%s when searching "
                        + "from %s in direction %s",
                expectedWorse, expectedBetter, srcRect, directionStr);

        assertFalse(assertMsg,
                mFocusFinder.isBetterCandidate(direction, srcRect,
                        expectedWorse, expectedBetter));
    
private voidassertDirectionIsCandidate(int direction, android.graphics.Rect src, android.graphics.Rect dest)

        String directionStr = validateAndGetStringFor(direction);

        final String assertMsg = String.format(
                "expected going from %s to %s in direction %s to be a valid "
                        + "focus search candidate",
                src, dest, directionStr);
        assertTrue(assertMsg, mFocusFinder.isCandidate(src, dest, direction));
    
private voidassertIsNotCandidate(int direction, android.graphics.Rect src, android.graphics.Rect dest)

        String directionStr = validateAndGetStringFor(direction);

        final String assertMsg = String.format(
                "expected going from %s to %s in direction %s to be an invalid "
                        + "focus search candidate",
                src, dest, directionStr);
        assertFalse(assertMsg, mFocusFinder.isCandidate(src, dest, direction));
    
protected voidsetUp()

        super.setUp();

        mFocusFinder = new FocusFinderHelper(FocusFinder.getInstance());
    
public voidtestAboveInBeamTrumpsSlightlyCloserOutOfBeam()

        Rect src = new Rect(0, 50, 20, 70);  // src (left, top, right, bottom)

        Rect directlyAbove = new Rect(src);
        directlyAbove.offset(0, -(1 + src.height()));

        Rect aboveLeft = new Rect(src);
        aboveLeft.offset(-(1 + src.width()), -(1 + src.height()));

        // offset directly above a little further up
        directlyAbove.offset(0, -5);
        assertBetterCandidate(View.FOCUS_UP, src, directlyAbove, aboveLeft);
    
public voidtestAboveShareEdgeEdgeOkForDirectionUp()

        final Rect src = new Rect(0, 30, 10, 40);

        final Rect dest = new Rect(src);
        dest.offset(0, -src.height());
        assertEquals(src.top, dest.bottom);

        assertDirectionIsCandidate(View.FOCUS_UP, src, dest);
    
public voidtestBeamAlwaysBeatsHoriz()

        assertBetterCandidate(View.FOCUS_RIGHT,
                //       L    T    R    B
                new Rect(0,   0,   50,  50),   // src
                new Rect(150, 0,   200, 50),   // better, (way further, but in beam)
                new Rect(60,  51,  110, 101)); // worse, even though it is closer 

        assertBetterCandidate(View.FOCUS_LEFT,
                //       L    T    R    B
                new Rect(150, 0,   200,  50),   // src
                new Rect(0,   50,  50,   50),   // better, (way further, but in beam)
                new Rect(49,  99,  149,  101)); // worse, even though it is closer 
    
public voidtestBeamsOverlapMajorAxisCloserMinorAxisFurther()
Example: going down from a thin button all the way to the left of a screen where, just below, is a very wide button, and just below that, is an equally skinny button all the way to the left. want to make sure any minor axis factor doesn't override the fact that the one below in vertical beam should be next focus

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L   T    R    B
                new Rect(0,  0,   100,  100),  // src
                new Rect(0,  100, 480,  200),  // expectedbetter
                new Rect(0,  200, 100,  300)); // expectedworse
    
public voidtestBelowNotCandidateForDirectionUp()

        assertIsNotCandidate(View.FOCUS_UP,
                new Rect(0, 30, 10, 40),  // src  (left, top, right, bottom)
                new Rect(0, 50, 10, 60));  // dest (left, top, right, bottom)
    
public voidtestCompletelyContainedNotCandidate()

        assertIsNotCandidate(
                View.FOCUS_DOWN,
                //       L  T   R   B
                new Rect(0, 0,  50, 50),
                new Rect(0, 1,  50, 49));
    
public voidtestContinaedWithCommonBottomNotCandidate()

        assertIsNotCandidate(
                View.FOCUS_DOWN,
                //       L  T   R   B
                new Rect(0, 0,  50, 50),
                new Rect(0, 1,  50, 50));
    
public voidtestDirectlyAboveTrumpsAboveLeft()

        Rect src = new Rect(0, 50, 20, 70);  // src (left, top, right, bottom)

        Rect directlyAbove = new Rect(src);
        directlyAbove.offset(0, -(1 + src.height()));

        Rect aboveLeft = new Rect(src);
        aboveLeft.offset(-(1 + src.width()), -(1 + src.height()));

        assertBetterCandidate(View.FOCUS_UP, src, directlyAbove, aboveLeft);
    
public voidtestEditContactScenarioLeftFromDiscardChangesGoesToSaveContactInLandscape()

        assertBetterCandidate(View.FOCUS_LEFT,
                //       L    T    R    B
                new Rect(357, 258, 478, 318),  // src
                new Rect(2,   258, 100, 318),  // better
                new Rect(106, 120, 424, 184)); // worse
    
public voidtestGmailReplyButtonsScenario()
Reproduce bug 1124559, drilling down to actual bug (majorAxisDistance was wrong for direction left)

        assertBetterCandidate(View.FOCUS_LEFT,
                //       L    T    R    B
                new Rect(223, 380, 312, 417),  // src
                new Rect(102, 380, 210, 417),  // better
                new Rect(111, 443, 206, 480)); // worse

        assertBeamBeats(View.FOCUS_LEFT,
            //       L    T    R    B
            new Rect(223, 380, 312, 417),  // src
            new Rect(102, 380, 210, 417),  // better
            new Rect(111, 443, 206, 480)); // worse

        assertBeamsOverlap(View.FOCUS_LEFT,
                //       L    T    R    B
                new Rect(223, 380, 312, 417),
                new Rect(102, 380, 210, 417));

        assertBeamsDontOverlap(View.FOCUS_LEFT,
                //       L    T    R    B
                new Rect(223, 380, 312, 417),
                new Rect(111, 443, 206, 480));

        assertTrue(
                "major axis distance less than major axis distance to "
                        + "far edge",
                FocusFinderHelper.majorAxisDistance(View.FOCUS_LEFT,
                        //       L    T    R    B
                        new Rect(223, 380, 312, 417),
                        new Rect(102, 380, 210, 417)) <
                FocusFinderHelper.majorAxisDistanceToFarEdge(View.FOCUS_LEFT,
                        //       L    T    R    B
                        new Rect(223, 380, 312, 417),
                        new Rect(111, 443, 206, 480)));
    
public voidtestGmailScenarioBug1203288()

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L    T    R    B
                new Rect(0,   2,   480, 82),   // src
                new Rect(344, 87,  475, 124),  // better
                new Rect(0,   130, 480, 203)); // worse
    
public voidtestGridWithTouchingEdges()
A dial pad with 9 squares arranged in a grid. no padding, so the edges are equal. see {@link android.widget.focus.LinearLayoutGrid}

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L    T    R    B
                new Rect(106, 49,  212, 192),  // src
                new Rect(106, 192, 212, 335),  // better
                new Rect(0,   192, 106, 335)); // worse

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L    T    R    B
                new Rect(106, 49,  212, 192),  // src
                new Rect(106, 192, 212, 335),  // better
                new Rect(212, 192, 318, 335)); // worse
    
public voidtestHomeShortcutScenarioBug1295354()

        assertBetterCandidate(View.FOCUS_RIGHT,
                //       L    T    R    B
                new Rect(3, 338, 77, 413),   // src
                new Rect(163, 338, 237, 413),  // better
                new Rect(83, 38, 157, 113)); // worse
    
public voidtestInBeamTrumpsOutOfBeamOverlapping()
Make sure that going down prefers views that are actually down (and not those next to but still a candidate because they are overlapping on the major axis)

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L    T    R    B
                new Rect(0,   0,   50,  50),   // src
                new Rect(0,   60,  50,  110),  // expectedbetter
                new Rect(51,  1,   101, 51)); // expectedworse
    
public voidtestIsCandidateOverlappingEdgeFromEmptyRect()

        assertDirectionIsCandidate(View.FOCUS_DOWN,
                //       L   T    R    B
                new Rect(0,  0,   0,   0),   // src
                new Rect(0,  0,   20,  1));  // candidate

        assertDirectionIsCandidate(View.FOCUS_UP,
                //       L   T    R    B
                new Rect(0,  0,   0,   0),   // src
                new Rect(0,  -1,  20,  0));  // candidate

        assertDirectionIsCandidate(View.FOCUS_LEFT,
                //       L   T    R    B
                new Rect(0,  0,   0,   0),    // src
                new Rect(-1,  0,  0,   20));  // candidate

        assertDirectionIsCandidate(View.FOCUS_RIGHT,
                //       L   T    R    B
                new Rect(0,  0,   0,   0),    // src
                new Rect(0,  0,   1,   20));  // candidate
    
public voidtestMusicPlaybackScenario()
Real scenario grabbed from song playback screen.

        assertBetterCandidate(View.FOCUS_LEFT,
                //       L    T    R    B
                new Rect(227, 185, 312, 231),   // src
                new Rect(195, 386, 266, 438),   // expectedbetter
                new Rect(124, 386, 195, 438));  // expectedworse
    
public voidtestOutOfBeamBeatsInBeamUp()


        Rect src = new Rect(0, 0, 50, 50); // (left, top, right, bottom)

        Rect aboveLeftOfBeam = new Rect(src);
        aboveLeftOfBeam.offset(-(src.width() + 1), -src.height());
        assertBeamsDontOverlap(View.FOCUS_UP, src, aboveLeftOfBeam);

        Rect aboveInBeam = new Rect(src);
        aboveInBeam.offset(0, -src.height());
        assertBeamsOverlap(View.FOCUS_UP, src, aboveInBeam);

        // in beam wins
        assertBetterCandidate(View.FOCUS_UP, src, aboveInBeam, aboveLeftOfBeam);

        // still wins while aboveInBeam's bottom edge is < out of beams' top
        aboveInBeam.offset(0, -(aboveLeftOfBeam.height() - 1));
        assertTrue("aboveInBeam.bottom > aboveLeftOfBeam.top", aboveInBeam.bottom > aboveLeftOfBeam.top);
        assertBetterCandidate(View.FOCUS_UP, src, aboveInBeam, aboveLeftOfBeam);

        // cross the threshold: the out of beam prevails
        aboveInBeam.offset(0, -1);
        assertEquals(aboveInBeam.bottom, aboveLeftOfBeam.top);
        assertBetterCandidate(View.FOCUS_UP, src, aboveLeftOfBeam, aboveInBeam);
    
public voidtestOutOfBeamOverlapBeatsOutOfBeamFurtherOnMajorAxis()
more generalized version of {@link #testMusicPlaybackScenario()}

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L    T    R    B
                new Rect(0,   0,   50,  50),   // src
                new Rect(60,  40,  110, 90),   // expectedbetter
                new Rect(60,  70,  110, 120));  // expectedworse
    
public voidtestOverlapBeamsRightLeftUpToEdge()

        final Rect rect1 = new Rect(0, 0, 20, 20);
        final Rect rect2 = new Rect(rect1);

        // just below bottom edge
        rect2.offset(0, rect1.height() - 1);
        assertBeamsOverlap(View.FOCUS_LEFT, rect1, rect2);
        assertBeamsOverlap(View.FOCUS_RIGHT, rect1, rect2);

        // at edge
        rect2.offset(0, 1);
        assertBeamsOverlap(View.FOCUS_LEFT, rect1, rect2);
        assertBeamsOverlap(View.FOCUS_RIGHT, rect1, rect2);

        // just beyond
        rect2.offset(0, 1);
        assertBeamsDontOverlap(View.FOCUS_LEFT, rect1, rect2);
        assertBeamsDontOverlap(View.FOCUS_RIGHT, rect1, rect2);

        // just below top edge
        rect2.set(rect1);
        rect2.offset(0, -(rect1.height() - 1));
        assertBeamsOverlap(View.FOCUS_LEFT, rect1, rect2);
        assertBeamsOverlap(View.FOCUS_RIGHT, rect1, rect2);

        // at top edge
        rect2.offset(0, -1);
        assertBeamsOverlap(View.FOCUS_LEFT, rect1, rect2);
        assertBeamsOverlap(View.FOCUS_RIGHT, rect1, rect2);

        // just beyond top edge
        rect2.offset(0, -1);
        assertBeamsDontOverlap(View.FOCUS_LEFT, rect1, rect2);
        assertBeamsDontOverlap(View.FOCUS_RIGHT, rect1, rect2);
    
public voidtestOverlapBeamsUpDownUpToEdge()

        final Rect rect1 = new Rect(0, 0, 20, 20);
        final Rect rect2 = new Rect(rect1);

        // just short of right edge
        rect2.offset(rect1.width() - 1, 0);
        assertBeamsOverlap(View.FOCUS_UP, rect1, rect2);
        assertBeamsOverlap(View.FOCUS_DOWN, rect1, rect2);

        // at edge
        rect2.offset(1, 0);
        assertBeamsOverlap(View.FOCUS_UP, rect1, rect2);
        assertBeamsOverlap(View.FOCUS_DOWN, rect1, rect2);

        // just beyond
        rect2.offset(1, 0);
        assertBeamsDontOverlap(View.FOCUS_UP, rect1, rect2);
        assertBeamsDontOverlap(View.FOCUS_DOWN, rect1, rect2);

        // just short of left edge
        rect2.set(rect1);
        rect2.offset(-(rect1.width() - 1), 0);
        assertBeamsOverlap(View.FOCUS_UP, rect1, rect2);
        assertBeamsOverlap(View.FOCUS_DOWN, rect1, rect2);

        // at edge
        rect2.offset(-1, 0);
        assertBeamsOverlap(View.FOCUS_UP, rect1, rect2);
        assertBeamsOverlap(View.FOCUS_DOWN, rect1, rect2);

        // just beyond edge
        rect2.offset(-1, 0);
        assertBeamsDontOverlap(View.FOCUS_UP, rect1, rect2);
        assertBeamsDontOverlap(View.FOCUS_DOWN, rect1, rect2);
    
public voidtestOverlappingBeatsNonOverlapping()

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L    T    R    B
                new Rect(0,   0,   50,  50),   // src
                new Rect(0,   40,  50,  90),   // expectedbetter
                new Rect(0,   75,  50,  125)); // expectedworse
    
public voidtestOverlappingIsCandidateWhenBothEdgesAreInDirection()

        assertDirectionIsCandidate(
                View.FOCUS_DOWN,
                //       L  T   R   B
                new Rect(0, 0,  50, 50),
                new Rect(0, 1,  50, 51));
    
public voidtestPreconditions()

        assertNotNull("focus finder instance", mFocusFinder);
    
public voidtestSameRectBeamsOverlap()

        final Rect rect = new Rect(0, 0, 20, 20);

        assertBeamsOverlap(View.FOCUS_LEFT, rect, rect);
        assertBeamsOverlap(View.FOCUS_RIGHT, rect, rect);
        assertBeamsOverlap(View.FOCUS_UP, rect, rect);
        assertBeamsOverlap(View.FOCUS_DOWN, rect, rect);
    
public voidtestSearchFromEmptyRect()

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L   T    R    B
                new Rect(0,  0,   0,   0),    // src
                new Rect(0,  0,   320, 45),   // better
                new Rect(0,  45,  320, 545)); // worse
    
public voidtestSomeCandidateBetterThanNonCandidate()
A non-candidate (even a much closer one) is always a worse choice than a real candidate.

        Rect src = new Rect(0, 0, 50, 50); // (left, top, right, bottom)

        Rect nonCandidate = new Rect(src);
        nonCandidate.offset(src.width() + 1, 0);

        assertIsNotCandidate(View.FOCUS_LEFT, src, nonCandidate);

        Rect candidate = new Rect(src);
        candidate.offset(-(4 * src.width()), 0);
        assertDirectionIsCandidate(View.FOCUS_LEFT, src, candidate);

        assertBetterCandidate(View.FOCUS_LEFT, src, candidate, nonCandidate);
    
public voidtestTopEdgeOfDestAtOrAboveTopOfSrcNotCandidateForDown()

        assertIsNotCandidate(
                View.FOCUS_DOWN,
                //       L  T   R   B
                new Rect(0, 0,  50, 50),
                new Rect(0, 0,  50, 51));
        assertIsNotCandidate(
                View.FOCUS_DOWN,
                //       L  T   R   B
                new Rect(0, 0,  50, 50),
                new Rect(0, -1, 50, 51));
    
public voidtestVerticalFocusSearchScenario()
Grabbed from {@link android.widget.focus.VerticalFocusSearchTest#testSearchFromMidLeft()}

        assertBetterCandidate(View.FOCUS_DOWN,
                //       L    T    R    B
                new Rect(0,   109, 153, 169),   // src
                new Rect(166, 169, 319, 229),  // expectedbetter
                new Rect(0,   229, 320, 289)); // expectedworse

        // failing test 4/10/2008, the values were tweaked somehow in functional
        // test...
        assertBetterCandidate(View.FOCUS_DOWN,
                //       L    T    R    B
                new Rect(0,   91, 153, 133),   // src
                new Rect(166, 133, 319, 175),  // expectedbetter
                new Rect(0,   175, 320, 217)); // expectedworse

    
private java.lang.StringvalidateAndGetStringFor(int direction)

        String directionStr = "??";
        switch(direction) {
            case View.FOCUS_UP:
                directionStr = "FOCUS_UP";
                break;
            case View.FOCUS_DOWN:
                directionStr = "FOCUS_DOWN";
                break;
            case View.FOCUS_LEFT:
                directionStr = "FOCUS_LEFT";
                break;
            case View.FOCUS_RIGHT:
                directionStr = "FOCUS_RIGHT";
                break;
            default:
                fail("passed in unknown direction, ya blewit!");
        }
        return directionStr;