2525import android .content .res .TypedArray ;
2626import android .content .res .XmlResourceParser ;
2727import android .graphics .Color ;
28+ import android .os .Build ;
2829import android .util .DisplayMetrics ;
2930import android .util .Log ;
3031import android .util .Xml ;
3637
3738/*
3839 A container that holds rows of keys, to be declared in a layout XML.
40+ It also determines the vertical placement of the stroke sequence bar
41+ and the candidates bar, which are separate entities to be placed
42+ above the keyboard (in the parent input container).
3943*/
4044public class Keyboard {
4145
42- private static final int DEFAULT_KEYBOARD_FILL_COLOUR = Color .BLACK ;
46+ private static final int STROKE_SEQUENCE_BAR_HEIGHT_DP = 24 ;
47+ private final int strokeSequenceBarHeightPx ;
48+ private static final int CANDIDATES_BAR_HEIGHT_DP = 36 ;
49+ private final int candidatesBarHeightPx ;
4350 public static final int KEYBOARD_GUTTER_HEIGHT_PX = 1 ;
4451
52+ private static final int DEFAULT_KEYBOARD_FILL_COLOUR = Color .BLACK ;
53+
4554 private static final float KEYBOARD_HEIGHT_MAX_FRACTION = 0.5f ;
4655
4756 private static final float DEFAULT_KEY_WIDTH_FRACTION = 0.1f ;
@@ -62,6 +71,11 @@ public class Keyboard {
6271 private static final int DEFAULT_KEY_PREVIEW_MARGIN_Y_DP = 16 ;
6372 private final int defaultKeyPreviewMarginYPx ;
6473
74+ // Parent input container properties
75+ private int popupBufferZoneHeight ;
76+ private int parentInputContainerHeight ;
77+ private int parentInputContainerTouchableTopY ;
78+
6579 // Keyboard properties
6680 private int width ;
6781 private int height ;
@@ -88,14 +102,23 @@ public class Keyboard {
88102 private final int screenWidth ;
89103 private final int screenHeight ;
90104
91- public Keyboard (final Context context , final int layoutResourceId ) {
92-
105+ public Keyboard (
106+ final Context context ,
107+ final int layoutResourceId ,
108+ final boolean isFullscreenMode
109+ )
110+ {
93111 final DisplayMetrics displayMetrics =
94112 context .getResources ().getDisplayMetrics ();
95113
96114 screenWidth = displayMetrics .widthPixels ;
97115 screenHeight = displayMetrics .heightPixels ;
98116
117+ strokeSequenceBarHeightPx =
118+ (int ) Valuey .pxFromDp (STROKE_SEQUENCE_BAR_HEIGHT_DP , displayMetrics );
119+ candidatesBarHeightPx =
120+ (int ) Valuey .pxFromDp (CANDIDATES_BAR_HEIGHT_DP , displayMetrics );
121+
99122 defaultKeyHeightPx =
100123 (int ) Valuey .pxFromDp (DEFAULT_KEY_HEIGHT_DP , displayMetrics );
101124 defaultKeyBorderThicknessPx =
@@ -108,13 +131,25 @@ public Keyboard(final Context context, final int layoutResourceId) {
108131 keyList = new ArrayList <>();
109132
110133 loadKeyboard (context , context .getResources ().getXml (layoutResourceId ));
111- adjustKeyboardVertically ();
134+ adjustKeyboardVertically (isFullscreenMode );
112135 }
113136
114137 public List <Key > getKeyList () {
115138 return keyList ;
116139 }
117140
141+ public int getPopupBufferZoneHeight () {
142+ return popupBufferZoneHeight ;
143+ }
144+
145+ public int getParentInputContainerHeight () {
146+ return parentInputContainerHeight ;
147+ }
148+
149+ public int getParentInputContainerTouchableTopY () {
150+ return parentInputContainerTouchableTopY ;
151+ }
152+
118153 public int getWidth () {
119154 return width ;
120155 }
@@ -142,7 +177,7 @@ private void loadKeyboard(
142177 boolean inRow = false ;
143178
144179 int x = 0 ;
145- int y = 0 ;
180+ int y = KEYBOARD_GUTTER_HEIGHT_PX ;
146181 Key key = null ;
147182 Row row = null ;
148183
@@ -200,20 +235,42 @@ else if (inRow) {
200235 }
201236 }
202237
203- private void adjustKeyboardVertically () {
238+ private void adjustKeyboardVertically (final boolean isFullscreenMode ) {
204239
205240 final float keyboardHeightCorrectionFactor =
206241 Math .min (1 , KEYBOARD_HEIGHT_MAX_FRACTION * screenHeight / height );
207242
208243 for (Key key : keyList ) {
209244 key .y *= keyboardHeightCorrectionFactor ;
210- key .y += KEYBOARD_GUTTER_HEIGHT_PX ;
211245 key .height *= keyboardHeightCorrectionFactor ;
212246 key .textOffsetY *= keyboardHeightCorrectionFactor ;
213247 key .previewMarginY *= keyboardHeightCorrectionFactor ;
214248 }
215-
216249 height *= keyboardHeightCorrectionFactor ;
250+
251+ if (Build .VERSION .SDK_INT == 28 && !isFullscreenMode ) {
252+ // API level 28 is dumb, see <https://stackoverflow.com/q/52929466>
253+ int popupBufferZoneTopY =
254+ -(strokeSequenceBarHeightPx + candidatesBarHeightPx );
255+ for (Key key : keyList ) {
256+ final int keyPreviewHeight =
257+ (int ) (key .previewMagnification * key .height );
258+ popupBufferZoneTopY = Math .min (
259+ key .y - keyPreviewHeight - key .previewMarginY ,
260+ popupBufferZoneTopY
261+ );
262+ }
263+ popupBufferZoneHeight = -popupBufferZoneTopY ;
264+ }
265+ else {
266+ popupBufferZoneHeight = candidatesBarHeightPx ;
267+ }
268+ for (Key key : keyList ) {
269+ key .y += popupBufferZoneHeight ;
270+ }
271+ parentInputContainerHeight = height + popupBufferZoneHeight ;
272+ parentInputContainerTouchableTopY =
273+ Math .max (0 , popupBufferZoneHeight - candidatesBarHeightPx );
217274 }
218275
219276 private void parseKeyboardAttributes (
0 commit comments