Skip to content

Commit 8b17b22

Browse files
committed
Merge branch 'preview-popups'
Implements key preview popups. A single instance of PopupWindow is shown/moved/dismissed as required. Unfortunately this suffers from the same drawbacks as mentioned in <florisboard/florisboard#108>: * Popups feel laggy * Popups don't appear when rapidly alternating between keys --- Also there seems to be some sort of layout transition animation going on when dragging a pointer between keys of different size (e.g. moving from "3" to "STROKE_1"). TODO: figure out how to eliminate this animation.
2 parents ed22cd0 + ce1872b commit 8b17b22

12 files changed

Lines changed: 331 additions & 41 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
## [Unreleased]
55

6+
- Implemented key preview popups
67
- Improved organisation of utility classes
78

89

app/src/main/java/io/github/yawnoc/strokeinput/InputContainer.java

Lines changed: 81 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,17 @@
3131
import android.os.Looper;
3232
import android.os.Message;
3333
import android.util.AttributeSet;
34+
import android.view.Gravity;
3435
import android.view.MotionEvent;
3536
import android.view.View;
37+
import android.widget.LinearLayout;
38+
import android.widget.PopupWindow;
3639
import android.widget.Toast;
3740

3841
import androidx.core.graphics.ColorUtils;
3942

43+
import io.github.yawnoc.utilities.Valuey;
44+
4045
/*
4146
A container that holds:
4247
- Candidates bar
@@ -58,13 +63,13 @@ public class InputContainer
5863

5964
private static final int SWIPE_ACTIVATION_DISTANCE = 40;
6065

61-
private static final int SHIFT_DISABLED = 0;
66+
public static final int SHIFT_DISABLED = 0;
6267
private static final int SHIFT_SINGLE = 1;
6368
private static final int SHIFT_PERSISTENT = 2;
6469
private static final int SHIFT_INITIATED = 3;
6570
private static final int SHIFT_HELD = 4;
6671

67-
private static final String KEYBOARD_FONT = "stroke_input_keyboard.ttf";
72+
public static final String KEYBOARD_FONT = "stroke_input_keyboard.ttf";
6873

6974
private static final float COLOUR_LIGHTNESS_CUTOFF = 0.7f;
7075

@@ -97,11 +102,17 @@ public class InputContainer
97102
// Keyboard drawing
98103
private final Rect keyboardRectangle;
99104
private final Paint keyboardFillPaint;
105+
106+
// Key drawing
100107
private final Rect keyRectangle;
101108
private final Paint keyFillPaint;
102109
private final Paint keyBorderPaint;
103110
private final Paint keyTextPaint;
104111

112+
// Key preview
113+
private final KeyPreview keyPreview;
114+
private final PopupWindow keyPreviewPopup;
115+
105116
// Debugging
106117
private final Paint debugPaint;
107118
private final Toast debugToast;
@@ -129,6 +140,7 @@ public void handleMessage(Message message) {
129140
inputListener.onLongPress(activeKey.valueText);
130141
activeKey = null;
131142
activePointerId = NONEXISTENT_POINTER_ID;
143+
updateKeyPreview();
132144
invalidate();
133145
break;
134146
}
@@ -155,6 +167,13 @@ public void handleMessage(Message message) {
155167
);
156168
keyTextPaint.setTextAlign(Paint.Align.CENTER);
157169

170+
final int popup_size = LinearLayout.LayoutParams.WRAP_CONTENT;
171+
172+
keyPreview = new KeyPreview(context);
173+
keyPreviewPopup = new PopupWindow(keyPreview, popup_size, popup_size);
174+
keyPreviewPopup.setTouchable(false);
175+
keyPreviewPopup.setClippingEnabled(false);
176+
158177
debugPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
159178
debugPaint.setStyle(Paint.Style.STROKE);
160179

@@ -245,7 +264,7 @@ public void onDraw(final Canvas canvas) {
245264

246265
keyRectangle.set(0, 0, key.width, key.height);
247266

248-
int keyFillColour = key.keyFillColour;
267+
int keyFillColour = key.fillColour;
249268
if (
250269
key == activeKey
251270
||
@@ -260,22 +279,22 @@ public void onDraw(final Canvas canvas) {
260279
)
261280
)
262281
{
263-
keyFillColour = getContrastingColour(keyFillColour);
282+
keyFillColour = toPressedColour(keyFillColour);
264283
}
265284

266285
keyFillPaint.setColor(keyFillColour);
267-
keyBorderPaint.setColor(key.keyBorderColour);
268-
keyBorderPaint.setStrokeWidth(key.keyBorderThickness);
286+
keyBorderPaint.setColor(key.borderColour);
287+
keyBorderPaint.setStrokeWidth(key.borderThickness);
269288

270289
final int keyTextColour;
271290
if (key == activeKey && swipeModeIsActivated) {
272-
keyTextColour = key.keyTextSwipeColour;
291+
keyTextColour = key.textSwipeColour;
273292
}
274293
else {
275-
keyTextColour = key.keyTextColour;
294+
keyTextColour = key.textColour;
276295
}
277296
keyTextPaint.setColor(keyTextColour);
278-
keyTextPaint.setTextSize(key.keyTextSize);
297+
keyTextPaint.setTextSize(key.textSize);
279298

280299
final String keyDisplayText;
281300
if (debugModeIsActivated && key.valueText.equals("SPACE")) {
@@ -285,32 +304,24 @@ public void onDraw(final Canvas canvas) {
285304
: activeKey.valueText
286305
);
287306
}
288-
else if (shiftMode == SHIFT_DISABLED) {
289-
keyDisplayText = key.displayText;
290-
}
291307
else {
292-
keyDisplayText = key.valueTextShifted;
308+
keyDisplayText = key.shiftAwareDisplayText(shiftMode);
293309
}
294310

295311
final float keyTextX = (
296312
key.width / 2f
297-
+ key.keyTextOffsetX
313+
+ key.textOffsetX
298314
);
299315
final float keyTextY = (
300316
(key.height - keyTextPaint.ascent() - keyTextPaint.descent()) / 2f
301-
+ key.keyTextOffsetY
317+
+ key.textOffsetY
302318
);
303319

304320
canvas.translate(key.x, key.y);
305321

306322
canvas.drawRect(keyRectangle, keyFillPaint);
307323
canvas.drawRect(keyRectangle, keyBorderPaint);
308-
canvas.drawText(
309-
keyDisplayText,
310-
keyTextX,
311-
keyTextY,
312-
keyTextPaint
313-
);
324+
canvas.drawText(keyDisplayText, keyTextX, keyTextY, keyTextPaint);
314325

315326
canvas.translate(-key.x, -key.y);
316327
}
@@ -330,7 +341,7 @@ else if (shiftMode == SHIFT_DISABLED) {
330341
Lighten a dark colour and darken a light colour.
331342
Used for key press colour changes.
332343
*/
333-
private static int getContrastingColour(final int colour) {
344+
public static int toPressedColour(final int colour) {
334345

335346
final float[] colourHSL = new float[3];
336347
ColorUtils.colorToHSL(colour, colourHSL);
@@ -365,6 +376,7 @@ public boolean onTouchEvent(final MotionEvent event) {
365376
shiftPointerId = NONEXISTENT_POINTER_ID;
366377
activeKey = null;
367378
activePointerId = NONEXISTENT_POINTER_ID;
379+
updateKeyPreview();
368380
invalidate();
369381
return true;
370382
}
@@ -490,6 +502,7 @@ private void sendDownEvent(
490502
activePointerY = y;
491503

492504
sendAppropriateExtendedPressHandlerMessage(key);
505+
updateKeyPreview();
493506
invalidate();
494507
}
495508

@@ -520,6 +533,7 @@ else if (key == activeKey && isSwipeableKey(key)) {
520533
removeAllExtendedPressHandlerMessages();
521534
sendAppropriateExtendedPressHandlerMessage(key);
522535
resetKeyRepeatIntervalMilliseconds();
536+
updateKeyPreview();
523537
shouldRedrawKeyboard = true;
524538
}
525539

@@ -560,6 +574,7 @@ else if (key != null) {
560574
removeAllExtendedPressHandlerMessages();
561575
resetKeyRepeatIntervalMilliseconds();
562576
if (shouldRedrawKeyboard) {
577+
updateKeyPreview();
563578
invalidate();
564579
}
565580
}
@@ -575,6 +590,7 @@ private void sendShiftDownEvent(final int pointerId) {
575590
}
576591
shiftPointerId = pointerId;
577592

593+
updateKeyPreview();
578594
invalidate();
579595
}
580596

@@ -587,6 +603,7 @@ private void sendShiftMoveToEvent(final int pointerId) {
587603
activePointerId = NONEXISTENT_POINTER_ID;
588604

589605
removeAllExtendedPressHandlerMessages();
606+
updateKeyPreview();
590607
invalidate();
591608
}
592609

@@ -607,6 +624,7 @@ private void sendShiftMoveFromEvent(
607624
removeAllExtendedPressHandlerMessages();
608625
sendAppropriateExtendedPressHandlerMessage(key);
609626
resetKeyRepeatIntervalMilliseconds();
627+
updateKeyPreview();
610628
invalidate();
611629
}
612630

@@ -627,6 +645,7 @@ private void sendShiftUpEvent(boolean shouldRedrawKeyboard) {
627645
shiftPointerId = NONEXISTENT_POINTER_ID;
628646

629647
if (shouldRedrawKeyboard) {
648+
updateKeyPreview();
630649
invalidate();
631650
}
632651
}
@@ -650,6 +669,46 @@ private boolean isSwipeableKey(final Key key) {
650669
return key != null && key.isSwipeable;
651670
}
652671

672+
private void updateKeyPreview() {
673+
674+
if (activeKey == null || !activeKey.isPreviewable) {
675+
if (keyPreviewPopup.isShowing()) {
676+
keyPreviewPopup.dismiss();
677+
}
678+
return;
679+
}
680+
681+
keyPreview.update(activeKey, shiftMode);
682+
683+
final int previewWidth = keyPreview.width;
684+
final int previewHeight = keyPreview.height;
685+
final int previewMargin = activeKey.previewMargin;
686+
687+
final int keyboardLeftX = 0;
688+
final int keyboardRightX = keyboard.getWidth() - previewWidth;
689+
final int previewX =
690+
(int) Valuey.clipValueToRange(
691+
activeKey.x - (previewWidth - activeKey.width) / 2f,
692+
keyboardLeftX,
693+
keyboardRightX
694+
);
695+
final int previewY = activeKey.y - previewHeight - previewMargin;
696+
697+
if (keyPreviewPopup.isShowing()) {
698+
keyPreviewPopup.update(previewX, previewY, previewWidth, previewHeight);
699+
}
700+
else {
701+
keyPreviewPopup.setWidth(previewWidth);
702+
keyPreviewPopup.setHeight(previewHeight);
703+
keyPreviewPopup.showAtLocation(
704+
this,
705+
Gravity.NO_GRAVITY,
706+
previewX,
707+
previewY
708+
);
709+
}
710+
}
711+
653712
private void sendAppropriateExtendedPressHandlerMessage(
654713
final Key key
655714
)

0 commit comments

Comments
 (0)