Merge "Spell checking in TextViews"
This commit is contained in:
committed by
Android (Google) Code Review
commit
f874c4f934
117
api/current.txt
117
api/current.txt
@@ -184,21 +184,21 @@ package android {
|
||||
public static final class R.attr {
|
||||
ctor public R.attr();
|
||||
field public static final int absListViewStyle = 16842858; // 0x101006a
|
||||
field public static final int accessibilityEventTypes = 16843644; // 0x101037c
|
||||
field public static final int accessibilityFeedbackType = 16843646; // 0x101037e
|
||||
field public static final int accessibilityFlags = 16843648; // 0x1010380
|
||||
field public static final int accessibilityEventTypes = 16843643; // 0x101037b
|
||||
field public static final int accessibilityFeedbackType = 16843645; // 0x101037d
|
||||
field public static final int accessibilityFlags = 16843647; // 0x101037f
|
||||
field public static final int accountPreferences = 16843423; // 0x101029f
|
||||
field public static final int accountType = 16843407; // 0x101028f
|
||||
field public static final int action = 16842797; // 0x101002d
|
||||
field public static final int actionBarDivider = 16843685; // 0x10103a5
|
||||
field public static final int actionBarItemBackground = 16843686; // 0x10103a6
|
||||
field public static final int actionBarDivider = 16843684; // 0x10103a4
|
||||
field public static final int actionBarItemBackground = 16843685; // 0x10103a5
|
||||
field public static final int actionBarSize = 16843499; // 0x10102eb
|
||||
field public static final int actionBarSplitStyle = 16843666; // 0x1010392
|
||||
field public static final int actionBarSplitStyle = 16843665; // 0x1010391
|
||||
field public static final int actionBarStyle = 16843470; // 0x10102ce
|
||||
field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
|
||||
field public static final int actionBarTabStyle = 16843507; // 0x10102f3
|
||||
field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5
|
||||
field public static final int actionBarWidgetTheme = 16843681; // 0x10103a1
|
||||
field public static final int actionBarWidgetTheme = 16843680; // 0x10103a0
|
||||
field public static final int actionButtonStyle = 16843480; // 0x10102d8
|
||||
field public static final int actionDropDownStyle = 16843479; // 0x10102d7
|
||||
field public static final int actionLayout = 16843515; // 0x10102fb
|
||||
@@ -210,11 +210,11 @@ package android {
|
||||
field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
|
||||
field public static final int actionModeCutDrawable = 16843537; // 0x1010311
|
||||
field public static final int actionModePasteDrawable = 16843539; // 0x1010313
|
||||
field public static final int actionModeSelectAllDrawable = 16843642; // 0x101037a
|
||||
field public static final int actionModeSplitBackground = 16843687; // 0x10103a7
|
||||
field public static final int actionModeStyle = 16843678; // 0x101039e
|
||||
field public static final int actionModeSelectAllDrawable = 16843641; // 0x1010379
|
||||
field public static final int actionModeSplitBackground = 16843686; // 0x10103a6
|
||||
field public static final int actionModeStyle = 16843677; // 0x101039d
|
||||
field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
|
||||
field public static final int actionProviderClass = 16843667; // 0x1010393
|
||||
field public static final int actionProviderClass = 16843666; // 0x1010392
|
||||
field public static final int actionViewClass = 16843516; // 0x10102fc
|
||||
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
|
||||
field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
|
||||
@@ -226,7 +226,7 @@ package android {
|
||||
field public static final int alertDialogIcon = 16843605; // 0x1010355
|
||||
field public static final int alertDialogStyle = 16842845; // 0x101005d
|
||||
field public static final int alertDialogTheme = 16843529; // 0x1010309
|
||||
field public static final int alignmentMode = 16843638; // 0x1010376
|
||||
field public static final int alignmentMode = 16843637; // 0x1010375
|
||||
field public static final int allContactsName = 16843468; // 0x10102cc
|
||||
field public static final int allowBackup = 16843392; // 0x1010280
|
||||
field public static final int allowClearUserData = 16842757; // 0x1010005
|
||||
@@ -260,8 +260,8 @@ package android {
|
||||
field public static final int background = 16842964; // 0x10100d4
|
||||
field public static final int backgroundDimAmount = 16842802; // 0x1010032
|
||||
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
|
||||
field public static final int backgroundSplit = 16843669; // 0x1010395
|
||||
field public static final int backgroundStacked = 16843668; // 0x1010394
|
||||
field public static final int backgroundSplit = 16843668; // 0x1010394
|
||||
field public static final int backgroundStacked = 16843667; // 0x1010393
|
||||
field public static final int backupAgent = 16843391; // 0x101027f
|
||||
field public static final int baseline = 16843548; // 0x101031c
|
||||
field public static final int baselineAlignBottom = 16843042; // 0x1010122
|
||||
@@ -270,7 +270,7 @@ package android {
|
||||
field public static final int borderlessButtonStyle = 16843563; // 0x101032b
|
||||
field public static final int bottom = 16843184; // 0x10101b0
|
||||
field public static final int bottomBright = 16842957; // 0x10100cd
|
||||
field public static final int bottomChevronDrawable = 16843655; // 0x1010387
|
||||
field public static final int bottomChevronDrawable = 16843654; // 0x1010386
|
||||
field public static final int bottomDark = 16842953; // 0x10100c9
|
||||
field public static final int bottomLeftRadius = 16843179; // 0x10101ab
|
||||
field public static final int bottomMedium = 16842958; // 0x10100ce
|
||||
@@ -289,7 +289,7 @@ package android {
|
||||
field public static final int cacheColorHint = 16843009; // 0x1010101
|
||||
field public static final int calendarViewShown = 16843596; // 0x101034c
|
||||
field public static final int calendarViewStyle = 16843613; // 0x101035d
|
||||
field public static final int canRetrieveWindowContent = 16843649; // 0x1010381
|
||||
field public static final int canRetrieveWindowContent = 16843648; // 0x1010380
|
||||
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
|
||||
field public static final deprecated int capitalize = 16843113; // 0x1010169
|
||||
field public static final int centerBright = 16842956; // 0x10100cc
|
||||
@@ -318,18 +318,18 @@ package android {
|
||||
field public static final int codes = 16843330; // 0x1010242
|
||||
field public static final int collapseColumns = 16843083; // 0x101014b
|
||||
field public static final int color = 16843173; // 0x10101a5
|
||||
field public static final int colorActivatedHighlight = 16843674; // 0x101039a
|
||||
field public static final int colorActivatedHighlight = 16843673; // 0x1010399
|
||||
field public static final int colorBackground = 16842801; // 0x1010031
|
||||
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
|
||||
field public static final int colorFocusedHighlight = 16843673; // 0x1010399
|
||||
field public static final int colorFocusedHighlight = 16843672; // 0x1010398
|
||||
field public static final int colorForeground = 16842800; // 0x1010030
|
||||
field public static final int colorForegroundInverse = 16843270; // 0x1010206
|
||||
field public static final int colorLongPressedHighlight = 16843672; // 0x1010398
|
||||
field public static final int colorMultiSelectHighlight = 16843675; // 0x101039b
|
||||
field public static final int colorPressedHighlight = 16843671; // 0x1010397
|
||||
field public static final int columnCount = 16843635; // 0x1010373
|
||||
field public static final int colorLongPressedHighlight = 16843671; // 0x1010397
|
||||
field public static final int colorMultiSelectHighlight = 16843674; // 0x101039a
|
||||
field public static final int colorPressedHighlight = 16843670; // 0x1010396
|
||||
field public static final int columnCount = 16843634; // 0x1010372
|
||||
field public static final int columnDelay = 16843215; // 0x10101cf
|
||||
field public static final int columnOrderPreserved = 16843636; // 0x1010374
|
||||
field public static final int columnOrderPreserved = 16843635; // 0x1010373
|
||||
field public static final int columnWidth = 16843031; // 0x1010117
|
||||
field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
|
||||
field public static final int completionHint = 16843122; // 0x1010172
|
||||
@@ -383,11 +383,11 @@ package android {
|
||||
field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
|
||||
field public static final int drawable = 16843161; // 0x1010199
|
||||
field public static final int drawableBottom = 16843118; // 0x101016e
|
||||
field public static final int drawableEnd = 16843677; // 0x101039d
|
||||
field public static final int drawableEnd = 16843676; // 0x101039c
|
||||
field public static final int drawableLeft = 16843119; // 0x101016f
|
||||
field public static final int drawablePadding = 16843121; // 0x1010171
|
||||
field public static final int drawableRight = 16843120; // 0x1010170
|
||||
field public static final int drawableStart = 16843676; // 0x101039c
|
||||
field public static final int drawableStart = 16843675; // 0x101039b
|
||||
field public static final int drawableTop = 16843117; // 0x101016d
|
||||
field public static final int drawingCacheQuality = 16842984; // 0x10100e8
|
||||
field public static final int dropDownAnchor = 16843363; // 0x1010263
|
||||
@@ -444,7 +444,7 @@ package android {
|
||||
field public static final int fastScrollTextColor = 16843609; // 0x1010359
|
||||
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
|
||||
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
|
||||
field public static final int feedbackCount = 16843661; // 0x101038d
|
||||
field public static final int feedbackCount = 16843660; // 0x101038c
|
||||
field public static final int fillAfter = 16843197; // 0x10101bd
|
||||
field public static final int fillBefore = 16843196; // 0x10101bc
|
||||
field public static final int fillEnabled = 16843343; // 0x101024f
|
||||
@@ -497,7 +497,7 @@ package android {
|
||||
field public static final int hand_hour = 16843011; // 0x1010103
|
||||
field public static final int hand_minute = 16843012; // 0x1010104
|
||||
field public static final int handle = 16843354; // 0x101025a
|
||||
field public static final int handleDrawable = 16843651; // 0x1010383
|
||||
field public static final int handleDrawable = 16843650; // 0x1010382
|
||||
field public static final int handleProfiling = 16842786; // 0x1010022
|
||||
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
|
||||
field public static final int hardwareAccelerated = 16843475; // 0x10102d3
|
||||
@@ -506,12 +506,12 @@ package android {
|
||||
field public static final int headerDividersEnabled = 16843310; // 0x101022e
|
||||
field public static final int height = 16843093; // 0x1010155
|
||||
field public static final int hint = 16843088; // 0x1010150
|
||||
field public static final int hitRadius = 16843658; // 0x101038a
|
||||
field public static final int hitRadius = 16843657; // 0x1010389
|
||||
field public static final int homeAsUpIndicator = 16843531; // 0x101030b
|
||||
field public static final int homeLayout = 16843549; // 0x101031d
|
||||
field public static final int horizontalDivider = 16843053; // 0x101012d
|
||||
field public static final int horizontalGap = 16843327; // 0x101023f
|
||||
field public static final int horizontalOffset = 16843663; // 0x101038f
|
||||
field public static final int horizontalOffset = 16843662; // 0x101038e
|
||||
field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
|
||||
field public static final int horizontalSpacing = 16843028; // 0x1010114
|
||||
field public static final int host = 16842792; // 0x1010028
|
||||
@@ -557,7 +557,7 @@ package android {
|
||||
field public static final int installLocation = 16843447; // 0x10102b7
|
||||
field public static final int interpolator = 16843073; // 0x1010141
|
||||
field public static final int isAlwaysSyncable = 16843571; // 0x1010333
|
||||
field public static final int isAuxiliary = 16843643; // 0x101037b
|
||||
field public static final int isAuxiliary = 16843642; // 0x101037a
|
||||
field public static final int isDefault = 16843297; // 0x1010221
|
||||
field public static final int isIndicator = 16843079; // 0x1010147
|
||||
field public static final int isModifier = 16843334; // 0x1010246
|
||||
@@ -610,7 +610,7 @@ package android {
|
||||
field public static final int layout_centerInParent = 16843151; // 0x101018f
|
||||
field public static final int layout_centerVertical = 16843153; // 0x1010191
|
||||
field public static final int layout_column = 16843084; // 0x101014c
|
||||
field public static final int layout_columnSpan = 16843641; // 0x1010379
|
||||
field public static final int layout_columnSpan = 16843640; // 0x1010378
|
||||
field public static final int layout_gravity = 16842931; // 0x10100b3
|
||||
field public static final int layout_height = 16842997; // 0x10100f5
|
||||
field public static final int layout_margin = 16842998; // 0x10100f6
|
||||
@@ -618,8 +618,8 @@ package android {
|
||||
field public static final int layout_marginLeft = 16842999; // 0x10100f7
|
||||
field public static final int layout_marginRight = 16843001; // 0x10100f9
|
||||
field public static final int layout_marginTop = 16843000; // 0x10100f8
|
||||
field public static final int layout_row = 16843639; // 0x1010377
|
||||
field public static final int layout_rowSpan = 16843640; // 0x1010378
|
||||
field public static final int layout_row = 16843638; // 0x1010376
|
||||
field public static final int layout_rowSpan = 16843639; // 0x1010377
|
||||
field public static final int layout_scale = 16843155; // 0x1010193
|
||||
field public static final int layout_span = 16843085; // 0x101014d
|
||||
field public static final int layout_toLeftOf = 16843138; // 0x1010182
|
||||
@@ -629,7 +629,7 @@ package android {
|
||||
field public static final int layout_x = 16843135; // 0x101017f
|
||||
field public static final int layout_y = 16843136; // 0x1010180
|
||||
field public static final int left = 16843181; // 0x10101ad
|
||||
field public static final int leftChevronDrawable = 16843652; // 0x1010384
|
||||
field public static final int leftChevronDrawable = 16843651; // 0x1010383
|
||||
field public static final int lineSpacingExtra = 16843287; // 0x1010217
|
||||
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
|
||||
field public static final int lines = 16843092; // 0x1010154
|
||||
@@ -641,8 +641,8 @@ package android {
|
||||
field public static final int listDividerAlertDialog = 16843525; // 0x1010305
|
||||
field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
|
||||
field public static final int listPreferredItemHeight = 16842829; // 0x101004d
|
||||
field public static final int listPreferredItemHeightLarge = 16843664; // 0x1010390
|
||||
field public static final int listPreferredItemHeightSmall = 16843665; // 0x1010391
|
||||
field public static final int listPreferredItemHeightLarge = 16843663; // 0x101038f
|
||||
field public static final int listPreferredItemHeightSmall = 16843664; // 0x1010390
|
||||
field public static final int listSelector = 16843003; // 0x10100fb
|
||||
field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
|
||||
field public static final int listViewStyle = 16842868; // 0x1010074
|
||||
@@ -673,8 +673,8 @@ package android {
|
||||
field public static final int minHeight = 16843072; // 0x1010140
|
||||
field public static final int minLevel = 16843185; // 0x10101b1
|
||||
field public static final int minLines = 16843094; // 0x1010156
|
||||
field public static final int minResizeHeight = 16843680; // 0x10103a0
|
||||
field public static final int minResizeWidth = 16843679; // 0x101039f
|
||||
field public static final int minResizeHeight = 16843679; // 0x101039f
|
||||
field public static final int minResizeWidth = 16843678; // 0x101039e
|
||||
field public static final int minSdkVersion = 16843276; // 0x101020c
|
||||
field public static final int minWidth = 16843071; // 0x101013f
|
||||
field public static final int mode = 16843134; // 0x101017e
|
||||
@@ -690,7 +690,7 @@ package android {
|
||||
field public static final int nextFocusUp = 16842979; // 0x10100e3
|
||||
field public static final int noHistory = 16843309; // 0x101022d
|
||||
field public static final int normalScreens = 16843397; // 0x1010285
|
||||
field public static final int notificationTimeout = 16843647; // 0x101037f
|
||||
field public static final int notificationTimeout = 16843646; // 0x101037e
|
||||
field public static final int numColumns = 16843032; // 0x1010118
|
||||
field public static final int numStars = 16843076; // 0x1010144
|
||||
field public static final deprecated int numeric = 16843109; // 0x1010165
|
||||
@@ -704,11 +704,11 @@ package android {
|
||||
field public static final int orderingFromXml = 16843239; // 0x10101e7
|
||||
field public static final int orientation = 16842948; // 0x10100c4
|
||||
field public static final int outAnimation = 16843128; // 0x1010178
|
||||
field public static final int outerRadius = 16843657; // 0x1010389
|
||||
field public static final int outerRadius = 16843656; // 0x1010388
|
||||
field public static final int overScrollFooter = 16843459; // 0x10102c3
|
||||
field public static final int overScrollHeader = 16843458; // 0x10102c2
|
||||
field public static final int overScrollMode = 16843457; // 0x10102c1
|
||||
field public static final int packageNames = 16843645; // 0x101037d
|
||||
field public static final int packageNames = 16843644; // 0x101037c
|
||||
field public static final int padding = 16842965; // 0x10100d5
|
||||
field public static final int paddingBottom = 16842969; // 0x10100d9
|
||||
field public static final int paddingLeft = 16842966; // 0x10100d6
|
||||
@@ -793,17 +793,17 @@ package android {
|
||||
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
|
||||
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
|
||||
field public static final int right = 16843183; // 0x10101af
|
||||
field public static final int rightChevronDrawable = 16843653; // 0x1010385
|
||||
field public static final int rightChevronDrawable = 16843652; // 0x1010384
|
||||
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
|
||||
field public static final int ringtoneType = 16843257; // 0x10101f9
|
||||
field public static final int rotation = 16843558; // 0x1010326
|
||||
field public static final int rotationX = 16843559; // 0x1010327
|
||||
field public static final int rotationY = 16843560; // 0x1010328
|
||||
field public static final int rowCount = 16843633; // 0x1010371
|
||||
field public static final int rowCount = 16843632; // 0x1010370
|
||||
field public static final int rowDelay = 16843216; // 0x10101d0
|
||||
field public static final int rowEdgeFlags = 16843329; // 0x1010241
|
||||
field public static final int rowHeight = 16843058; // 0x1010132
|
||||
field public static final int rowOrderPreserved = 16843634; // 0x1010372
|
||||
field public static final int rowOrderPreserved = 16843633; // 0x1010371
|
||||
field public static final int saveEnabled = 16842983; // 0x10100e7
|
||||
field public static final int scaleGravity = 16843262; // 0x10101fe
|
||||
field public static final int scaleHeight = 16843261; // 0x10101fd
|
||||
@@ -869,7 +869,7 @@ package android {
|
||||
field public static final int smallIcon = 16843422; // 0x101029e
|
||||
field public static final int smallScreens = 16843396; // 0x1010284
|
||||
field public static final int smoothScrollbar = 16843313; // 0x1010231
|
||||
field public static final int snapMargin = 16843660; // 0x101038c
|
||||
field public static final int snapMargin = 16843659; // 0x101038b
|
||||
field public static final int soundEffectsEnabled = 16843285; // 0x1010215
|
||||
field public static final int spacing = 16843027; // 0x1010113
|
||||
field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
|
||||
@@ -915,11 +915,10 @@ package android {
|
||||
field public static final int stretchMode = 16843030; // 0x1010116
|
||||
field public static final int subtitle = 16843473; // 0x10102d1
|
||||
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
|
||||
field public static final int subtypeExtraValue = 16843684; // 0x10103a4
|
||||
field public static final int subtypeLocale = 16843683; // 0x10103a3
|
||||
field public static final int subtypeExtraValue = 16843683; // 0x10103a3
|
||||
field public static final int subtypeLocale = 16843682; // 0x10103a2
|
||||
field public static final int suggestActionMsg = 16843228; // 0x10101dc
|
||||
field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
|
||||
field public static final int suggestionsEnabled = 16843632; // 0x1010370
|
||||
field public static final int summary = 16843241; // 0x10101e9
|
||||
field public static final int summaryColumn = 16843426; // 0x10102a2
|
||||
field public static final int summaryOff = 16843248; // 0x10101f0
|
||||
@@ -936,7 +935,7 @@ package android {
|
||||
field public static final int tag = 16842961; // 0x10100d1
|
||||
field public static final int targetActivity = 16843266; // 0x1010202
|
||||
field public static final int targetClass = 16842799; // 0x101002f
|
||||
field public static final int targetDrawables = 16843650; // 0x1010382
|
||||
field public static final int targetDrawables = 16843649; // 0x1010381
|
||||
field public static final int targetPackage = 16842785; // 0x1010021
|
||||
field public static final int targetSdkVersion = 16843376; // 0x1010270
|
||||
field public static final int taskAffinity = 16842770; // 0x1010012
|
||||
@@ -951,15 +950,15 @@ package android {
|
||||
field public static final int tension = 16843370; // 0x101026a
|
||||
field public static final int testOnly = 16843378; // 0x1010272
|
||||
field public static final int text = 16843087; // 0x101014f
|
||||
field public static final int textAllCaps = 16843670; // 0x1010396
|
||||
field public static final int textAllCaps = 16843669; // 0x1010395
|
||||
field public static final int textAppearance = 16842804; // 0x1010034
|
||||
field public static final int textAppearanceButton = 16843271; // 0x1010207
|
||||
field public static final int textAppearanceInverse = 16842805; // 0x1010035
|
||||
field public static final int textAppearanceLarge = 16842816; // 0x1010040
|
||||
field public static final int textAppearanceLargeInverse = 16842819; // 0x1010043
|
||||
field public static final int textAppearanceLargePopupMenu = 16843521; // 0x1010301
|
||||
field public static final int textAppearanceListItem = 16843688; // 0x10103a8
|
||||
field public static final int textAppearanceListItemSmall = 16843689; // 0x10103a9
|
||||
field public static final int textAppearanceListItem = 16843687; // 0x10103a7
|
||||
field public static final int textAppearanceListItemSmall = 16843688; // 0x10103a8
|
||||
field public static final int textAppearanceMedium = 16842817; // 0x1010041
|
||||
field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
|
||||
field public static final int textAppearanceSearchResultSubtitle = 16843424; // 0x10102a0
|
||||
@@ -1027,7 +1026,7 @@ package android {
|
||||
field public static final int toYScale = 16843205; // 0x10101c5
|
||||
field public static final int top = 16843182; // 0x10101ae
|
||||
field public static final int topBright = 16842955; // 0x10100cb
|
||||
field public static final int topChevronDrawable = 16843654; // 0x1010386
|
||||
field public static final int topChevronDrawable = 16843653; // 0x1010385
|
||||
field public static final int topDark = 16842951; // 0x10100c7
|
||||
field public static final int topLeftRadius = 16843177; // 0x10101a9
|
||||
field public static final int topOffset = 16843352; // 0x1010258
|
||||
@@ -1039,12 +1038,12 @@ package android {
|
||||
field public static final int translationY = 16843555; // 0x1010323
|
||||
field public static final int type = 16843169; // 0x10101a1
|
||||
field public static final int typeface = 16842902; // 0x1010096
|
||||
field public static final int uiOptions = 16843682; // 0x10103a2
|
||||
field public static final int uiOptions = 16843681; // 0x10103a1
|
||||
field public static final int uncertainGestureColor = 16843382; // 0x1010276
|
||||
field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
|
||||
field public static final int unselectedAlpha = 16843278; // 0x101020e
|
||||
field public static final int updatePeriodMillis = 16843344; // 0x1010250
|
||||
field public static final int useDefaultMargins = 16843637; // 0x1010375
|
||||
field public static final int useDefaultMargins = 16843636; // 0x1010374
|
||||
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
|
||||
field public static final int useLevel = 16843167; // 0x101019f
|
||||
field public static final int userVisible = 16843409; // 0x1010291
|
||||
@@ -1058,10 +1057,10 @@ package android {
|
||||
field public static final int verticalCorrection = 16843322; // 0x101023a
|
||||
field public static final int verticalDivider = 16843054; // 0x101012e
|
||||
field public static final int verticalGap = 16843328; // 0x1010240
|
||||
field public static final int verticalOffset = 16843662; // 0x101038e
|
||||
field public static final int verticalOffset = 16843661; // 0x101038d
|
||||
field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
|
||||
field public static final int verticalSpacing = 16843029; // 0x1010115
|
||||
field public static final int vibrationDuration = 16843659; // 0x101038b
|
||||
field public static final int vibrationDuration = 16843658; // 0x101038a
|
||||
field public static final int visibility = 16842972; // 0x10100dc
|
||||
field public static final int visible = 16843156; // 0x1010194
|
||||
field public static final int vmSafeMode = 16843448; // 0x10102b8
|
||||
@@ -1078,7 +1077,7 @@ package android {
|
||||
field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
|
||||
field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
|
||||
field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
|
||||
field public static final int waveDrawable = 16843656; // 0x1010388
|
||||
field public static final int waveDrawable = 16843655; // 0x1010387
|
||||
field public static final int webTextViewStyle = 16843449; // 0x10102b9
|
||||
field public static final int webViewStyle = 16842885; // 0x1010085
|
||||
field public static final int weekDayTextAppearance = 16843592; // 0x1010348
|
||||
@@ -20811,6 +20810,7 @@ package android.text.style {
|
||||
method public java.lang.String getLocale();
|
||||
method public int getSpanTypeId();
|
||||
method public java.lang.String[] getSuggestions();
|
||||
method public void setFlags(int);
|
||||
method public void updateDrawState(android.text.TextPaint);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final java.lang.String ACTION_SUGGESTION_PICKED = "android.text.style.SUGGESTION_PICKED";
|
||||
@@ -27131,7 +27131,6 @@ package android.widget {
|
||||
method public void setSingleLine();
|
||||
method public void setSingleLine(boolean);
|
||||
method public final void setSpannableFactory(android.text.Spannable.Factory);
|
||||
method public void setSuggestionsEnabled(boolean);
|
||||
method public final void setText(java.lang.CharSequence);
|
||||
method public void setText(java.lang.CharSequence, android.widget.TextView.BufferType);
|
||||
method public final void setText(char[], int, int);
|
||||
|
||||
@@ -16,21 +16,18 @@
|
||||
|
||||
package android.text;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.text.style.SuggestionSpan;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
/**
|
||||
* This is the class for text whose content and markup can both be changed.
|
||||
*/
|
||||
public class SpannableStringBuilder
|
||||
implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
GraphicsOperations
|
||||
{
|
||||
public class SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable,
|
||||
Appendable, GraphicsOperations {
|
||||
/**
|
||||
* Create a new SpannableStringBuilder with empty contents
|
||||
*/
|
||||
@@ -111,8 +108,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
if (where < 0) {
|
||||
throw new IndexOutOfBoundsException("charAt: " + where + " < 0");
|
||||
} else if (where >= len) {
|
||||
throw new IndexOutOfBoundsException("charAt: " + where +
|
||||
" >= length " + len);
|
||||
throw new IndexOutOfBoundsException("charAt: " + where + " >= length " + len);
|
||||
}
|
||||
|
||||
if (where >= mGapStart)
|
||||
@@ -266,8 +262,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
return append(String.valueOf(text));
|
||||
}
|
||||
|
||||
private int change(int start, int end,
|
||||
CharSequence tb, int tbstart, int tbend) {
|
||||
private int change(int start, int end, CharSequence tb, int tbstart, int tbend) {
|
||||
return change(true, start, end, tb, tbstart, tbend);
|
||||
}
|
||||
|
||||
@@ -277,8 +272,9 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
int ret = tbend - tbstart;
|
||||
TextWatcher[] recipients = null;
|
||||
|
||||
if (notify)
|
||||
if (notify) {
|
||||
recipients = sendTextWillChange(start, end - start, tbend - tbstart);
|
||||
}
|
||||
|
||||
for (int i = mSpanCount - 1; i >= 0; i--) {
|
||||
if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) {
|
||||
@@ -353,7 +349,6 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
// no need for span fixup on pure insertion
|
||||
if (tbend > tbstart && end - start == 0) {
|
||||
if (notify) {
|
||||
removeSuggestionSpans(start, end);
|
||||
sendTextChange(recipients, start, end - start, tbend - tbstart);
|
||||
sendTextHasChanged(recipients);
|
||||
}
|
||||
@@ -388,7 +383,6 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
if (mSpanEnds[i] < mSpanStarts[i]) {
|
||||
removeSpan(i);
|
||||
}
|
||||
removeSuggestionSpans(start, end);
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
@@ -399,30 +393,26 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the SuggestionSpan that overlap the [start, end] range, and that would
|
||||
* not make sense anymore after the change.
|
||||
*/
|
||||
private void removeSuggestionSpans(int start, int end) {
|
||||
for (int i = mSpanCount - 1; i >= 0; i--) {
|
||||
final int spanEnd = mSpanEnds[i];
|
||||
final int spanSpart = mSpanStarts[i];
|
||||
if ((mSpans[i] instanceof SuggestionSpan) && (
|
||||
(spanSpart < start && spanEnd > start) ||
|
||||
(spanSpart < end && spanEnd > end))) {
|
||||
removeSpan(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSpan(int i) {
|
||||
// XXX send notification on removal
|
||||
System.arraycopy(mSpans, i + 1, mSpans, i, mSpanCount - (i + 1));
|
||||
System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, mSpanCount - (i + 1));
|
||||
System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, mSpanCount - (i + 1));
|
||||
System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, mSpanCount - (i + 1));
|
||||
Object object = mSpans[i];
|
||||
|
||||
int start = mSpanStarts[i];
|
||||
int end = mSpanEnds[i];
|
||||
|
||||
if (start > mGapStart) start -= mGapLength;
|
||||
if (end > mGapStart) end -= mGapLength;
|
||||
|
||||
int count = mSpanCount - (i + 1);
|
||||
System.arraycopy(mSpans, i + 1, mSpans, i, count);
|
||||
System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count);
|
||||
System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count);
|
||||
System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count);
|
||||
|
||||
mSpanCount--;
|
||||
|
||||
mSpans[mSpanCount] = null;
|
||||
|
||||
sendSpanRemoved(object, start, end);
|
||||
}
|
||||
|
||||
// Documentation from interface
|
||||
@@ -462,11 +452,10 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
moveGapTo(end);
|
||||
TextWatcher[] recipients;
|
||||
|
||||
recipients = sendTextWillChange(start, end - start,
|
||||
tbend - tbstart);
|
||||
|
||||
int origlen = end - start;
|
||||
|
||||
recipients = sendTextWillChange(start, origlen, tbend - tbstart);
|
||||
|
||||
if (mGapLength < 2)
|
||||
resizeFor(length() + 1);
|
||||
|
||||
@@ -486,11 +475,9 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
new Exception("mGapLength < 1").printStackTrace();
|
||||
}
|
||||
|
||||
int oldlen = (end + 1) - start;
|
||||
|
||||
int inserted = change(false, start + 1, start + 1, tb, tbstart, tbend);
|
||||
change(false, start, start + 1, "", 0, 0);
|
||||
change(false, start + inserted, start + inserted + oldlen - 1, "", 0, 0);
|
||||
change(false, start + inserted, start + inserted + origlen, "", 0, 0);
|
||||
|
||||
/*
|
||||
* Special case to keep the cursor in the same position
|
||||
@@ -515,13 +502,12 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
off = off * inserted / (end - start);
|
||||
selend = (int) off + start;
|
||||
|
||||
setSpan(false, Selection.SELECTION_END, selend, selend,
|
||||
Spanned.SPAN_POINT_POINT);
|
||||
setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT);
|
||||
}
|
||||
|
||||
sendTextChange(recipients, start, origlen, inserted);
|
||||
sendTextHasChanged(recipients);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -534,8 +520,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
setSpan(true, what, start, end, flags);
|
||||
}
|
||||
|
||||
private void setSpan(boolean send,
|
||||
Object what, int start, int end, int flags) {
|
||||
private void setSpan(boolean send, Object what, int start, int end, int flags) {
|
||||
int nstart = start;
|
||||
int nend = end;
|
||||
|
||||
@@ -546,8 +531,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
char c = charAt(start - 1);
|
||||
|
||||
if (c != '\n')
|
||||
throw new RuntimeException(
|
||||
"PARAGRAPH span must start at paragraph boundary");
|
||||
throw new RuntimeException("PARAGRAPH span must start at paragraph boundary");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,23 +540,22 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
char c = charAt(end - 1);
|
||||
|
||||
if (c != '\n')
|
||||
throw new RuntimeException(
|
||||
"PARAGRAPH span must end at paragraph boundary");
|
||||
throw new RuntimeException("PARAGRAPH span must end at paragraph boundary");
|
||||
}
|
||||
}
|
||||
|
||||
if (start > mGapStart)
|
||||
if (start > mGapStart) {
|
||||
start += mGapLength;
|
||||
else if (start == mGapStart) {
|
||||
} else if (start == mGapStart) {
|
||||
int flag = (flags & START_MASK) >> START_SHIFT;
|
||||
|
||||
if (flag == POINT || (flag == PARAGRAPH && start == length()))
|
||||
start += mGapLength;
|
||||
}
|
||||
|
||||
if (end > mGapStart)
|
||||
if (end > mGapStart) {
|
||||
end += mGapLength;
|
||||
else if (end == mGapStart) {
|
||||
} else if (end == mGapStart) {
|
||||
int flag = (flags & END_MASK);
|
||||
|
||||
if (flag == POINT || (flag == PARAGRAPH && end == length()))
|
||||
@@ -637,25 +620,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
public void removeSpan(Object what) {
|
||||
for (int i = mSpanCount - 1; i >= 0; i--) {
|
||||
if (mSpans[i] == what) {
|
||||
int ostart = mSpanStarts[i];
|
||||
int oend = mSpanEnds[i];
|
||||
|
||||
if (ostart > mGapStart)
|
||||
ostart -= mGapLength;
|
||||
if (oend > mGapStart)
|
||||
oend -= mGapLength;
|
||||
|
||||
int count = mSpanCount - (i + 1);
|
||||
|
||||
System.arraycopy(mSpans, i + 1, mSpans, i, count);
|
||||
System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count);
|
||||
System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count);
|
||||
System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count);
|
||||
|
||||
mSpanCount--;
|
||||
mSpans[mSpanCount] = null;
|
||||
|
||||
sendSpanRemoved(what, ostart, oend);
|
||||
removeSpan(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -729,6 +694,8 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
|
||||
if (kind == null) return ArrayUtils.emptyArray(kind);
|
||||
|
||||
int spanCount = mSpanCount;
|
||||
Object[] spans = mSpans;
|
||||
int[] starts = mSpanStarts;
|
||||
@@ -742,6 +709,8 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
T ret1 = null;
|
||||
|
||||
for (int i = 0; i < spanCount; i++) {
|
||||
if (!kind.isInstance(spans[i])) continue;
|
||||
|
||||
int spanStart = starts[i];
|
||||
int spanEnd = ends[i];
|
||||
|
||||
@@ -766,10 +735,6 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kind != null && !kind.isInstance(spans[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
// Safe conversion thanks to the isInstance test above
|
||||
ret1 = (T) spans[i];
|
||||
@@ -909,8 +874,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
return recip;
|
||||
}
|
||||
|
||||
private void sendTextChange(TextWatcher[] recip, int start, int before,
|
||||
int after) {
|
||||
private void sendTextChange(TextWatcher[] recip, int start, int before, int after) {
|
||||
int n = recip.length;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
@@ -945,8 +909,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
|
||||
}
|
||||
|
||||
private void sendSpanChanged(Object what, int s, int e, int st, int en) {
|
||||
SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en),
|
||||
SpanWatcher.class);
|
||||
SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en), SpanWatcher.class);
|
||||
int n = recip.length;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
||||
@@ -73,6 +73,10 @@ public class WordIterator implements Selection.PositionIterator {
|
||||
}
|
||||
};
|
||||
|
||||
public void forceUpdate() {
|
||||
mCurrentDirty = true;
|
||||
}
|
||||
|
||||
public void setCharSequence(CharSequence incoming) {
|
||||
// When incoming is different object, move listeners to new sequence
|
||||
// and mark as dirty so we reload contents.
|
||||
|
||||
41
core/java/android/text/style/SpellCheckSpan.java
Normal file
41
core/java/android/text/style/SpellCheckSpan.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.text.style;
|
||||
|
||||
/**
|
||||
* A SpellCheckSpan is an internal data structure created by the TextView's SpellChecker to
|
||||
* annotate portions of the text that are about to or currently being spell checked. They are
|
||||
* automatically removed once the spell check is completed.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class SpellCheckSpan {
|
||||
|
||||
private boolean mSpellCheckInProgress;
|
||||
|
||||
public SpellCheckSpan() {
|
||||
mSpellCheckInProgress = false;
|
||||
}
|
||||
|
||||
public void setSpellCheckInProgress() {
|
||||
mSpellCheckInProgress = true;
|
||||
}
|
||||
|
||||
public boolean isSpellCheckInProgress() {
|
||||
return mSpellCheckInProgress;
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ import java.util.Locale;
|
||||
* These spans should typically be created by the input method to provide correction and alternates
|
||||
* for the text.
|
||||
*
|
||||
* @see TextView#setSuggestionsEnabled(boolean)
|
||||
* @see TextView#isSuggestionsEnabled()
|
||||
*/
|
||||
public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
|
||||
@@ -76,7 +76,7 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
* And the current IME might want to specify any IME as the target IME including other IMEs.
|
||||
*/
|
||||
|
||||
private final int mFlags;
|
||||
private int mFlags;
|
||||
private final String[] mSuggestions;
|
||||
private final String mLocaleString;
|
||||
private final String mNotificationTargetClassName;
|
||||
@@ -134,8 +134,7 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
} else {
|
||||
mNotificationTargetClassName = "";
|
||||
}
|
||||
mHashCode = hashCodeInternal(
|
||||
mFlags, mSuggestions, mLocaleString, mNotificationTargetClassName);
|
||||
mHashCode = hashCodeInternal(mSuggestions, mLocaleString, mNotificationTargetClassName);
|
||||
|
||||
initStyle(context);
|
||||
}
|
||||
@@ -211,6 +210,10 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
public void setFlags(int flags) {
|
||||
mFlags = flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
@@ -247,10 +250,10 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
return mHashCode;
|
||||
}
|
||||
|
||||
private static int hashCodeInternal(int flags, String[] suggestions,String locale,
|
||||
private static int hashCodeInternal(String[] suggestions, String locale,
|
||||
String notificationTargetClassName) {
|
||||
return Arrays.hashCode(new Object[] {SystemClock.uptimeMillis(), flags, suggestions, locale,
|
||||
notificationTargetClassName});
|
||||
return Arrays.hashCode(new Object[] {Long.valueOf(SystemClock.uptimeMillis()), suggestions,
|
||||
locale, notificationTargetClassName});
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<SuggestionSpan> CREATOR =
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.view.textservice;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@@ -23,7 +25,7 @@ import android.os.Parcelable;
|
||||
* This class contains a metadata of suggestions from the text service
|
||||
*/
|
||||
public final class SuggestionsInfo implements Parcelable {
|
||||
private static final String[] EMPTY = new String[0];
|
||||
private static final String[] EMPTY = ArrayUtils.emptyArray(String.class);
|
||||
|
||||
/**
|
||||
* Flag of the attributes of the suggestions that can be obtained by
|
||||
|
||||
226
core/java/android/widget/SpellChecker.java
Normal file
226
core/java/android/widget/SpellChecker.java
Normal file
@@ -0,0 +1,226 @@
|
||||
// Copyright 2011 Google Inc. All Rights Reserved.
|
||||
|
||||
package android.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Editable;
|
||||
import android.text.Selection;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.SpellCheckSpan;
|
||||
import android.text.style.SuggestionSpan;
|
||||
import android.util.Log;
|
||||
import android.view.textservice.SpellCheckerSession;
|
||||
import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
|
||||
import android.view.textservice.SuggestionsInfo;
|
||||
import android.view.textservice.TextInfo;
|
||||
import android.view.textservice.TextServicesManager;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class for TextView. Bridge between the TextView and the Dictionnary service.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class SpellChecker implements SpellCheckerSessionListener {
|
||||
private static final String LOG_TAG = "SpellChecker";
|
||||
private static final boolean DEBUG_SPELL_CHECK = false;
|
||||
private static final int DELAY_BEFORE_SPELL_CHECK = 400; // milliseconds
|
||||
|
||||
private final TextView mTextView;
|
||||
|
||||
final SpellCheckerSession spellCheckerSession;
|
||||
final int mCookie;
|
||||
|
||||
// Paired arrays for the (id, spellCheckSpan) pair. mIndex is the next available position
|
||||
private int[] mIds;
|
||||
private SpellCheckSpan[] mSpellCheckSpans;
|
||||
// The actual current number of used slots in the above arrays
|
||||
private int mLength;
|
||||
|
||||
private int mSpanSequenceCounter = 0;
|
||||
private Runnable mChecker;
|
||||
|
||||
public SpellChecker(TextView textView) {
|
||||
mTextView = textView;
|
||||
|
||||
final TextServicesManager textServicesManager = (TextServicesManager) textView.getContext().
|
||||
getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
|
||||
spellCheckerSession = textServicesManager.newSpellCheckerSession(
|
||||
null /* not currently used by the textServicesManager */, Locale.getDefault(),
|
||||
this, true /* means use the languages defined in Settings */);
|
||||
mCookie = hashCode();
|
||||
|
||||
// Arbitrary: 4 simultaneous spell check spans. Will automatically double size on demand
|
||||
final int size = ArrayUtils.idealObjectArraySize(4);
|
||||
mIds = new int[size];
|
||||
mSpellCheckSpans = new SpellCheckSpan[size];
|
||||
mLength = 0;
|
||||
}
|
||||
|
||||
public void addSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
|
||||
int length = mIds.length;
|
||||
if (mLength >= length) {
|
||||
final int newSize = length * 2;
|
||||
int[] newIds = new int[newSize];
|
||||
SpellCheckSpan[] newSpellCheckSpans = new SpellCheckSpan[newSize];
|
||||
System.arraycopy(mIds, 0, newIds, 0, length);
|
||||
System.arraycopy(mSpellCheckSpans, 0, newSpellCheckSpans, 0, length);
|
||||
mIds = newIds;
|
||||
mSpellCheckSpans = newSpellCheckSpans;
|
||||
}
|
||||
|
||||
mIds[mLength] = mSpanSequenceCounter++;
|
||||
mSpellCheckSpans[mLength] = spellCheckSpan;
|
||||
mLength++;
|
||||
|
||||
if (DEBUG_SPELL_CHECK) {
|
||||
final Editable mText = (Editable) mTextView.getText();
|
||||
int start = mText.getSpanStart(spellCheckSpan);
|
||||
int end = mText.getSpanEnd(spellCheckSpan);
|
||||
if (start >= 0 && end >= 0) {
|
||||
Log.d(LOG_TAG, "Schedule check " + mText.subSequence(start, end));
|
||||
} else {
|
||||
Log.d(LOG_TAG, "Schedule check EMPTY!");
|
||||
}
|
||||
}
|
||||
|
||||
scheduleSpellCheck();
|
||||
}
|
||||
|
||||
public void removeSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
|
||||
for (int i = 0; i < mLength; i++) {
|
||||
if (mSpellCheckSpans[i] == spellCheckSpan) {
|
||||
removeAtIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeAtIndex(int i) {
|
||||
System.arraycopy(mIds, i + 1, mIds, i, mLength - i - 1);
|
||||
System.arraycopy(mSpellCheckSpans, i + 1, mSpellCheckSpans, i, mLength - i - 1);
|
||||
mLength--;
|
||||
}
|
||||
|
||||
public void onSelectionChanged() {
|
||||
scheduleSpellCheck();
|
||||
}
|
||||
|
||||
private void scheduleSpellCheck() {
|
||||
if (mLength == 0) return;
|
||||
if (mChecker != null) {
|
||||
mTextView.removeCallbacks(mChecker);
|
||||
}
|
||||
if (mChecker == null) {
|
||||
mChecker = new Runnable() {
|
||||
public void run() {
|
||||
spellCheck();
|
||||
}
|
||||
};
|
||||
}
|
||||
mTextView.postDelayed(mChecker, DELAY_BEFORE_SPELL_CHECK);
|
||||
}
|
||||
|
||||
private void spellCheck() {
|
||||
final Editable editable = (Editable) mTextView.getText();
|
||||
final int selectionStart = Selection.getSelectionStart(editable);
|
||||
final int selectionEnd = Selection.getSelectionEnd(editable);
|
||||
|
||||
TextInfo[] textInfos = new TextInfo[mLength];
|
||||
int textInfosCount = 0;
|
||||
|
||||
for (int i = 0; i < mLength; i++) {
|
||||
SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
|
||||
|
||||
if (spellCheckSpan.isSpellCheckInProgress()) continue;
|
||||
|
||||
final int start = editable.getSpanStart(spellCheckSpan);
|
||||
final int end = editable.getSpanEnd(spellCheckSpan);
|
||||
|
||||
// Do not check this word if the user is currently editing it
|
||||
if (start >= 0 && end >= 0 && (selectionEnd < start || selectionStart > end)) {
|
||||
final String word = editable.subSequence(start, end).toString();
|
||||
spellCheckSpan.setSpellCheckInProgress();
|
||||
textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (textInfosCount > 0) {
|
||||
if (textInfosCount < mLength) {
|
||||
TextInfo[] textInfosCopy = new TextInfo[textInfosCount];
|
||||
System.arraycopy(textInfos, 0, textInfosCopy, 0, textInfosCount);
|
||||
textInfos = textInfosCopy;
|
||||
}
|
||||
spellCheckerSession.getSuggestions(textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE,
|
||||
false /* TODO Set sequentialWords to true for initial spell check */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGetSuggestions(SuggestionsInfo[] results) {
|
||||
final Editable editable = (Editable) mTextView.getText();
|
||||
for (int i = 0; i < results.length; i++) {
|
||||
SuggestionsInfo suggestionsInfo = results[i];
|
||||
if (suggestionsInfo.getCookie() != mCookie) continue;
|
||||
|
||||
final int sequenceNumber = suggestionsInfo.getSequence();
|
||||
// Starting from the end, to limit the number of array copy while removing
|
||||
for (int j = mLength - 1; j >= 0; j--) {
|
||||
if (sequenceNumber == mIds[j]) {
|
||||
SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
|
||||
final int attributes = suggestionsInfo.getSuggestionsAttributes();
|
||||
boolean isInDictionary =
|
||||
((attributes & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) > 0);
|
||||
boolean looksLikeTypo =
|
||||
((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);
|
||||
|
||||
if (DEBUG_SPELL_CHECK) {
|
||||
final int start = editable.getSpanStart(spellCheckSpan);
|
||||
final int end = editable.getSpanEnd(spellCheckSpan);
|
||||
Log.d(LOG_TAG, "Result sequence=" + suggestionsInfo.getSequence() + " " +
|
||||
editable.subSequence(start, end) +
|
||||
"\t" + (isInDictionary?"IN_DICT" : "NOT_DICT") +
|
||||
"\t" + (looksLikeTypo?"TYPO" : "NOT_TYPO"));
|
||||
}
|
||||
|
||||
if (!isInDictionary && looksLikeTypo) {
|
||||
String[] suggestions = getSuggestions(suggestionsInfo);
|
||||
if (suggestions.length > 0) {
|
||||
SuggestionSpan suggestionSpan = new SuggestionSpan(
|
||||
mTextView.getContext(), suggestions,
|
||||
SuggestionSpan.FLAG_EASY_CORRECT |
|
||||
SuggestionSpan.FLAG_MISSPELLED);
|
||||
final int start = editable.getSpanStart(spellCheckSpan);
|
||||
final int end = editable.getSpanEnd(spellCheckSpan);
|
||||
editable.setSpan(suggestionSpan, start, end,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
// TODO limit to the word rectangle region
|
||||
mTextView.invalidate();
|
||||
|
||||
if (DEBUG_SPELL_CHECK) {
|
||||
String suggestionsString = "";
|
||||
for (String s : suggestions) { suggestionsString += s + "|"; }
|
||||
Log.d(LOG_TAG, " Suggestions for " + sequenceNumber + " " +
|
||||
editable.subSequence(start, end)+ " " + suggestionsString);
|
||||
}
|
||||
}
|
||||
}
|
||||
editable.removeSpan(spellCheckSpan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] getSuggestions(SuggestionsInfo suggestionsInfo) {
|
||||
final int len = Math.max(0, suggestionsInfo.getSuggestionsCount());
|
||||
String[] suggestions = new String[len];
|
||||
for (int j = 0; j < len; ++j) {
|
||||
suggestions[j] = suggestionsInfo.getSuggestionAt(j);
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
@@ -61,11 +61,6 @@ import android.text.SpannedString;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextDirectionHeuristic;
|
||||
import android.text.TextDirectionHeuristics;
|
||||
import android.text.TextDirectionHeuristics.AnyStrong;
|
||||
import android.text.TextDirectionHeuristics.CharCount;
|
||||
import android.text.TextDirectionHeuristics.FirstStrong;
|
||||
import android.text.TextDirectionHeuristics.TextDirectionAlgorithm;
|
||||
import android.text.TextDirectionHeuristics.TextDirectionHeuristicImpl;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
@@ -88,6 +83,7 @@ import android.text.method.TransformationMethod2;
|
||||
import android.text.method.WordIterator;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.ParagraphStyle;
|
||||
import android.text.style.SpellCheckSpan;
|
||||
import android.text.style.SuggestionSpan;
|
||||
import android.text.style.TextAppearanceSpan;
|
||||
import android.text.style.URLSpan;
|
||||
@@ -220,7 +216,6 @@ import java.util.HashMap;
|
||||
* @attr ref android.R.styleable#TextView_imeActionLabel
|
||||
* @attr ref android.R.styleable#TextView_imeActionId
|
||||
* @attr ref android.R.styleable#TextView_editorExtras
|
||||
* @attr ref android.R.styleable#TextView_suggestionsEnabled
|
||||
*/
|
||||
@RemoteView
|
||||
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
|
||||
@@ -334,7 +329,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
private int mTextEditSuggestionItemLayout;
|
||||
private SuggestionsPopupWindow mSuggestionsPopupWindow;
|
||||
private SuggestionRangeSpan mSuggestionRangeSpan;
|
||||
private boolean mSuggestionsEnabled = true;
|
||||
|
||||
private int mCursorDrawableRes;
|
||||
private final Drawable[] mCursorDrawable = new Drawable[2];
|
||||
@@ -356,6 +350,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
|
||||
private WordIterator mWordIterator;
|
||||
|
||||
private SpellChecker mSpellChecker;
|
||||
|
||||
// The alignment to pass to Layout, or null if not resolved.
|
||||
private Layout.Alignment mLayoutAlignment;
|
||||
|
||||
@@ -826,10 +822,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mTextIsSelectable = a.getBoolean(attr, false);
|
||||
break;
|
||||
|
||||
case com.android.internal.R.styleable.TextView_suggestionsEnabled:
|
||||
mSuggestionsEnabled = a.getBoolean(attr, true);
|
||||
break;
|
||||
|
||||
case com.android.internal.R.styleable.TextView_textAllCaps:
|
||||
allCaps = a.getBoolean(attr, false);
|
||||
break;
|
||||
@@ -3100,18 +3092,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
|
||||
boolean needEditableForNotification = false;
|
||||
boolean startSpellCheck = false;
|
||||
|
||||
if (mListeners != null && mListeners.size() != 0) {
|
||||
needEditableForNotification = true;
|
||||
}
|
||||
|
||||
if (type == BufferType.EDITABLE || mInput != null ||
|
||||
needEditableForNotification) {
|
||||
if (type == BufferType.EDITABLE || mInput != null || needEditableForNotification) {
|
||||
Editable t = mEditableFactory.newEditable(text);
|
||||
text = t;
|
||||
setFilters(t, mFilters);
|
||||
InputMethodManager imm = InputMethodManager.peekInstance();
|
||||
if (imm != null) imm.restartInput(this);
|
||||
startSpellCheck = true;
|
||||
} else if (type == BufferType.SPANNABLE || mMovement != null) {
|
||||
text = mSpannableFactory.newSpannable(text);
|
||||
} else if (!(text instanceof CharWrapper)) {
|
||||
@@ -3200,6 +3193,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
sendOnTextChanged(text, 0, oldlen, textLength);
|
||||
onTextChanged(text, 0, oldlen, textLength);
|
||||
|
||||
if (startSpellCheck) {
|
||||
updateSpellCheckSpans(0, textLength);
|
||||
}
|
||||
|
||||
if (needEditableForNotification) {
|
||||
sendAfterTextChanged((Editable) text);
|
||||
}
|
||||
@@ -7113,8 +7110,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
* to turn off ellipsizing.
|
||||
*
|
||||
* If {@link #setMaxLines} has been used to set two or more lines,
|
||||
* {@link TextUtils.TruncateAt#END} and {@link TextUtils.TruncateAt#MARQUEE}
|
||||
* are only supported (other ellipsizing types will not do anything).
|
||||
* {@link android.text.TextUtils.TruncateAt#END} and
|
||||
* {@link android.text.TextUtils.TruncateAt#MARQUEE}* are only supported
|
||||
* (other ellipsizing types will not do anything).
|
||||
*
|
||||
* @attr ref android.R.styleable#TextView_ellipsize
|
||||
*/
|
||||
@@ -7376,7 +7374,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
* @param lengthAfter The length of the replacement modified text
|
||||
*/
|
||||
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
|
||||
// intentionally empty
|
||||
// intentionally empty, template pattern method can be overridden by subclasses
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7388,6 +7386,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
*/
|
||||
protected void onSelectionChanged(int selStart, int selEnd) {
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
|
||||
if (mSpellChecker != null) {
|
||||
mSpellChecker.onSelectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7422,8 +7423,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
}
|
||||
|
||||
private void sendBeforeTextChanged(CharSequence text, int start, int before,
|
||||
int after) {
|
||||
private void sendBeforeTextChanged(CharSequence text, int start, int before, int after) {
|
||||
if (mListeners != null) {
|
||||
final ArrayList<TextWatcher> list = mListeners;
|
||||
final int count = list.size();
|
||||
@@ -7431,14 +7431,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
list.get(i).beforeTextChanged(text, start, before, after);
|
||||
}
|
||||
}
|
||||
|
||||
// The spans that are inside or intersect the modified region no longer make sense
|
||||
removeIntersectingSpans(start, start + before, SpellCheckSpan.class);
|
||||
removeIntersectingSpans(start, start + before, SuggestionSpan.class);
|
||||
}
|
||||
|
||||
// Removes all spans that are inside or actually overlap the start..end range
|
||||
private <T> void removeIntersectingSpans(int start, int end, Class<T> type) {
|
||||
if (!(mText instanceof Editable)) return;
|
||||
Editable text = (Editable) mText;
|
||||
|
||||
T[] spans = text.getSpans(start, end, type);
|
||||
final int length = spans.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
final int s = text.getSpanStart(spans[i]);
|
||||
final int e = text.getSpanEnd(spans[i]);
|
||||
if (e == start || s == end) break;
|
||||
text.removeSpan(spans[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not private so it can be called from an inner class without going
|
||||
* through a thunk.
|
||||
*/
|
||||
void sendOnTextChanged(CharSequence text, int start, int before,
|
||||
int after) {
|
||||
void sendOnTextChanged(CharSequence text, int start, int before, int after) {
|
||||
if (mListeners != null) {
|
||||
final ArrayList<TextWatcher> list = mListeners;
|
||||
final int count = list.size();
|
||||
@@ -7486,6 +7504,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
sendOnTextChanged(buffer, start, before, after);
|
||||
onTextChanged(buffer, start, before, after);
|
||||
|
||||
// The WordIterator text change listener may be called after this one.
|
||||
// Make sure this changed text is rescanned before the iterator is used on it.
|
||||
getWordIterator().forceUpdate();
|
||||
updateSpellCheckSpans(start, start + after);
|
||||
|
||||
// Hide the controllers if the amount of content changed
|
||||
if (before != after) {
|
||||
hideControllers();
|
||||
@@ -7573,7 +7596,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (what instanceof ParcelableSpan) {
|
||||
// If this is a span that can be sent to a remote process,
|
||||
// the current extract editor would be interested in it.
|
||||
@@ -7603,10 +7626,102 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (what instanceof SpellCheckSpan) {
|
||||
if (newStart < 0) {
|
||||
getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what);
|
||||
} else if (oldStart < 0) {
|
||||
getSpellChecker().addSpellCheckSpan((SpellCheckSpan) what);
|
||||
}
|
||||
}
|
||||
|
||||
if (what instanceof SuggestionSpan) {
|
||||
if (newStart < 0) {
|
||||
Log.d("spellcheck", "REMOVE suggspan " + mText.subSequence(oldStart, oldEnd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ChangeWatcher
|
||||
implements TextWatcher, SpanWatcher {
|
||||
/**
|
||||
* Create new SpellCheckSpans on the modified region.
|
||||
*/
|
||||
private void updateSpellCheckSpans(int start, int end) {
|
||||
if (!(mText instanceof Editable) || !isSuggestionsEnabled()) return;
|
||||
Editable text = (Editable) mText;
|
||||
|
||||
WordIterator wordIterator = getWordIterator();
|
||||
wordIterator.setCharSequence(text);
|
||||
|
||||
// Move back to the beginning of the current word, if any
|
||||
int wordStart = wordIterator.preceding(start);
|
||||
int wordEnd;
|
||||
if (wordStart == BreakIterator.DONE) {
|
||||
wordEnd = wordIterator.following(start);
|
||||
if (wordEnd != BreakIterator.DONE) {
|
||||
wordStart = wordIterator.getBeginning(wordEnd);
|
||||
}
|
||||
} else {
|
||||
wordEnd = wordIterator.getEnd(wordStart);
|
||||
}
|
||||
if (wordEnd == BreakIterator.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate over the newly added text and schedule new SpellCheckSpans
|
||||
while (wordStart <= end) {
|
||||
if (wordEnd >= start) {
|
||||
// A word across the interval boundaries must remove boundary edition spans
|
||||
if (wordStart < start && wordEnd > start) {
|
||||
removeEditionSpansAt(start, text);
|
||||
}
|
||||
|
||||
if (wordStart < end && wordEnd > end) {
|
||||
removeEditionSpansAt(end, text);
|
||||
}
|
||||
|
||||
// Do not create new boundary spans if they already exist
|
||||
boolean createSpellCheckSpan = true;
|
||||
if (wordEnd == start) {
|
||||
SpellCheckSpan[] spellCheckSpans = text.getSpans(start, start,
|
||||
SpellCheckSpan.class);
|
||||
if (spellCheckSpans.length > 0) createSpellCheckSpan = false;
|
||||
}
|
||||
|
||||
if (wordStart == end) {
|
||||
SpellCheckSpan[] spellCheckSpans = text.getSpans(end, end,
|
||||
SpellCheckSpan.class);
|
||||
if (spellCheckSpans.length > 0) createSpellCheckSpan = false;
|
||||
}
|
||||
|
||||
if (createSpellCheckSpan) {
|
||||
text.setSpan(new SpellCheckSpan(), wordStart, wordEnd,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
// iterate word by word
|
||||
wordEnd = wordIterator.following(wordEnd);
|
||||
if (wordEnd == BreakIterator.DONE) return;
|
||||
wordStart = wordIterator.getBeginning(wordEnd);
|
||||
if (wordStart == BreakIterator.DONE) {
|
||||
Log.e(LOG_TAG, "Unable to find word beginning from " + wordEnd + "in " + mText);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeEditionSpansAt(int offset, Editable text) {
|
||||
SuggestionSpan[] suggestionSpans = text.getSpans(offset, offset, SuggestionSpan.class);
|
||||
for (int i = 0; i < suggestionSpans.length; i++) {
|
||||
text.removeSpan(suggestionSpans[i]);
|
||||
}
|
||||
SpellCheckSpan[] spellCheckSpans = text.getSpans(offset, offset, SpellCheckSpan.class);
|
||||
for (int i = 0; i < spellCheckSpans.length; i++) {
|
||||
text.removeSpan(spellCheckSpans[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private class ChangeWatcher implements TextWatcher, SpanWatcher {
|
||||
|
||||
private CharSequence mBeforeText;
|
||||
|
||||
@@ -7631,8 +7746,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
TextView.this.handleTextChanged(buffer, start, before, after);
|
||||
|
||||
if (AccessibilityManager.getInstance(mContext).isEnabled() &&
|
||||
(isFocused() || isSelected() &&
|
||||
isShown())) {
|
||||
(isFocused() || isSelected() && isShown())) {
|
||||
sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after);
|
||||
mBeforeText = null;
|
||||
}
|
||||
@@ -7642,8 +7756,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
if (DEBUG_EXTRACT) Log.v(LOG_TAG, "afterTextChanged: " + buffer);
|
||||
TextView.this.sendAfterTextChanged(buffer);
|
||||
|
||||
if (MetaKeyKeyListener.getMetaState(buffer,
|
||||
MetaKeyKeyListener.META_SELECTING) != 0) {
|
||||
if (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) {
|
||||
MetaKeyKeyListener.stopSelecting(TextView.this, buffer);
|
||||
}
|
||||
}
|
||||
@@ -7841,17 +7954,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
if (mInputContentType != null) {
|
||||
mInputContentType.enterDown = false;
|
||||
}
|
||||
|
||||
hideControllers();
|
||||
removeAllSuggestionSpans();
|
||||
|
||||
removeSpans(0, mText.length(), SuggestionSpan.class);
|
||||
removeSpans(0, mText.length(), SpellCheckSpan.class);
|
||||
}
|
||||
|
||||
startStopMarquee(hasWindowFocus);
|
||||
}
|
||||
|
||||
private void removeAllSuggestionSpans() {
|
||||
private void removeSpans(int start, int end, Class<?> type) {
|
||||
if (mText instanceof Editable) {
|
||||
Editable editable = ((Editable) mText);
|
||||
SuggestionSpan[] spans = editable.getSpans(0, mText.length(), SuggestionSpan.class);
|
||||
Object[] spans = editable.getSpans(start, end, type);
|
||||
final int length = spans.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
editable.removeSpan(spans[i]);
|
||||
@@ -7969,6 +8085,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
@@ -7979,12 +8097,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
return superResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if the cursor/current selection overlaps a {@link SuggestionSpan}.
|
||||
*/
|
||||
private boolean isCursorInsideSuggestionSpan() {
|
||||
if (!(mText instanceof Spannable)) return false;
|
||||
|
||||
SuggestionSpan[] suggestionSpans = ((Spannable) mText).getSpans(getSelectionStart(),
|
||||
getSelectionEnd(), SuggestionSpan.class);
|
||||
return (suggestionSpans.length > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if the cursor is inside an {@link SuggestionSpan} with
|
||||
* {@link SuggestionSpan#FLAG_EASY_CORRECT} set.
|
||||
*/
|
||||
private boolean isCursorInsideEasyCorrectionSpan() {
|
||||
Spannable spannable = (Spannable) TextView.this.mText;
|
||||
Spannable spannable = (Spannable) mText;
|
||||
SuggestionSpan[] suggestionSpans = spannable.getSpans(getSelectionStart(),
|
||||
getSelectionEnd(), SuggestionSpan.class);
|
||||
for (int i = 0; i < suggestionSpans.length; i++) {
|
||||
@@ -8445,16 +8574,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
selectionStart = ((Spanned) mText).getSpanStart(url);
|
||||
selectionEnd = ((Spanned) mText).getSpanEnd(url);
|
||||
} else {
|
||||
if (mWordIterator == null) {
|
||||
mWordIterator = new WordIterator();
|
||||
}
|
||||
// WordIerator handles text changes, this is a no-op if text in unchanged.
|
||||
mWordIterator.setCharSequence(mText);
|
||||
WordIterator wordIterator = getWordIterator();
|
||||
// WordIterator handles text changes, this is a no-op if text in unchanged.
|
||||
wordIterator.setCharSequence(mText);
|
||||
|
||||
selectionStart = mWordIterator.getBeginning(minOffset);
|
||||
selectionStart = wordIterator.getBeginning(minOffset);
|
||||
if (selectionStart == BreakIterator.DONE) return false;
|
||||
|
||||
selectionEnd = mWordIterator.getEnd(maxOffset);
|
||||
selectionEnd = wordIterator.getEnd(maxOffset);
|
||||
if (selectionEnd == BreakIterator.DONE) return false;
|
||||
}
|
||||
|
||||
@@ -8462,6 +8589,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
return true;
|
||||
}
|
||||
|
||||
WordIterator getWordIterator() {
|
||||
if (mWordIterator == null) {
|
||||
mWordIterator = new WordIterator();
|
||||
}
|
||||
return mWordIterator;
|
||||
}
|
||||
|
||||
private SpellChecker getSpellChecker() {
|
||||
if (mSpellChecker == null) {
|
||||
mSpellChecker = new SpellChecker(this);
|
||||
}
|
||||
return mSpellChecker;
|
||||
}
|
||||
|
||||
private long getLastTouchOffsets() {
|
||||
int minOffset, maxOffset;
|
||||
|
||||
@@ -8790,7 +8931,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
final int offset = getOffsetForPosition(mLastDownPositionX, mLastDownPositionY);
|
||||
stopSelectionActionMode();
|
||||
Selection.setSelection((Spannable) mText, offset);
|
||||
getInsertionController().showImmediately();
|
||||
getInsertionController().showWithActionPopup();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
@@ -9067,10 +9208,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
|
||||
private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnClickListener {
|
||||
private static final int MAX_NUMBER_SUGGESTIONS = 5;
|
||||
private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
|
||||
private static final int NO_SUGGESTIONS = -1;
|
||||
private static final float AVERAGE_HIGHLIGHTS_PER_SUGGESTION = 1.4f;
|
||||
private WordIterator mSuggestionWordIterator;
|
||||
private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan[0];
|
||||
private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan
|
||||
[(int) (AVERAGE_HIGHLIGHTS_PER_SUGGESTION * MAX_NUMBER_SUGGESTIONS)];
|
||||
|
||||
@Override
|
||||
protected void createPopupWindow() {
|
||||
@@ -9149,9 +9292,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
@Override
|
||||
public void show() {
|
||||
if (!(mText instanceof Editable)) return;
|
||||
updateSuggestions();
|
||||
|
||||
super.show();
|
||||
if (updateSuggestions()) {
|
||||
super.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -9179,7 +9323,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSuggestions() {
|
||||
private boolean updateSuggestions() {
|
||||
Spannable spannable = (Spannable)TextView.this.mText;
|
||||
SuggestionSpan[] suggestionSpans = getSuggestionSpans();
|
||||
|
||||
@@ -9217,22 +9361,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
}
|
||||
|
||||
if (totalNbSuggestions == 0) {
|
||||
// TODO Replace by final text, use a dedicated layout, add a fade out timer...
|
||||
TextView textView = (TextView) mContentView.getChildAt(0);
|
||||
textView.setText("No suggestions available");
|
||||
SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
|
||||
suggestionInfo.spanStart = NO_SUGGESTIONS;
|
||||
totalNbSuggestions++;
|
||||
} else {
|
||||
if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
|
||||
((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
if (totalNbSuggestions == 0) return false;
|
||||
|
||||
for (int i = 0; i < totalNbSuggestions; i++) {
|
||||
final TextView textView = (TextView) mContentView.getChildAt(i);
|
||||
highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
|
||||
}
|
||||
if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
|
||||
((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
for (int i = 0; i < totalNbSuggestions; i++) {
|
||||
final TextView textView = (TextView) mContentView.getChildAt(i);
|
||||
highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
|
||||
}
|
||||
|
||||
for (int i = 0; i < totalNbSuggestions; i++) {
|
||||
@@ -9241,6 +9378,27 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
for (int i = totalNbSuggestions; i < MAX_NUMBER_SUGGESTIONS; i++) {
|
||||
mContentView.getChildAt(i).setVisibility(GONE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onDictionarySuggestionsReceived(String[] suggestions) {
|
||||
if (suggestions.length == 0) {
|
||||
// TODO Actual implementation of this feature
|
||||
suggestions = new String[] {"Add to dictionary"};
|
||||
}
|
||||
|
||||
WordIterator wordIterator = getWordIterator();
|
||||
wordIterator.setCharSequence(mText);
|
||||
|
||||
final int pos = getSelectionStart();
|
||||
int wordStart = wordIterator.getBeginning(pos);
|
||||
int wordEnd = wordIterator.getEnd(pos);
|
||||
|
||||
SuggestionSpan suggestionSpan = new SuggestionSpan(getContext(), suggestions, 0);
|
||||
((Editable) mText).setSpan(suggestionSpan, wordStart, wordEnd,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
show();
|
||||
}
|
||||
|
||||
private long[] getWordLimits(CharSequence text) {
|
||||
@@ -9422,6 +9580,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
final String originalText = mText.subSequence(spanStart, spanEnd).toString();
|
||||
((Editable) mText).replace(spanStart, spanEnd, suggestion);
|
||||
|
||||
// A replacement on a misspelled text removes the misspelled flag.
|
||||
// TODO restore the flag if the misspelled word is selected back?
|
||||
int suggestionSpanFlags = suggestionInfo.suggestionSpan.getFlags();
|
||||
if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) {
|
||||
suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED);
|
||||
suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT);
|
||||
suggestionInfo.suggestionSpan.setFlags(suggestionSpanFlags);
|
||||
}
|
||||
|
||||
// Notify source IME of the suggestion pick. Do this before swaping texts.
|
||||
if (!TextUtils.isEmpty(
|
||||
suggestionInfo.suggestionSpan.getNotificationTargetClassName())) {
|
||||
@@ -9471,53 +9638,46 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
|
||||
boolean areSuggestionsShown() {
|
||||
return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing();
|
||||
}
|
||||
}
|
||||
|
||||
void onDictionarySuggestionsReceived(String[] suggestions) {
|
||||
if (mSuggestionsPopupWindow != null) {
|
||||
mSuggestionsPopupWindow.onDictionarySuggestionsReceived(suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some parts of the text can have alternate suggestion text attached. This is typically done by
|
||||
* the IME by adding {@link SuggestionSpan}s to the text.
|
||||
* Return whether or not suggestions are enabled on this TextView. The suggestions are generated
|
||||
* by the IME or by the spell checker as the user types. This is done by adding
|
||||
* {@link SuggestionSpan}s to the text.
|
||||
*
|
||||
* When suggestions are enabled (default), this list of suggestions will be displayed when the
|
||||
* user double taps on these parts of the text. No suggestions are displayed when this value is
|
||||
* false. Use {@link #setSuggestionsEnabled(boolean)} to change this value.
|
||||
* user asks for them on these parts of the text. This value depends on the inputType of this
|
||||
* TextView.
|
||||
*
|
||||
* Note that suggestions are only enabled for a subset of input types. In addition to setting
|
||||
* this flag to <code>true</code> using {@link #setSuggestionsEnabled(boolean)} or the
|
||||
* <code>android:suggestionsEnabled</code> xml attribute, this method will return
|
||||
* <code>true</code> only if the class of your input type is {@link InputType#TYPE_CLASS_TEXT}.
|
||||
* In addition, the type variation must also be one of
|
||||
* The class of the input type must be {@link InputType#TYPE_CLASS_TEXT}.
|
||||
*
|
||||
* In addition, the type variation must be one of
|
||||
* {@link InputType#TYPE_TEXT_VARIATION_NORMAL},
|
||||
* {@link InputType#TYPE_TEXT_VARIATION_EMAIL_SUBJECT},
|
||||
* {@link InputType#TYPE_TEXT_VARIATION_LONG_MESSAGE},
|
||||
* {@link InputType#TYPE_TEXT_VARIATION_SHORT_MESSAGE} or
|
||||
* {@link InputType#TYPE_TEXT_VARIATION_WEB_EDIT_TEXT}.
|
||||
*
|
||||
* @return true if the suggestions popup window is enabled.
|
||||
* And finally, the {@link InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS} flag must <i>not</i> be set.
|
||||
*
|
||||
* @attr ref android.R.styleable#TextView_suggestionsEnabled
|
||||
* @return true if the suggestions popup window is enabled, based on the inputType.
|
||||
*/
|
||||
public boolean isSuggestionsEnabled() {
|
||||
if (!mSuggestionsEnabled) return false;
|
||||
if ((mInputType & InputType.TYPE_MASK_CLASS) != InputType.TYPE_CLASS_TEXT) return false;
|
||||
if ((mInputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) > 0) return false;
|
||||
|
||||
final int variation = mInputType & EditorInfo.TYPE_MASK_VARIATION;
|
||||
if (variation == EditorInfo.TYPE_TEXT_VARIATION_NORMAL ||
|
||||
return (variation == EditorInfo.TYPE_TEXT_VARIATION_NORMAL ||
|
||||
variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT ||
|
||||
variation == EditorInfo.TYPE_TEXT_VARIATION_LONG_MESSAGE ||
|
||||
variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE ||
|
||||
variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the suggestion popup. See {@link #isSuggestionsEnabled()}.
|
||||
*
|
||||
* @param enabled Whether or not suggestions are enabled.
|
||||
*
|
||||
* @attr ref android.R.styleable#TextView_suggestionsEnabled
|
||||
*/
|
||||
public void setSuggestionsEnabled(boolean enabled) {
|
||||
mSuggestionsEnabled = enabled;
|
||||
variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9787,11 +9947,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
@Override
|
||||
public void show() {
|
||||
boolean canPaste = canPaste();
|
||||
boolean suggestionsEnabled = isSuggestionsEnabled();
|
||||
boolean canSuggest = isSuggestionsEnabled() && isCursorInsideSuggestionSpan();
|
||||
mPasteTextView.setVisibility(canPaste ? View.VISIBLE : View.GONE);
|
||||
mReplaceTextView.setVisibility(suggestionsEnabled ? View.VISIBLE : View.GONE);
|
||||
mReplaceTextView.setVisibility(canSuggest ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (!canPaste && !suggestionsEnabled) return;
|
||||
if (!canPaste && !canSuggest) return;
|
||||
|
||||
super.show();
|
||||
}
|
||||
@@ -9802,6 +9962,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
onTextContextMenuItem(ID_PASTE);
|
||||
hide();
|
||||
} else if (view == mReplaceTextView) {
|
||||
final int middle = (getSelectionStart() + getSelectionEnd()) / 2;
|
||||
stopSelectionActionMode();
|
||||
Selection.setSelection((Spannable) mText, middle);
|
||||
showSuggestions();
|
||||
}
|
||||
}
|
||||
@@ -10133,17 +10296,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
hideAfterDelay();
|
||||
}
|
||||
|
||||
public void show(int delayBeforeShowActionPopup) {
|
||||
show();
|
||||
|
||||
final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime;
|
||||
if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) {
|
||||
delayBeforeShowActionPopup = 0;
|
||||
showActionPopupWindow(0);
|
||||
}
|
||||
showActionPopupWindow(delayBeforeShowActionPopup);
|
||||
|
||||
hideAfterDelay();
|
||||
}
|
||||
|
||||
public void showWithActionPopup() {
|
||||
show();
|
||||
showActionPopupWindow(0);
|
||||
}
|
||||
|
||||
private void hideAfterDelay() {
|
||||
@@ -10194,7 +10358,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
// Tapping on the handle dismisses the displayed action popup
|
||||
mActionPopupWindow.hide();
|
||||
} else {
|
||||
show(0);
|
||||
showWithActionPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10349,16 +10513,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
|
||||
private class InsertionPointCursorController implements CursorController {
|
||||
private static final int DELAY_BEFORE_PASTE_ACTION = 1600;
|
||||
|
||||
private InsertionHandleView mHandle;
|
||||
|
||||
public void show() {
|
||||
getHandle().show(DELAY_BEFORE_PASTE_ACTION);
|
||||
getHandle().show();
|
||||
}
|
||||
|
||||
public void showImmediately() {
|
||||
getHandle().show(0);
|
||||
public void showWithActionPopup() {
|
||||
getHandle().showWithActionPopup();
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
@@ -10390,7 +10552,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
}
|
||||
|
||||
private class SelectionModifierCursorController implements CursorController {
|
||||
private static final int DELAY_BEFORE_REPLACE_ACTION = 1200;
|
||||
private static final int DELAY_BEFORE_REPLACE_ACTION = 200; // milliseconds
|
||||
// The cursor controller handles, lazily created when shown.
|
||||
private SelectionStartHandleView mStartHandle;
|
||||
private SelectionEndHandleView mEndHandle;
|
||||
@@ -10879,8 +11041,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
private int mAutoLinkMask;
|
||||
private boolean mLinksClickable = true;
|
||||
|
||||
private float mSpacingMult = 1;
|
||||
private float mSpacingAdd = 0;
|
||||
private float mSpacingMult = 1.0f;
|
||||
private float mSpacingAdd = 0.0f;
|
||||
private boolean mTextIsSelectable = false;
|
||||
|
||||
private static final int LINES = 1;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 709 B After Width: | Height: | Size: 626 B |
Binary file not shown.
|
Before Width: | Height: | Size: 945 B After Width: | Height: | Size: 435 B |
@@ -151,7 +151,6 @@
|
||||
android:background="@drawable/lockscreen_password_field_dark"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:imeOptions="flagNoFullscreen|actionDone"
|
||||
android:suggestionsEnabled="false"
|
||||
/>
|
||||
|
||||
<ImageView android:id="@+id/switch_ime_button"
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textColor="#ffffffff"
|
||||
android:imeOptions="actionDone"
|
||||
android:suggestionsEnabled="false"/>
|
||||
/>
|
||||
|
||||
<ImageView android:id="@+id/switch_ime_button"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -881,10 +881,6 @@
|
||||
Default value is false. EditText content is always selectable. -->
|
||||
<attr name="textIsSelectable" format="boolean" />
|
||||
|
||||
<!-- When true, IME suggestions will be displayed when the user double taps on editable text.
|
||||
The default value is true. -->
|
||||
<attr name="suggestionsEnabled" format="boolean" />
|
||||
|
||||
<!-- Where to ellipsize text. -->
|
||||
<attr name="ellipsize">
|
||||
<enum name="none" value="0" />
|
||||
@@ -3148,8 +3144,6 @@
|
||||
|
||||
<!-- Indicates that the content of a non-editable text can be selected. -->
|
||||
<attr name="textIsSelectable" />
|
||||
<!-- Suggestions will be displayed when the user double taps on editable text. -->
|
||||
<attr name="suggestionsEnabled" />
|
||||
<!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
|
||||
<attr name="textAllCaps" />
|
||||
</declare-styleable>
|
||||
|
||||
@@ -1717,8 +1717,6 @@
|
||||
<public type="attr" name="textSuggestionsWindowStyle" />
|
||||
<public type="attr" name="textEditSuggestionItemLayout" />
|
||||
|
||||
<public type="attr" name="suggestionsEnabled" />
|
||||
|
||||
<public type="attr" name="rowCount" />
|
||||
<public type="attr" name="rowOrderPreserved" />
|
||||
<public type="attr" name="columnCount" />
|
||||
|
||||
@@ -2470,7 +2470,7 @@
|
||||
<string name="paste">Paste</string>
|
||||
|
||||
<!-- Item on EditText context menu. This action is used to replace the current word by other suggested words, suggested by the IME or the spell checker -->
|
||||
<string name="replace">Replace</string>
|
||||
<string name="replace">Replace\u2026</string>
|
||||
|
||||
<!-- Item on EditText context menu. This action is used to copy a URL from the edit field into the clipboard. -->
|
||||
<string name="copyUrl">Copy URL</string>
|
||||
|
||||
Reference in New Issue
Block a user