Final Cleanup

This commit is contained in:
Matthew Lee 2025-12-02 16:16:48 -05:00
parent 6445a6bcb5
commit d955404307
7 changed files with 400 additions and 30 deletions

View file

@ -97,20 +97,13 @@ public class AdjustKeyboardHeightActivity extends BaseActivity {
break;
case MotionEvent.ACTION_MOVE:
// Get the touch position relative to the screen bottom
// The keyboard top should align with the touch point
int[] location = new int[2];
sampleKeyboard.getLocationOnScreen(location);
int viewBottom = location[1] + sampleKeyboard.getHeight();
int touchY = (int) event.getRawY();
// Calculate height: distance from touch point to bottom of screen
currentHeight = viewBottom - touchY;
// Apply lower and upper bounds on currentHeight
int minKeyboardHeight = KMManager.getKeyboardHeightMin(context);
int maxKeyboardHeight = KMManager.getKeyboardHeightMax(context);
currentHeight = Math.max(minKeyboardHeight, currentHeight);
currentHeight = Math.min(maxKeyboardHeight, currentHeight);
// Calculate height with bounds checking
currentHeight = KMManager.calculateKeyboardHeightFromTouch(context, touchY, viewBottom);
refreshSampleKeyboard(context);
break;
@ -136,25 +129,58 @@ public class AdjustKeyboardHeightActivity extends BaseActivity {
* @param context
*/
private void refreshSampleKeyboard(Context context) {
layoutParams.height = currentHeight;
sampleKeyboard.setLayoutParams(layoutParams);
if (layoutParams != null && sampleKeyboard != null) {
layoutParams.height = currentHeight;
sampleKeyboard.requestLayout();
// Update percentage display
String percentageText = KMManager.createKeyboardHeightString(
// Update percentage display based on current (unsaved) height
if (percentageDisplay != null) {
String percentageText = createLiveKeyboardHeightString(context);
percentageDisplay.setText(percentageText);
}
}
}
/**
* Create a string showing keyboard height percentages for both orientations.
* Uses the current (unsaved) height for the active orientation and saved height for the other.
* @param context Context
* @return String in format "100% Portrait | 100% Landscape"
*/
private String createLiveKeyboardHeightString(Context context) {
int currentOrientation = KMManager.getOrientation(context);
return KMManager.createKeyboardHeightString(
context,
currentHeight,
currentOrientation,
getString(R.string.portrait),
getString(R.string.landscape)
);
percentageDisplay.setText(percentageText);
}
@Override
protected void onPause() {
super.onPause();
// Ensure height is saved even if user switches tasks or navigates away abnormally
// This prevents the touch zone from being out of sync with the keyboard visual
if (currentHeight > 0) {
KMManager.applyKeyboardHeight(this, currentHeight);
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// IMPORTANT: Apply current height BEFORE switching orientations
// This ensures the old orientation's height is saved before loading the new one
if (currentHeight > 0) {
KMManager.applyKeyboardHeight(this, currentHeight);
}
layoutParams = sampleKeyboard.getLayoutParams();
// When the user rotates the device, restore currentHeight
// When the user rotates the device, restore currentHeight for the new orientation
currentHeight = KMManager.getKeyboardHeight(this);
refreshSampleKeyboard(this);
}

View file

@ -64,7 +64,7 @@
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="14sp"
android:textColor="@color/keyman_blue"
android:textColor="?android:attr/textColorSecondary"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="100% Portrait | 100% Landscape"
@ -83,7 +83,7 @@
android:clickable="true"
android:focusable="true"
android:contentDescription="@string/drag_the_keyboard"
app:layout_constraintTop_toBottomOf="@id/keyboard_height_percentage"
app:layout_constraintBottom_toTopOf="@id/sample_keyboard"
app:layout_constraintStart_toStartOf="parent">
<!-- Up arrow on left -->
@ -129,15 +129,7 @@
android:contentDescription="@string/adjust_keyboard_height"
android:scaleType="fitXY"
android:src="@drawable/blank_osk"
android:background="@drawable/dash_border"
android:layout_alignParentBottom="true"
android:paddingStart="@dimen/blank_osk_padding"
android:paddingEnd="@dimen/blank_osk_padding"
android:paddingTop="@dimen/blank_osk_padding"
android:paddingBottom="@dimen/blank_osk_padding"
app:layout_constraintTop_toBottomOf="@id/resize_handle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="1.0" />
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -2619,16 +2619,34 @@ public final class KMManager {
}
/**
* Get keyboard height as percentage of default for specified orientation
* Get keyboard height as percentage of default for specified orientation.
*
* <p>The percentage is calculated using Math.ceil() to round up to the nearest integer.
* This ensures consistency with {@link #createKeyboardHeightString(Context, String, String)}
* and prevents percentages from being displayed as 0%.
*
* <p>Example: If current height is 288px and default is 200px:
* <pre>
* percentage = ceil(288 * 100.0 / 200) = ceil(144.0) = 144%
* </pre>
*
* @param context Context
* @param orientation Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE
* @return Percentage (e.g., 120 for 120%)
* @param orientation Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE
* @return Percentage (e.g., 120 for 120%), minimum value is 100
* @see #getKeyboardHeight(Context, int)
* @see #getDefaultKeyboardHeight(int)
* @see #createKeyboardHeightString(Context, String, String)
*/
public static int getKeyboardHeightPercentage(Context context, int orientation) {
int currentHeight = getKeyboardHeight(context, orientation);
int defaultHeight = getDefaultKeyboardHeight(orientation);
if (defaultHeight == 0) return 100;
return (int) Math.round((currentHeight * 100.0) / defaultHeight);
// Use Math.ceil to match createKeyboardHeightString() calculation
int percent = (int) Math.ceil((currentHeight * 100.0) / defaultHeight);
if (percent == 0) {
percent = 100;
}
return percent;
}
/**
@ -2682,6 +2700,114 @@ public final class KMManager {
return percentages;
}
/**
* Create a string showing keyboard height percentages for both orientations.
* Uses a live (unsaved) height for the specified orientation and reads saved height for the other.
* This is useful for displaying real-time percentages during keyboard height adjustment.
*
* <p>The percentage is calculated using Math.ceil() to ensure consistency with
* {@link #createKeyboardHeightString(Context, String, String)} and
* {@link #getKeyboardHeightPercentage(Context, int)}.
*
* <p>Example usage during drag operation:
* <pre>{@code
* // User is dragging to adjust portrait height
* int currentOrientation = KMManager.getOrientation(context);
* String display = KMManager.createKeyboardHeightString(
* context,
* currentHeight, // Live height being adjusted
* currentOrientation,
* "Portrait",
* "Landscape"
* );
* // Result: "145% Portrait | 100% Landscape"
* }</pre>
*
* @param context Context
* @param liveHeight The current keyboard height in pixels (not yet saved to SharedPreferences)
* @param liveOrientation The orientation for which liveHeight applies
* (Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE)
* @param portraitLabel Label for portrait orientation (e.g., "Portrait")
* @param landscapeLabel Label for landscape orientation (e.g., "Landscape")
* @return String in format "100% Portrait | 100% Landscape"
* @see #createKeyboardHeightString(Context, String, String)
* @see #getKeyboardHeightPercentage(Context, int)
* @see #calculateKeyboardHeightFromTouch(Context, int, int)
*/
public static String createKeyboardHeightString(Context context, int liveHeight, int liveOrientation,
String portraitLabel, String landscapeLabel) {
int portraitPercent = 100;
int landscapePercent = 100;
// Calculate percentage for the live orientation
int liveDefaultHeight = getDefaultKeyboardHeight(liveOrientation);
if (liveDefaultHeight > 0 && liveHeight > 0) {
int livePercent = (int) Math.ceil((liveHeight * 100.0) / liveDefaultHeight);
if (livePercent == 0) {
livePercent = 100;
}
if (liveOrientation == Configuration.ORIENTATION_PORTRAIT) {
portraitPercent = livePercent;
landscapePercent = getKeyboardHeightPercentage(context, Configuration.ORIENTATION_LANDSCAPE);
} else {
landscapePercent = livePercent;
portraitPercent = getKeyboardHeightPercentage(context, Configuration.ORIENTATION_PORTRAIT);
}
} else {
// Fallback: read both from saved preferences
portraitPercent = getKeyboardHeightPercentage(context, Configuration.ORIENTATION_PORTRAIT);
landscapePercent = getKeyboardHeightPercentage(context, Configuration.ORIENTATION_LANDSCAPE);
}
return portraitPercent + "% " + portraitLabel + " | " +
landscapePercent + "% " + landscapeLabel;
}
/**
* Calculate keyboard height from a touch Y coordinate, applying min/max bounds.
* This is used during interactive keyboard height adjustment (e.g., dragging a resize handle).
*
* <p>The height is calculated as the distance from the touch point to the bottom of the screen,
* then clamped to the valid range defined by {@link #getKeyboardHeightMin(Context)} and
* {@link #getKeyboardHeightMax(Context)}.
*
* <p>Example usage in touch listener:
* <pre>{@code
* case MotionEvent.ACTION_MOVE:
* int[] location = new int[2];
* keyboardView.getLocationOnScreen(location);
* int viewBottom = location[1] + keyboardView.getHeight();
* int touchY = (int) event.getRawY();
*
* int newHeight = KMManager.calculateKeyboardHeightFromTouch(
* context, touchY, viewBottom);
* // newHeight is guaranteed to be within min/max bounds
* break;
* }</pre>
*
* @param context Context
* @param touchY The Y coordinate of the touch event in screen coordinates (from event.getRawY())
* @param viewBottom The bottom Y coordinate of the keyboard view in screen coordinates
* (typically: view.getLocationOnScreen()[1] + view.getHeight())
* @return The calculated keyboard height in pixels, clamped to valid range
* @see #getKeyboardHeightMin(Context)
* @see #getKeyboardHeightMax(Context)
* @see #applyKeyboardHeight(Context, int)
*/
public static int calculateKeyboardHeightFromTouch(Context context, int touchY, int viewBottom) {
// Calculate height: distance from touch point to bottom of screen
int height = viewBottom - touchY;
// Apply lower and upper bounds
int minKeyboardHeight = getKeyboardHeightMin(context);
int maxKeyboardHeight = getKeyboardHeightMax(context);
height = Math.max(minKeyboardHeight, height);
height = Math.min(maxKeyboardHeight, height);
return height;
}
/**
* Returns the preference key for tracking pending keyboard height updates.
* This allows separate tracking for each keyboard type (in-app/system) and orientation.

View file

@ -0,0 +1,74 @@
---
title: KMManager.calculateKeyboardHeightFromTouch()
---
## Summary
The **calculateKeyboardHeightFromTouch()** method calculates the keyboard height from a touch Y coordinate, automatically applying minimum and maximum bounds.
## Syntax
```java
KMManager.calculateKeyboardHeightFromTouch(Context context, int touchY, int viewBottom)
```
### Parameters
`context`
: The context
`touchY`
: The Y coordinate of the touch event in screen coordinates (from event.getRawY())
`viewBottom`
: The bottom Y coordinate of the keyboard view in screen coordinates (typically: view.getLocationOnScreen()[1] + view.getHeight())
### Returns
Returns an `int` representing the calculated keyboard height in pixels, clamped to the valid range defined by `getKeyboardHeightMin()` and `getKeyboardHeightMax()`.
## Description
Use this method during interactive keyboard height adjustment (e.g., when implementing a draggable resize handle). The height is calculated as the distance from the touch point to the bottom of the screen, then automatically clamped to ensure it stays within valid bounds.
This method encapsulates the calculation logic and bounds checking, ensuring consistency across different implementations of keyboard height adjustment UI.
## Examples
### Example: Using `calculateKeyboardHeightFromTouch()` in a touch listener
The following script illustrates implementing a draggable keyboard resize handle:
```java
View.OnTouchListener touchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// Get the keyboard view's bottom position on screen
int[] location = new int[2];
keyboardView.getLocationOnScreen(location);
int viewBottom = location[1] + keyboardView.getHeight();
int touchY = (int) event.getRawY();
// Calculate new height with automatic bounds checking
int newHeight = KMManager.calculateKeyboardHeightFromTouch(
context, touchY, viewBottom);
// newHeight is guaranteed to be within min/max bounds
// Update the keyboard preview
updateKeyboardPreview(newHeight);
break;
case MotionEvent.ACTION_UP:
// Save the final height
KMManager.applyKeyboardHeight(context, newHeight);
break;
}
return true;
}
};
// Attach listener to resize handle or keyboard view
resizeHandle.setOnTouchListener(touchListener);
```
## See also
* [applyKeyboardHeight()](applyKeyboardHeight)
* [getKeyboardHeightMin()](getKeyboardHeightMin)
* [getKeyboardHeightMax()](getKeyboardHeightMax)
* [createKeyboardHeightString()](createKeyboardHeightString)

View file

@ -0,0 +1,79 @@
---
title: KMManager.createKeyboardHeightString()
---
## Summary
The **createKeyboardHeightString()** method creates a formatted string showing keyboard height percentages for both portrait and landscape orientations.
## Syntax
```java
KMManager.createKeyboardHeightString(Context context, String portraitLabel, String landscapeLabel)
```
or
```java
KMManager.createKeyboardHeightString(Context context, int liveHeight, int liveOrientation, String portraitLabel, String landscapeLabel)
```
### Parameters
`context`
: The context
`portraitLabel`
: Label for portrait orientation (e.g., "Portrait")
`landscapeLabel`
: Label for landscape orientation (e.g., "Landscape")
`liveHeight` _(Optional)_
: The current keyboard height in pixels (not yet saved to SharedPreferences). Used for displaying real-time percentages during keyboard height adjustment.
`liveOrientation` _(Optional)_
: The orientation for which `liveHeight` applies (Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE)
### Returns
Returns a `String` in the format "100% Portrait | 100% Landscape"
## Description
Use this method to display the keyboard height percentages for both orientations. The first variant reads both values from saved preferences, while the second variant allows you to provide a live (unsaved) height for one orientation, useful during interactive height adjustment.
The percentage is calculated using Math.ceil() to ensure consistency with `getKeyboardHeightPercentage()`.
## Examples
### Example 1: Display saved percentages
The following script illustrates displaying saved keyboard heights:
```java
// Display the saved keyboard height percentages
String heightText = KMManager.createKeyboardHeightString(
this,
"Portrait",
"Landscape"
);
// Result: "100% Portrait | 100% Landscape"
textView.setText(heightText);
```
### Example 2: Display live percentage during drag
The following script shows how to display real-time percentages while the user adjusts keyboard height:
```java
// User is dragging to adjust portrait height
int currentOrientation = KMManager.getOrientation(this);
String display = KMManager.createKeyboardHeightString(
this,
currentHeight, // Live height being adjusted
currentOrientation,
"Portrait",
"Landscape"
);
// Result: "145% Portrait | 100% Landscape"
percentageDisplay.setText(display);
```
## See also
* [getKeyboardHeightPercentage()](getKeyboardHeightPercentage)
* [applyKeyboardHeight()](applyKeyboardHeight)
* [calculateKeyboardHeightFromTouch()](calculateKeyboardHeightFromTouch)

View file

@ -0,0 +1,64 @@
---
title: KMManager.getKeyboardHeightPercentage()
---
## Summary
The **getKeyboardHeightPercentage()** method returns the keyboard height as a percentage of the default height for the current or specified orientation.
## Syntax
```java
KMManager.getKeyboardHeightPercentage(Context context)
```
or
```java
KMManager.getKeyboardHeightPercentage(Context context, int orientation)
```
### Parameters
`context`
: The context
`orientation` _(Optional)_
: Accepts a [screen orientation](https://developer.android.com/training/multiscreen/screensizes#TaskUseOriQuali) value (Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE). If not specified, uses the current device orientation.
### Returns
Returns an `int` representing the keyboard height as a percentage (e.g., 120 for 120%). The minimum return value is 100.
## Description
Use this method to determine how much the user has adjusted the keyboard height from its default size. The percentage is calculated using Math.ceil() to round up to the nearest integer, ensuring consistency with `createKeyboardHeightString()`.
For example, if the current height is 288px and the default height is 200px:
```
percentage = ceil(288 * 100.0 / 200) = ceil(144.0) = 144%
```
## Examples
### Example: Using `getKeyboardHeightPercentage()`
The following script illustrates the use of `getKeyboardHeightPercentage()`:
```java
// Get the current keyboard height percentage
int percentage = KMManager.getKeyboardHeightPercentage(this);
Log.d("Keyboard", "Current height is " + percentage + "% of default");
```
or
```java
import android.content.res.Configuration;
...
// Get the keyboard height percentage for landscape orientation
int landscapePercentage = KMManager.getKeyboardHeightPercentage(
this,
Configuration.ORIENTATION_LANDSCAPE
);
```
## See also
* [getKeyboardHeight()](getKeyboardHeight)
* [getDefaultKeyboardHeight()](getDefaultKeyboardHeight)
* [applyKeyboardHeight()](applyKeyboardHeight)
* [createKeyboardHeightString()](createKeyboardHeightString)

View file

@ -44,6 +44,9 @@ The KMManager is the core class which provides most of the methods and constants
[`applyKeyboardHeight()`](applyKeyboardHeight)
: sets the height of keyboard frame
[`calculateKeyboardHeightFromTouch()`](calculateKeyboardHeightFromTouch)
: calculates the keyboard height from a touch Y coordinate, applying min/max bounds
[`canAddNewKeyboard()`](canAddNewKeyboard)
: returns whether adding a new keyboard is enabled, like in the keyboard picker menu
@ -59,6 +62,9 @@ The KMManager is the core class which provides most of the methods and constants
[`createInputView()`](createInputView)
: creates the input view to be used in InputMethodService
[`createKeyboardHeightString()`](createKeyboardHeightString)
: creates a formatted string showing keyboard height percentages for both orientations
[`deregisterLexicalModel()`](deregisterLexicalModel)
: deregisters the specified lexical model from the LMLayer so it isn't used
@ -107,6 +113,9 @@ The KMManager is the core class which provides most of the methods and constants
[`getKeyboardHeightMin()`](getKeyboardHeightMin)
: returns the minimum allowed height of the keyboard frame
[`getKeyboardHeightPercentage()`](getKeyboardHeightPercentage)
: returns the keyboard height as a percentage of the default height
[`getKeyboardIndex()`](getKeyboardIndex)
: returns index number of the specified keyboard in keyboards list