@@ -81,6 +81,8 @@ class TextEditorActivity : AppCompatActivity() {
8181 private var isNewFile = false
8282 private var isSaving = false
8383 private var noWrapContainer: HorizontalScrollView ? = null
84+ private var mainListBaseBottomMargin = 0
85+ private var fabBaseBottomMargin = 0
8486 private val progressBarDialog by lazy { ProgressBarDialog (this ) }
8587
8688 override fun onCreate (savedInstanceState : Bundle ? ) {
@@ -122,23 +124,36 @@ class TextEditorActivity : AppCompatActivity() {
122124 /* *
123125 * App đang dùng chế độ edge-to-edge (decorFitsSystemWindows = false) nên hệ thống sẽ
124126 * không tự đẩy layout lên khi hiện bàn phím dù có khai báo windowSoftInputMode="adjustResize"
125- * trong manifest — phải tự lắng nghe inset của bàn phím (IME) rồi tự đẩy .
127+ * trong manifest — phải tự lắng nghe inset của bàn phím (IME) rồi tự xử lý .
126128 *
127- * Thay vì chỉ đệm (padding) đáy vùng cuộn — vốn phụ thuộc vào cách ScrollView tự tính vùng
128- * cuộn được nên không phải lúc nào cũng chắc chắn tránh được bàn phím — cách này dịch chuyển
129- * (translationY) thẳng toàn bộ vùng nội dung bên dưới thanh tiêu đề (gồm cả FAB) lên trên
130- * đúng bằng phần chiều cao bị bàn phím che, đảm bảo con trỏ/văn bản luôn nổi lên trên bàn
131- * phím chứ không bị che.
129+ * Dùng translationY (chỉ dịch hình ảnh) từng gây lỗi không kéo lên đầu được, vì vùng chạm/
130+ * cuộn vẫn được tính theo kích thước View cũ (translation không đổi kích thước/measurement
131+ * thật). Ở đây đổi sang tăng bottomMargin thật của vùng nội dung và FAB — tương đương
132+ * cách adjustResize thật sự hoạt động — nên kích thước, vùng cuộn và vùng chạm đều được
133+ * tính lại chính xác theo không gian còn trống phía trên bàn phím. Có thêm một khoảng đệm
134+ * dư ra để văn bản/con trỏ không dính sát vào mép bàn phím.
132135 */
133136 private fun setupKeyboardInsets () {
137+ val mainListParams = binding.mainList.layoutParams as ViewGroup .MarginLayoutParams
138+ mainListBaseBottomMargin = mainListParams.bottomMargin
139+ val fabParams = binding.editorFabRun.layoutParams as ViewGroup .MarginLayoutParams
140+ fabBaseBottomMargin = fabParams.bottomMargin
141+ val extraGapPx = (48 * resources.displayMetrics.density).toInt()
142+
134143 ViewCompat .setOnApplyWindowInsetsListener(binding.root) { _, insets ->
135144 val imeInset = insets.getInsets(WindowInsetsCompat .Type .ime()).bottom
136145 val systemBarsInset = insets.getInsets(WindowInsetsCompat .Type .systemBars()).bottom
137- val pushUp = (imeInset - systemBarsInset).coerceAtLeast(0 ).toFloat()
138- val keyboardVisible = pushUp > 0
146+ val keyboardHeight = (imeInset - systemBarsInset).coerceAtLeast(0 )
147+ val keyboardVisible = keyboardHeight > 0
148+ val extraGap = if (keyboardVisible) extraGapPx else 0
149+
150+ val mlp = binding.mainList.layoutParams as ViewGroup .MarginLayoutParams
151+ mlp.bottomMargin = mainListBaseBottomMargin + keyboardHeight + extraGap
152+ binding.mainList.layoutParams = mlp
139153
140- binding.mainList.animate().translationY(- pushUp).setDuration(120 ).start()
141- binding.editorFabRun.animate().translationY(- pushUp).setDuration(120 ).start()
154+ val flp = binding.editorFabRun.layoutParams as ViewGroup .MarginLayoutParams
155+ flp.bottomMargin = fabBaseBottomMargin + keyboardHeight + extraGap
156+ binding.editorFabRun.layoutParams = flp
142157
143158 if (keyboardVisible) {
144159 binding.mainList.post { scrollToCursor() }
0 commit comments