LinkAccessibilityHelperTest.java revision 7c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14ad
1d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam/* 2d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * Copyright (C) 2016 The Android Open Source Project 3d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * 4d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * Licensed under the Apache License, Version 2.0 (the "License"); 5d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * you may not use this file except in compliance with the License. 6d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * You may obtain a copy of the License at 7d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * 8d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * http://www.apache.org/licenses/LICENSE-2.0 9d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * 10d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * Unless required by applicable law or agreed to in writing, software 11d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * distributed under the License is distributed on an "AS IS" BASIS, 12d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * See the License for the specific language governing permissions and 14d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * limitations under the License. 15d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam */ 16d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 17d832154e333a3a45b5faecd518b664ddd297183cMaurice Lampackage com.android.setupwizardlib.test; 18d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 19d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.graphics.Rect; 20d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.os.Bundle; 217c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lamimport android.support.v4.text.BidiFormatter; 22d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 23d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.support.v4.widget.ExploreByTouchHelper; 24d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.test.AndroidTestCase; 25d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.test.suitebuilder.annotation.SmallTest; 26d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.text.SpannableStringBuilder; 27059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lamimport android.util.DisplayMetrics; 28059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lamimport android.util.TypedValue; 297c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lamimport android.view.View; 30d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.view.accessibility.AccessibilityEvent; 31d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport android.widget.TextView; 32d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 33d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport com.android.setupwizardlib.span.LinkSpan; 34d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport com.android.setupwizardlib.util.LinkAccessibilityHelper; 35d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 36d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport java.util.ArrayList; 37d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport java.util.Collections; 38d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamimport java.util.List; 39d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 40d832154e333a3a45b5faecd518b664ddd297183cMaurice Lampublic class LinkAccessibilityHelperTest extends AndroidTestCase { 41d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 427c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam private static final LinkSpan LINK_SPAN = new LinkSpan("foobar"); 437c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 44d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam private TextView mTextView; 45d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam private TestLinkAccessibilityHelper mHelper; 46d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 47059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam private DisplayMetrics mDisplayMetrics; 48059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam 49d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @SmallTest 50d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void testGetVirtualViewAt() { 517c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(); 52059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam final int virtualViewId = mHelper.getVirtualViewAt(dp2Px(15), dp2Px(10)); 53d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam assertEquals("Virtual view ID should be 1", 1, virtualViewId); 54d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 55d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 56d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @SmallTest 57d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void testGetVirtualViewAtHost() { 587c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(); 59059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam final int virtualViewId = mHelper.getVirtualViewAt(dp2Px(100), dp2Px(100)); 60d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam assertEquals("Virtual view ID should be INVALID_ID", 61d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam ExploreByTouchHelper.INVALID_ID, virtualViewId); 62d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 63d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 64d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @SmallTest 65d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void testGetVisibleVirtualViews() { 667c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(); 67d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam List<Integer> virtualViewIds = new ArrayList<>(); 68d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam mHelper.getVisibleVirtualViews(virtualViewIds); 69d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 70d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam assertEquals("VisibleVirtualViews should be [1]", 71d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam Collections.singletonList(1), virtualViewIds); 72d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 73d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 74d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @SmallTest 75d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void testOnPopulateEventForVirtualView() { 767c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(); 77d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam AccessibilityEvent event = AccessibilityEvent.obtain(); 78d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam mHelper.onPopulateEventForVirtualView(1, event); 79d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 80d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam // LinkSpan is set on substring(1, 2) of "Hello world" --> "e" 81d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam assertEquals("LinkSpan description should be \"e\"", 82d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam "e", event.getContentDescription().toString()); 83d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 84d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam event.recycle(); 85d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 86d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 87d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @SmallTest 88d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void testOnPopulateEventForVirtualViewHost() { 897c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(); 90d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam AccessibilityEvent event = AccessibilityEvent.obtain(); 91d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam mHelper.onPopulateEventForVirtualView(ExploreByTouchHelper.INVALID_ID, event); 92d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 93d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam assertEquals("Host view description should be \"Hello world\"", "Hello world", 94d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam event.getContentDescription().toString()); 95d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 96d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam event.recycle(); 97d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 98d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 99d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @SmallTest 100d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void testOnPopulateNodeForVirtualView() { 1017c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(); 102d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 103d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam mHelper.onPopulateNodeForVirtualView(1, info); 104d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 105d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam assertEquals("LinkSpan description should be \"e\"", 106d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam "e", info.getContentDescription().toString()); 107d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam assertTrue("LinkSpan should be focusable", info.isFocusable()); 108d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam assertTrue("LinkSpan should be clickable", info.isClickable()); 109d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam Rect bounds = new Rect(); 110d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam info.getBoundsInParent(bounds); 111059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam assertEquals("LinkSpan bounds should be (10.5dp, 0dp, 18.5dp, 20.5dp)", 112059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam new Rect(dp2Px(10.5f), dp2Px(0f), dp2Px(18.5f), dp2Px(20.5f)), bounds); 113d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 114d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam info.recycle(); 115d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 116d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 117cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam @SmallTest 118cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam public void testNullLayout() { 1197c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(); 120cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam // Setting the padding will cause the layout to be null-ed out. 121cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam mTextView.setPadding(1, 1, 1, 1); 122cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam 123cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 124cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam mHelper.onPopulateNodeForVirtualView(0, info); 125cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam 126cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam Rect bounds = new Rect(); 127cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam info.getBoundsInParent(bounds); 128cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam assertEquals("LinkSpan bounds should be (0, 0, 1, 1)", 129cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam new Rect(0, 0, 1, 1), bounds); 130cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam 131cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam info.recycle(); 132cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam } 133cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam 13404eecdd42f0bc9751825f9f21131a59852256278Maurice Lam @SmallTest 13504eecdd42f0bc9751825f9f21131a59852256278Maurice Lam public void testRtlLayout() { 13604eecdd42f0bc9751825f9f21131a59852256278Maurice Lam SpannableStringBuilder ssb = new SpannableStringBuilder("מכונה בתרגום"); 1377c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam ssb.setSpan(LINK_SPAN, 1, 2, 0 /* flags */); 1387c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(ssb); 13904eecdd42f0bc9751825f9f21131a59852256278Maurice Lam 14004eecdd42f0bc9751825f9f21131a59852256278Maurice Lam AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 14104eecdd42f0bc9751825f9f21131a59852256278Maurice Lam mHelper.onPopulateNodeForVirtualView(1, info); 14204eecdd42f0bc9751825f9f21131a59852256278Maurice Lam 14304eecdd42f0bc9751825f9f21131a59852256278Maurice Lam assertEquals("LinkSpan description should be \"כ\"", 14404eecdd42f0bc9751825f9f21131a59852256278Maurice Lam "כ", info.getContentDescription().toString()); 14504eecdd42f0bc9751825f9f21131a59852256278Maurice Lam Rect bounds = new Rect(); 14604eecdd42f0bc9751825f9f21131a59852256278Maurice Lam info.getBoundsInParent(bounds); 1477c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam assertEquals("LinkSpan bounds should be (481.5dp, 0dp, 489.5dp, 20.5dp)", 1487c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam new Rect(dp2Px(481.5f), dp2Px(0f), dp2Px(489.5f), dp2Px(20.5f)), bounds); 1497c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 1507c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam info.recycle(); 1517c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam } 1527c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 1537c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam @SmallTest 1547c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam public void testMultilineLink() { 1557c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam SpannableStringBuilder ssb = new SpannableStringBuilder( 1567c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " 1577c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam + "Praesent accumsan efficitur eros eu porttitor."); 1587c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam ssb.setSpan(LINK_SPAN, 51, 74, 0 /* flags */); 1597c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(ssb); 1607c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 1617c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 1627c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mHelper.onPopulateNodeForVirtualView(51, info); 1637c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 1647c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam assertEquals("LinkSpan description should match the span", 1657c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam "elit. Praesent accumsan", info.getContentDescription().toString()); 1667c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam Rect bounds = new Rect(); 1677c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam info.getBoundsInParent(bounds); 1687c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam assertEquals("LinkSpan bounds should match first line of the span", 1697c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam new Rect(dp2Px(343f), dp2Px(0f), dp2Px(500f), dp2Px(19.5f)), bounds); 1707c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 1717c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam info.recycle(); 1727c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam } 1737c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 1747c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam @SmallTest 1757c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam public void testRtlMultilineLink() { 1767c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam String iwLoremIpsum = "אחר על רביעי אקטואליה. לוח דת אחרות המקובל רומנית, מיזמים מועמדים " 1777c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam + "האנציקלופדיה בה צ'ט. מתן מה שנורו לערוך ייִדיש, בקר או החול אנתרופולוגיה, עוד " 1787c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam + "דפים המחשב מיזמים ב."; 1797c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam SpannableStringBuilder ssb = new SpannableStringBuilder(iwLoremIpsum); 1807c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam ssb.setSpan(LINK_SPAN, 50, 100, 0 /* flags */); 1817c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(ssb); 1827c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 1837c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 1847c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mHelper.onPopulateNodeForVirtualView(50, info); 1857c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 1867c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam assertEquals("LinkSpan description should match the span", 1877c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam iwLoremIpsum.substring(50, 100), 1887c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam info.getContentDescription().toString()); 1897c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam Rect bounds = new Rect(); 1907c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam info.getBoundsInParent(bounds); 1917c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam assertEquals("LinkSpan bounds should match the first line of the span", 1927c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam new Rect(dp2Px(0f), dp2Px(0f), dp2Px(150f), dp2Px(19.5f)), bounds); 19304eecdd42f0bc9751825f9f21131a59852256278Maurice Lam 19404eecdd42f0bc9751825f9f21131a59852256278Maurice Lam info.recycle(); 19504eecdd42f0bc9751825f9f21131a59852256278Maurice Lam } 19604eecdd42f0bc9751825f9f21131a59852256278Maurice Lam 1977c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam @SmallTest 1987c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam public void testBidiMultilineLink() { 1997c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam String iwLoremIpsum = "אחר על רביעי אקטואליה. לוח דת אחרות המקובל רומנית, מיזמים מועמדים " 2007c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam + "האנציקלופדיה בה צ'ט. מתן מה שנורו לערוך ייִדיש, בקר או החול אנתרופולוגיה, עוד " 2017c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam + "דפים המחשב מיזמים ב."; 2027c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam BidiFormatter formatter = BidiFormatter.getInstance(false /* rtlContext */); 2037c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam SpannableStringBuilder ssb = new SpannableStringBuilder(); 2047c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam ssb.append("hello ").append(formatter.unicodeWrap(iwLoremIpsum)).append(" world"); 2057c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam ssb.setSpan(LINK_SPAN, 2067c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam "hello ".length() + 2, // Add two for the characters added by BidiFormatter 2077c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam "hello ".length() + 2 + iwLoremIpsum.length(), 2087c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 0 /* flags */); 2097c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(ssb); 2107c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 2117c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 2127c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mHelper.onPopulateNodeForVirtualView("hello ".length() + 2, info); 2137c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 2147c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam assertEquals("LinkSpan description should match the span", 2157c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam iwLoremIpsum, 2167c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam info.getContentDescription().toString()); 2177c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam Rect bounds = new Rect(); 2187c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam info.getBoundsInParent(bounds); 2197c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam assertEquals("LinkSpan bounds should match the first line of the span", 2207c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam new Rect(dp2Px(491.5f), dp2Px(0f), dp2Px(500f), dp2Px(19.5f)), bounds); 2217c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 2227c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam info.recycle(); 2237c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam } 2247c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 2257c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam private void initTextView() { 2267c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam SpannableStringBuilder ssb = new SpannableStringBuilder("Hello world"); 2277c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam ssb.setSpan(LINK_SPAN, 1, 2, 0 /* flags */); 2287c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam initTextView(ssb); 2297c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam } 2307c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 2317c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam private void initTextView(CharSequence text) { 2327c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mTextView = new TextView(getContext()); 2337c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mTextView.setSingleLine(false); 2347c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mTextView.setText(text); 2357c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); 2367c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mHelper = new TestLinkAccessibilityHelper(mTextView); 2377c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 2387c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam int measureExactly500dp = View.MeasureSpec.makeMeasureSpec(dp2Px(500), 2397c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam View.MeasureSpec.EXACTLY); 2407c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mTextView.measure(measureExactly500dp, measureExactly500dp); 2417c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam mTextView.layout(dp2Px(0), dp2Px(0), dp2Px(500), dp2Px(500)); 2427c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam } 2437c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam 244059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam private int dp2Px(float dp) { 245059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam if (mDisplayMetrics == null) { 246059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam mDisplayMetrics = getContext().getResources().getDisplayMetrics(); 247059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam } 248059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mDisplayMetrics); 249059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam } 250059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam 251d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam private static class TestLinkAccessibilityHelper extends LinkAccessibilityHelper { 252d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 253d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public TestLinkAccessibilityHelper(TextView view) { 254d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam super(view); 255d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 256d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 257d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @Override 258d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public int getVirtualViewAt(float x, float y) { 259d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam return super.getVirtualViewAt(x, y); 260d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 261d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 262d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @Override 263d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void getVisibleVirtualViews(List<Integer> virtualViewIds) { 264d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam super.getVisibleVirtualViews(virtualViewIds); 265d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 266d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 267d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @Override 268d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) { 269d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam super.onPopulateEventForVirtualView(virtualViewId, event); 270d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 271d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 272d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @Override 273d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public void onPopulateNodeForVirtualView(int virtualViewId, 274d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam AccessibilityNodeInfoCompat info) { 275d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam super.onPopulateNodeForVirtualView(virtualViewId, info); 276d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 277d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam 278d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam @Override 279d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam public boolean onPerformActionForVirtualView(int virtualViewId, int action, 280d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam Bundle arguments) { 281d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam return super.onPerformActionForVirtualView(virtualViewId, action, arguments); 282d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 283d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam } 284d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam} 285