Skip to content

Commit f6f6a3b

Browse files
committed
fix(data,ime): eliminate the wired padding on the either side of liquid keyboard (#869)
- Also reimplement how to save symbol key history (easier).
1 parent fb21642 commit f6f6a3b

File tree

4 files changed

+40
-157
lines changed

4 files changed

+40
-157
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.osfans.trime.data
2+
3+
import com.osfans.trime.util.appContext
4+
5+
class SymbolHistory(
6+
val capacity: Int
7+
) : LinkedHashMap<String, String>(0, .75f, true) {
8+
9+
companion object {
10+
const val FILE_NAME = "symbol_history"
11+
}
12+
13+
private val file = appContext.filesDir.resolve(FILE_NAME).apply { createNewFile() }
14+
15+
fun load() {
16+
val all = file.readLines()
17+
all.forEach {
18+
if (it.isNotBlank())
19+
put(it, it)
20+
}
21+
}
22+
23+
fun save() {
24+
file.writeText(values.joinToString("\n"))
25+
}
26+
27+
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<String, String>?) =
28+
size > capacity
29+
30+
fun insert(s: String) = put(s, s)
31+
32+
fun toOrderedList() = values.toList().reversed()
33+
}

app/src/main/java/com/osfans/trime/ime/core/Trime.java

-3
Original file line numberDiff line numberDiff line change
@@ -419,9 +419,6 @@ public void selectLiquidKeyboard(final int tabIndex) {
419419
symbolInput.getLayoutParams().height = mainInput.getHeight();
420420
symbolInput.setVisibility(View.VISIBLE);
421421

422-
final int orientation = getResources().getConfiguration().orientation;
423-
liquidKeyboard.setLand(orientation == Configuration.ORIENTATION_LANDSCAPE);
424-
liquidKeyboard.calcPadding(mainInput.getWidth());
425422
symbolKeyboardType = liquidKeyboard.select(tabIndex);
426423
tabView.updateTabWidth();
427424
if (inputRootBinding != null) {

app/src/main/java/com/osfans/trime/ime/symbol/LiquidKeyboard.kt

+7-88
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.osfans.trime.ime.symbol
22

33
import android.annotation.SuppressLint
44
import android.content.Context
5-
import android.view.View
65
import androidx.core.view.setPadding
76
import androidx.lifecycle.lifecycleScope
87
import androidx.recyclerview.widget.RecyclerView
@@ -11,8 +10,8 @@ import com.google.android.flexbox.FlexDirection
1110
import com.google.android.flexbox.FlexWrap
1211
import com.google.android.flexbox.FlexboxLayoutManager
1312
import com.google.android.flexbox.JustifyContent
14-
import com.osfans.trime.R
1513
import com.osfans.trime.core.Rime
14+
import com.osfans.trime.data.SymbolHistory
1615
import com.osfans.trime.data.db.ClipboardHelper
1716
import com.osfans.trime.data.db.CollectionHelper
1817
import com.osfans.trime.data.db.DatabaseBean
@@ -22,33 +21,22 @@ import com.osfans.trime.ime.core.Trime
2221
import com.osfans.trime.ime.enums.KeyCommandType
2322
import com.osfans.trime.ime.enums.SymbolKeyboardType
2423
import com.osfans.trime.ime.text.TextInputManager
25-
import com.osfans.trime.util.appContext
2624
import com.osfans.trime.util.dp2px
2725
import kotlinx.coroutines.launch
2826
import timber.log.Timber
29-
import kotlin.math.ceil
3027

3128
class LiquidKeyboard(private val context: Context) {
3229
private val theme: Config = Config.get()
3330
private val tabManager: TabManager = TabManager.get()
3431
private val service: Trime = Trime.getService()
35-
private var rootView: View? = null
3632
private lateinit var keyboardView: RecyclerView
37-
private var historyBeans: MutableList<SimpleKeyBean>? = null
38-
private var marginLeft = 0
39-
private var marginTop = 0
40-
private var singleWidth = 0
41-
private var parentWidth = 0
42-
private var keyHeight = 0
43-
var isLand = false
44-
private val historySavePath = "${appContext.getExternalFilesDir(null)!!.absolutePath}/key_history"
33+
private val symbolHistory = SymbolHistory(180)
4534

4635
private val flexbox: FlexboxLayoutManager by lazy {
4736
return@lazy FlexboxLayoutManager(context).apply {
4837
flexDirection = FlexDirection.ROW // 主轴为水平方向,起点在左端。
4938
flexWrap = FlexWrap.WRAP // 按正常方向换行
5039
justifyContent = JustifyContent.FLEX_START // 交叉轴的起点对齐
51-
// alignItems = AlignItems.BASELINE
5240
}
5341
}
5442

@@ -67,7 +55,8 @@ class LiquidKeyboard(private val context: Context) {
6755

6856
fun select(i: Int): SymbolKeyboardType {
6957
val tag = TabManager.getTag(i)
70-
calcPadding(tag.type)
58+
symbolHistory.load()
59+
keyboardView.removeAllViews()
7160
when (tag.type) {
7261
SymbolKeyboardType.CLIPBOARD,
7362
SymbolKeyboardType.COLLECTION,
@@ -91,72 +80,8 @@ class LiquidKeyboard(private val context: Context) {
9180
return tag.type
9281
}
9382

94-
// 设置liquidKeyboard共用的布局参数
95-
fun calcPadding(width: Int) {
96-
parentWidth = width
97-
98-
// liquid_keyboard/margin_x定义了每个键左右两边的间隙,
99-
// 也就是说相邻两个键间隙是x2,而horizontal_gap定义的是spacer,使用时需要/2
100-
marginLeft = dp2px(theme.liquid.getFloat("margin_x")).toInt()
101-
if (marginLeft == 0) {
102-
var horizontal_gap = dp2px(theme.style.getFloat("horizontal_gap")).toInt()
103-
if (horizontal_gap > 1) {
104-
horizontal_gap /= 2
105-
}
106-
marginLeft = horizontal_gap
107-
}
108-
109-
// 初次显示布局,需要刷新背景
110-
rootView = keyboardView.parent as View
111-
val keyboardBackground = theme.colors.getDrawable("liquid_keyboard_background")
112-
if (keyboardBackground != null) rootView!!.background = keyboardBackground
113-
var keyboardHeight = dp2px(theme.style.getFloat("keyboard_height")).toInt()
114-
if (isLand) {
115-
val keyBoardHeightLand = dp2px(theme.style.getFloat("keyboard_height_land")).toInt()
116-
if (keyBoardHeightLand > 0) keyboardHeight = keyBoardHeightLand
117-
}
118-
var row = theme.liquid.getInt("row")
119-
if (row > 0) {
120-
if (isLand) {
121-
val r = theme.liquid.getInt("row_land")
122-
if (r > 0) row = r
123-
}
124-
val rawHeight = theme.liquid.getFloat("key_height")
125-
val rawVGap = theme.liquid.getFloat("vertical_gap")
126-
val scale = keyboardHeight.toFloat() / ((rawHeight + rawVGap) * row)
127-
marginTop = ceil((rawVGap * scale).toDouble()).toInt()
128-
keyHeight = keyboardHeight / row - marginTop
129-
} else {
130-
keyHeight = dp2px(theme.liquid.getFloat("key_height_land")).toInt()
131-
if (!isLand || keyHeight <= 0) keyHeight = dp2px(theme.liquid.getFloat("key_height")).toInt()
132-
marginTop = dp2px(theme.liquid.getFloat("vertical_gap")).toInt()
133-
}
134-
Timber.i("config keyHeight=$keyHeight marginTop=$marginTop")
135-
if (isLand) {
136-
singleWidth = dp2px(theme.liquid.getFloat("single_width_land")).toInt()
137-
if (singleWidth <= 0) singleWidth = dp2px(theme.liquid.getFloat("single_width")).toInt()
138-
} else singleWidth = dp2px(theme.liquid.getFloat("single_width")).toInt()
139-
if (singleWidth <= 0) singleWidth = context.resources.getDimensionPixelSize(R.dimen.simple_key_single_width)
140-
}
141-
142-
// 每次点击tab都需要刷新的参数
143-
private fun calcPadding(type: SymbolKeyboardType) {
144-
val padding = theme.keyboardPadding
145-
if (type === SymbolKeyboardType.SINGLE) {
146-
padding[0] = (
147-
(if (rootView!!.width > 0) rootView!!.width else parentWidth) %
148-
(singleWidth + marginLeft * 2) /
149-
2
150-
)
151-
padding[1] = padding[0]
152-
}
153-
rootView!!.setPadding(padding[0], 0, padding[1], 0)
154-
historyBeans = SimpleKeyDao.getSymbolKeyHistory(historySavePath)
155-
}
156-
15783
private fun initFixData(i: Int) {
15884
val tabTag = TabManager.getTag(i)
159-
keyboardView.removeAllViews()
16085

16186
val simpleAdapter = SimpleAdapter(theme).apply {
16287
// 列表适配器的点击监听事件
@@ -168,8 +93,8 @@ class LiquidKeyboard(private val context: Context) {
16893
service.currentInputConnection?.run {
16994
commitText(bean.text, 1)
17095
if (tabTag.type !== SymbolKeyboardType.HISTORY) {
171-
historyBeans?.add(0, bean)
172-
SimpleKeyDao.saveSymbolKeyHistory(historySavePath, historyBeans!!)
96+
symbolHistory.insert(bean.text)
97+
symbolHistory.save()
17398
}
17499
}
175100
} else {
@@ -207,7 +132,7 @@ class LiquidKeyboard(private val context: Context) {
207132

208133
when (tabTag.type) {
209134
SymbolKeyboardType.HISTORY ->
210-
simpleAdapter.updateBeans(historyBeans!!)
135+
simpleAdapter.updateBeans(symbolHistory.toOrderedList().map(::SimpleKeyBean))
211136
SymbolKeyboardType.TABS ->
212137
simpleAdapter.updateBeans(tabManager.tabSwitchData)
213138
else ->
@@ -217,8 +142,6 @@ class LiquidKeyboard(private val context: Context) {
217142
}
218143

219144
private fun initDbData(type: SymbolKeyboardType) {
220-
keyboardView.removeAllViews()
221-
222145
val dbAdapter = FlexibleAdapter(theme).apply {
223146
setListener(object : FlexibleAdapter.Listener {
224147
override fun onPaste(bean: DatabaseBean) {
@@ -316,8 +239,6 @@ class LiquidKeyboard(private val context: Context) {
316239
}
317240

318241
private fun initCandidates() {
319-
keyboardView.removeAllViews()
320-
321242
val candidateAdapter = CandidateAdapter(theme).apply {
322243
setListener { position ->
323244
TextInputManager.getInstance().onCandidatePressed(position)
@@ -339,8 +260,6 @@ class LiquidKeyboard(private val context: Context) {
339260
}
340261

341262
private fun initVarLengthKeys(data: List<SimpleKeyBean>) {
342-
keyboardView.removeAllViews()
343-
344263
val candidateAdapter = CandidateAdapter(theme).apply {
345264
setListener { position ->
346265
service.currentInputConnection?.commitText(data[position].text, 1)
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
package com.osfans.trime.ime.symbol;
22

33
import androidx.annotation.NonNull;
4-
import java.io.File;
5-
import java.io.FileInputStream;
6-
import java.io.FileOutputStream;
7-
import java.io.IOException;
8-
import java.io.ObjectInputStream;
9-
import java.io.ObjectOutputStream;
104
import java.util.ArrayList;
115
import java.util.List;
126

@@ -39,64 +33,4 @@ else if (c >= '\udc00' && c <= '\udfff')
3933
}
4034
return list;
4135
}
42-
43-
@NonNull
44-
public static List<SimpleKeyBean> getSymbolKeyHistory(String path) {
45-
List<SimpleKeyBean> list = new ArrayList<>();
46-
47-
ObjectInputStream ois = null;
48-
try {
49-
ois = new ObjectInputStream(new FileInputStream(path));
50-
Object object = ois.readObject();
51-
if (object != null) {
52-
if (object instanceof ArrayList<?>) {
53-
for (Object o : (List<?>) object) {
54-
list.add((SimpleKeyBean) o);
55-
}
56-
}
57-
}
58-
59-
} catch (Exception e) {
60-
e.printStackTrace();
61-
} finally {
62-
try {
63-
if (ois != null) {
64-
ois.close();
65-
}
66-
} catch (IOException e) {
67-
e.printStackTrace();
68-
}
69-
}
70-
return list;
71-
}
72-
73-
public static void saveSymbolKeyHistory(String path, @NonNull List<SimpleKeyBean> list) {
74-
ObjectOutputStream fos = null;
75-
List<String> text_list = new ArrayList<>();
76-
List<SimpleKeyBean> cache = new ArrayList<>();
77-
for (SimpleKeyBean bean : list) {
78-
String text = bean.getText();
79-
if (!text_list.contains(text)) {
80-
text_list.add(text);
81-
cache.add(bean);
82-
if (cache.size() > 180) break;
83-
}
84-
}
85-
86-
try {
87-
File file = new File(path);
88-
fos = new ObjectOutputStream(new FileOutputStream(file));
89-
fos.writeObject(cache);
90-
} catch (Exception e) {
91-
e.printStackTrace();
92-
} finally {
93-
try {
94-
if (fos != null) {
95-
fos.close();
96-
}
97-
} catch (IOException e) {
98-
e.printStackTrace();
99-
}
100-
}
101-
}
10236
}

0 commit comments

Comments
 (0)