Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ GitHub Release 的发布说明;版本与发布流程见 [docs/RELEASE.md](docs

## [Unreleased]

## [0.0.9-beta.1] - 2026-10-10

第九个测试版:横屏默认改回铺满宽度的停靠键盘,竖屏和横屏各记一份键盘高度,横屏左右分离的九键改成“一手数字、一手拼音”。从 0.0.8-beta.1 覆盖安装即可,用户数据保留。

- 横屏默认沿用竖屏的停靠键盘布局并铺满可用宽度,避免新装后自动缩成居中浮窗;浮动和左右分离仍可在偏好设置中选择。已经选过横屏布局的用户不受影响。
- 竖屏和横屏分别记忆键盘高度,偏好设置里的滑块按当前方向显示“竖屏键盘高度”或“横屏键盘高度”;横屏的整宽、浮动、左右分离布局共用横屏高度,旧版高度设置会作为两种方向的初始值。数据备份和恢复包含横屏高度。
- 横屏按键行从 40dp 加高到 48dp,横屏顶栏从 48dp 加高到 54dp,按键更大更好按。
- 横屏左右分离的九键:九宫格保持熟悉的 3×3 顺序,另一只手改为直接输入数字的 1–9、0 和逗号,加上符号列和“互换”键;去掉原来的常用字面板和中间的“镜像”键。

## [0.0.8-beta.1] - 2026-10-09

第八个测试版:英文大写手势、长按后滑动选字、横屏浮动与左右分离键盘、工具栏的复制和验证码提示,修复九键拼音栏缺音节和排序错误、一次点按两次反馈、分段选词学不到。从 0.0.7-beta.1 覆盖安装即可,用户数据保留。
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.8-beta.1
0.0.9-beta.1
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ class AuditInteractionInstrumentedTest {
harness.awaitMain {
keyboard.showPanel(Panel.SETTINGS)
val settings = keyboard.findViewWithTag<ViewGroup>("settings-panel")
listOf("键盘高度", "浮动宽度", "浮动透明度").forEach { label ->
listOf("竖屏键盘高度", "浮动宽度", "浮动透明度").forEach { label ->
val slider = settings.findViewWithTag<View>("settings-slider:$label")
assertTrue("$label must keep a 48dp touch target", slider.minimumHeight >= keyboard.resources.displayMetrics.density * 48f)
assertTrue("$label must expose its current value", slider.contentDescription.toString().contains(label))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,11 @@ class ImeSettingsActivity : Activity(), ImeKeyboardView.Listener {
refreshLiveIme()
}
override fun onKeyboardHeightChanged(percent: Int) {
ImeSettingsRepository.saveKeyboardHeightPercent(this, percent)
ImeSettingsRepository.saveKeyboardHeightPercent(
this,
percent,
landscape = resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE,
)
refreshLiveIme()
}
override fun onFloatingStyleChanged(widthPercent: Int, opacityPercent: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class LocalVoiceImeService : InputMethodService(), ImeKeyboardView.Listener, Can
resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE

/**
* Landscape layout setting: floating (default), full width, or split halves.
* Landscape layout setting: full width (default), floating, or split halves.
* Only the transitions the setting itself caused are undone: a keyboard the
* user floated from the tools page stays floating in both orientations.
*/
Expand Down
12 changes: 7 additions & 5 deletions app/src/main/java/llc/slacker/openime/core/LandscapeLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package llc.slacker.openime.core
/**
* How the keyboard sits when the phone is held sideways.
*
* WeChat Keyboard floats by itself in landscape and Gboard does the same; the
* Chinese keyboards otherwise stretch the full width. Sogou also offers a split
* keyboard, one half under each thumb. Floating is the default because a
* full-width keyboard of four rows covers most of a landscape screen.
* The default keeps the docked keyboard surface and controls consistent with
* portrait, using the extra width for larger, easier-to-reach keys. Floating
* and split layouts remain optional alternatives for landscape use.
*/
enum class LandscapeLayout(val key: String, val label: String) {
FLOATING("floating", "浮动"),
Expand All @@ -16,6 +15,9 @@ enum class LandscapeLayout(val key: String, val label: String) {
companion object {
// "side" was an earlier name of the split layout.
fun fromKey(key: String?): LandscapeLayout =
entries.firstOrNull { it.key == key } ?: if (key == "side") SPLIT else FLOATING
entries.firstOrNull { it.key == key } ?: when (key) {
"side" -> SPLIT
else -> FULL
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ object ImeSettingsRepository {
private const val KEY_VOICE_PUNCTUATION_AS_SPACE = "voice_punctuation_as_space"
private const val KEY_PREFERRED_CHINESE_MODE = "preferred_chinese_mode"
private const val KEY_KEYBOARD_HEIGHT = "keyboard_height_percent"
private const val KEY_LANDSCAPE_KEYBOARD_HEIGHT = "landscape_keyboard_height_percent"
private const val KEY_FLOATING_WIDTH = "floating_width_percent"
private const val KEY_FLOATING_OPACITY = "floating_opacity_percent"
private const val KEY_LANDSCAPE_LAYOUT = "landscape_layout"
Expand All @@ -54,14 +55,26 @@ object ImeSettingsRepository {
.edit().putString(KEY_PREFERRED_CHINESE_MODE, mode.name).apply()
}

fun loadKeyboardHeightPercent(context: Context): Int =
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
.getInt(KEY_KEYBOARD_HEIGHT, 100)
.coerceIn(80, 120)
fun loadKeyboardHeightPercent(context: Context, landscape: Boolean = false): Int {
val preferences = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
val stored = if (landscape && preferences.contains(KEY_LANDSCAPE_KEYBOARD_HEIGHT)) {
preferences.getInt(KEY_LANDSCAPE_KEYBOARD_HEIGHT, 100)
} else {
// Existing height preferences seed landscape until a user changes
// its independent value, preserving the current appearance on upgrade.
preferences.getInt(KEY_KEYBOARD_HEIGHT, 100)
}
return stored.coerceIn(80, 120)
}

fun saveKeyboardHeightPercent(context: Context, percent: Int) {
fun saveKeyboardHeightPercent(context: Context, percent: Int, landscape: Boolean = false) {
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
.edit().putInt(KEY_KEYBOARD_HEIGHT, percent.coerceIn(80, 120)).apply()
.edit()
.putInt(
if (landscape) KEY_LANDSCAPE_KEYBOARD_HEIGHT else KEY_KEYBOARD_HEIGHT,
percent.coerceIn(80, 120),
)
.apply()
}

fun loadSplitMirrored(context: Context): Boolean =
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/llc/slacker/openime/data/UserDataArchive.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ internal data class ArchiveSettings(
val railSymbols: List<String>? = null,
/** Keys of the 模糊音 pairs switched on; null in backups made before the switches. */
val fuzzyRules: List<String>? = null,
val landscapeKeyboardHeightPercent: Int = keyboardHeightPercent,
)

internal data class RimeUserDictionaryArchive(
Expand Down Expand Up @@ -190,6 +191,7 @@ internal object UserDataArchiveCodec {
.put("swipe_up_digits", value.swipeUpDigits)
.put("preferred_chinese_mode", value.preferredChineseMode)
.put("keyboard_height_percent", value.keyboardHeightPercent)
.put("landscape_keyboard_height_percent", value.landscapeKeyboardHeightPercent)
.put("floating_width_percent", value.floatingWidthPercent)
.put("floating_opacity_percent", value.floatingOpacityPercent)
.put("letter_hints", value.letterHints)
Expand Down Expand Up @@ -217,6 +219,10 @@ internal object UserDataArchiveCodec {
),
keyboardHeightPercent =
value.optInt("keyboard_height_percent", 100).coerceIn(80, 120),
landscapeKeyboardHeightPercent = value.optInt(
"landscape_keyboard_height_percent",
value.optInt("keyboard_height_percent", 100),
).coerceIn(80, 120),
floatingWidthPercent =
value.optInt("floating_width_percent", 88).coerceIn(72, 96),
floatingOpacityPercent =
Expand Down Expand Up @@ -353,6 +359,8 @@ internal object UserDataRepository {
ImeSettingsRepository.loadPreferredChineseMode(context).name,
keyboardHeightPercent =
ImeSettingsRepository.loadKeyboardHeightPercent(context),
landscapeKeyboardHeightPercent =
ImeSettingsRepository.loadKeyboardHeightPercent(context, landscape = true),
floatingWidthPercent =
ImeSettingsRepository.loadFloatingWidthPercent(context),
floatingOpacityPercent =
Expand Down Expand Up @@ -448,6 +456,11 @@ internal object UserDataRepository {
context,
value.keyboardHeightPercent,
)
ImeSettingsRepository.saveKeyboardHeightPercent(
context,
value.landscapeKeyboardHeightPercent,
landscape = true,
)
ImeSettingsRepository.saveFloatingWidthPercent(
context,
value.floatingWidthPercent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,10 @@ open class ImeKeyboardView(
private var appliedScreenWidthDp = resources.configuration.screenWidthDp
private var appliedFontScale = resources.configuration.fontScale
private var appliedDensityDpi = resources.displayMetrics.densityDpi
private var keyboardHeightPercent = ImeSettingsRepository.loadKeyboardHeightPercent(context)
private var keyboardHeightPercent = ImeSettingsRepository.loadKeyboardHeightPercent(
context,
landscape = appliedOrientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE,
)
private var floatingWidthPercent = ImeSettingsRepository.loadFloatingWidthPercent(context)
private var floatingOpacityPercent = ImeSettingsRepository.loadFloatingOpacityPercent(context)
private var referenceScale = if (standalonePanel) 1f else ImeReferenceSizing.scale(context)
Expand Down Expand Up @@ -748,6 +751,13 @@ open class ImeKeyboardView(
currentExtraToggle = ::onState,
currentFuzzy = { fuzzyEnabled },
currentKeyboardHeightPercent = { keyboardHeightPercent },
currentKeyboardHeightLabel = {
if (appliedOrientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE) {
"横屏键盘高度"
} else {
"竖屏键盘高度"
}
},
currentFloatingWidthPercent = { floatingWidthPercent },
currentFloatingOpacityPercent = { floatingOpacityPercent },
onThemeSelected = ::setTheme,
Expand Down Expand Up @@ -994,6 +1004,10 @@ open class ImeKeyboardView(
appliedOrientation = newConfig.orientation
appliedFontScale = newConfig.fontScale
appliedDensityDpi = newConfig.densityDpi
keyboardHeightPercent = ImeSettingsRepository.loadKeyboardHeightPercent(
context,
landscape = appliedOrientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE,
)
layoutMetrics = buildLayoutMetrics()
if (!geometryChanged) return
// The rows under an open panel are stale too (split layout, row heights):
Expand Down Expand Up @@ -1790,7 +1804,11 @@ open class ImeKeyboardView(
val bounded = percent.coerceIn(80, 120)
if (keyboardHeightPercent == bounded) return
keyboardHeightPercent = bounded
ImeSettingsRepository.saveKeyboardHeightPercent(context, bounded)
ImeSettingsRepository.saveKeyboardHeightPercent(
context,
bounded,
landscape = appliedOrientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE,
)
listener.onKeyboardHeightChanged(bounded)
renderedMode = null
layoutMetrics = buildLayoutMetrics()
Expand Down Expand Up @@ -1819,7 +1837,10 @@ open class ImeKeyboardView(
popup: Boolean,
fuzzy: Boolean,
) {
val persistedHeight = ImeSettingsRepository.loadKeyboardHeightPercent(context)
val persistedHeight = ImeSettingsRepository.loadKeyboardHeightPercent(
context,
landscape = appliedOrientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE,
)
val persistedFloatingWidth = ImeSettingsRepository.loadFloatingWidthPercent(context)
val persistedFloatingOpacity = ImeSettingsRepository.loadFloatingOpacityPercent(context)
val floatingStyleChanged =
Expand Down
Loading
Loading