Skip to content

Commit 1b7e19a

Browse files
committed
docs: 补充注释说明
1 parent f5751e0 commit 1b7e19a

File tree

11 files changed

+93
-76
lines changed

11 files changed

+93
-76
lines changed

app/src/main/kotlin/com/xiaocydx/inputview/sample/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import com.xiaocydx.inputview.sample.dialog.MessageListBottomSheetDialog
1010
import com.xiaocydx.inputview.sample.dialog.MessageListBottomSheetDialogFragment
1111
import com.xiaocydx.inputview.sample.dialog.MessageListDialog
1212
import com.xiaocydx.inputview.sample.dialog.MessageListDialogFragment
13-
import com.xiaocydx.inputview.sample.fragment.FragmentEditorAdapterActivity
1413
import com.xiaocydx.inputview.sample.edit.VideoEditActivity
14+
import com.xiaocydx.inputview.sample.fragment.FragmentEditorAdapterActivity
1515

1616
/**
1717
* **注意**:需要确保`androidx.core`的版本足够高,因为高版本修复了[WindowInsetsCompat]一些常见的问题,

app/src/main/kotlin/com/xiaocydx/inputview/sample/MessageListActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.xiaocydx.inputview.sample
22

33
import android.os.Bundle
4+
import android.view.WindowManager
45
import androidx.appcompat.app.AppCompatActivity
56
import com.xiaocydx.inputview.InputView
67
import com.xiaocydx.inputview.init

app/src/main/kotlin/com/xiaocydx/inputview/sample/edit/VideoEditViewModel.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.xiaocydx.inputview.sample.edit
33
import androidx.lifecycle.ViewModel
44
import kotlinx.coroutines.flow.MutableStateFlow
55
import kotlinx.coroutines.flow.asStateFlow
6-
import kotlinx.coroutines.flow.update
76

87
/**
98
* @author xcc

app/src/main/kotlin/com/xiaocydx/inputview/sample/edit/VideoEditorAdapter.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package com.xiaocydx.inputview.sample.edit
33
import androidx.fragment.app.Fragment
44
import androidx.fragment.app.FragmentActivity
55
import com.xiaocydx.inputview.FragmentEditorAdapter
6-
import com.xiaocydx.inputview.notifyHideCurrent
7-
import com.xiaocydx.inputview.notifyShow
86
import com.xiaocydx.inputview.sample.fragment.EmojiFragment
97

108
/**
@@ -22,8 +20,4 @@ class VideoEditorAdapter(
2220
if (editor == VideoEditor.Text.Emoji) return EmojiFragment()
2321
return CommonFragment.newInstance(editor.title, editor.size)
2422
}
25-
26-
fun notifyShowOrHide(current: VideoEditor?) {
27-
if (current != null) notifyShow(current) else notifyHideCurrent()
28-
}
2923
}

inputview/src/main/kotlin/com/xiaocydx/inputview/Compat.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ package com.xiaocydx.inputview.compat
2121
import android.view.View
2222
import android.view.Window
2323
import android.view.WindowInsets
24+
import android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN
25+
import android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
2426
import android.view.animation.Interpolator
2527
import androidx.core.view.OnApplyWindowInsetsListener
2628
import androidx.core.view.ViewCompat
@@ -31,6 +33,46 @@ import androidx.core.view.WindowInsetsCompat.Type.InsetsType
3133
import androidx.core.view.WindowInsetsControllerCompat
3234
import com.xiaocydx.inputview.OnApplyWindowInsetsListenerCompat
3335

36+
/**
37+
* 检查Android 11以下`ViewRootImpl.dispatchApplyInsets()`的兼容性
38+
*
39+
* 以Android 10显示IME为例:
40+
* 1. IME进程调用`WindowManagerService.setInsetsWindow()`,
41+
* 进而调用`DisplayPolicy.layoutWindowLw()`计算各项`insets`。
42+
*
43+
* 2. `window.attributes.flags`包含[FLAG_FULLSCREEN],
44+
* 或`window.attributes.softInputMode`不包含[SOFT_INPUT_ADJUST_RESIZE],
45+
* `DisplayPolicy.layoutWindowLw()`计算的`contentInsets`不会包含IME的数值。
46+
*
47+
* 3. `WindowManagerService`通知应用进程的`ViewRootImpl`重新设置`mPendingContentInsets`的数值,
48+
* 并申请下一帧布局,下一帧由于`mPendingContentInsets`跟`mAttachInfo.mContentInsets`的数值相等,
49+
* 因此不调用`ViewRootImpl.dispatchApplyInsets()`。
50+
*/
51+
internal fun Window.checkDispatchApplyInsetsCompatibility() = ReflectCompat {
52+
check(!isFloating) {
53+
"""window.isFloating = true
54+
| InputView需要主题的windowIsFloating = false,否则会导致视图树没有WindowInsets分发
55+
""".trimMargin()
56+
}
57+
@Suppress("DEPRECATION")
58+
check(attributes.softInputMode and SOFT_INPUT_ADJUST_RESIZE != 0) {
59+
"""window.attributes.softInputMode未包含SOFT_INPUT_ADJUST_RESIZE
60+
| InputView需要window.attributes.softInputMode包含SOFT_INPUT_ADJUST_RESIZE,
61+
| 否则会导致Android 11以下显示或隐藏IME不进行WindowInsets分发,
62+
| 可以调用Window.setSoftInputMode()设置SOFT_INPUT_ADJUST_RESIZE
63+
""".trimMargin()
64+
}
65+
@Suppress("DEPRECATION")
66+
check(isFullscreenCompatEnabled || (attributes.flags and FLAG_FULLSCREEN == 0)) {
67+
"""window.attributes.flags包含FLAG_FULLSCREEN
68+
| InputView需要主题的windowFullscreen = false,
69+
| 或者window.attributes.flags不包含FLAG_FULLSCREEN,
70+
| 否则会导致Android 11以下显示或隐藏IME不进行WindowInsets分发,
71+
| 可以尝试Window.enableDispatchApplyInsetsFullscreenCompat()的兼容方案
72+
""".trimMargin()
73+
}
74+
}
75+
3476
internal fun Window.setDecorFitsSystemWindowsCompat(decorFitsSystemWindows: Boolean) {
3577
WindowCompat.setDecorFitsSystemWindows(this, decorFitsSystemWindows)
3678
}

inputview/src/main/kotlin/com/xiaocydx/inputview/EditTextHolder.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,21 @@ internal class EditTextHolder(editText: EditText) :
6060
override fun onViewDetachedFromWindow(v: View) = removePending()
6161

6262
fun requestCurrentFocus() {
63-
window?.currentFocus?.requestFocus() ?: get()?.requestFocus()
63+
val currentFocus = window?.currentFocus
64+
if (currentFocus == null) {
65+
get()?.requestFocus()
66+
} else {
67+
(currentFocus as? EditText)?.requestFocus()
68+
}
6469
}
6570

6671
fun clearCurrentFocus() {
67-
window?.currentFocus?.clearFocus() ?: get()?.clearFocus()
72+
val currentFocus = window?.currentFocus
73+
if (currentFocus == null) {
74+
get()?.clearFocus()
75+
} else {
76+
(currentFocus as? EditText)?.clearFocus()
77+
}
6878
}
6979

7080
fun showIme() {

inputview/src/main/kotlin/com/xiaocydx/inputview/EditorContainer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ internal class EditorContainer(context: Context) : FrameLayout(context) {
5757
override fun onTouchEvent(event: MotionEvent?) = true
5858

5959
fun setAdapter(adapter: EditorAdapter<*>) {
60-
this.adapter = adapter
6160
current?.let(::hideChecked)
61+
this.adapter = adapter
6262
if (views.isNotEmpty()) {
6363
removeAllViews()
6464
views.clear()

inputview/src/main/kotlin/com/xiaocydx/inputview/EditorNotify.kt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package com.xiaocydx.inputview
1818

19+
import android.widget.EditText
20+
1921
/**
2022
* 当前显示的[Editor],若为`null`,则当前是初始化状态
2123
*/
@@ -29,42 +31,48 @@ val <T : Editor> EditorAdapter<T>.current: T?
2931
fun <T : Editor> EditorAdapter<T>.isShowing(editor: T): Boolean = current === editor
3032

3133
/**
32-
* 通知显示[editor],若当前[EditorAdapter]未关联[InputView],则调用无效
34+
* 通知显示[editor],若当前[EditorAdapter]未关联[InputView],则调用无效,
35+
* 多个[EditText]的焦点处理逻辑,详细解释可以看[InputView.editText]的注释。
3336
*/
3437
fun <T : Editor> EditorAdapter<T>.notifyShow(editor: T) {
3538
host?.showChecked(editor)
3639
}
3740

3841
/**
39-
* 通知隐藏[editor],若当前[EditorAdapter]未关联[InputView],则调用无效
42+
* 通知隐藏[editor],若当前[EditorAdapter]未关联[InputView],则调用无效,
43+
* 多个[EditText]的焦点处理逻辑,详细解释可以看[InputView.editText]的注释。
4044
*/
4145
fun <T : Editor> EditorAdapter<T>.notifyHide(editor: T) {
4246
host?.hideChecked(editor)
4347
}
4448

4549
/**
46-
* 通知隐藏当前[Editor],若当前[EditorAdapter]未关联[InputView],则调用无效
50+
* 通知隐藏当前[Editor],若当前[EditorAdapter]未关联[InputView],则调用无效,
51+
* 多个[EditText]的焦点处理逻辑,详细解释可以看[InputView.editText]的注释。
4752
*/
4853
fun <T : Editor> EditorAdapter<T>.notifyHideCurrent() {
4954
current?.let(::notifyHide)
5055
}
5156

5257
/**
53-
* 通知显示IME,若当前[EditorAdapter]未关联[InputView],则调用无效
58+
* 通知显示IME,若当前[EditorAdapter]未关联[InputView],则调用无效,
59+
* 多个[EditText]的焦点处理逻辑,详细解释可以看[InputView.editText]的注释。
5460
*/
5561
fun EditorAdapter<*>.notifyShowIme() {
5662
host?.apply { ime?.let(::showChecked) }
5763
}
5864

5965
/**
60-
* 通知隐藏IME,若当前[EditorAdapter]未关联[InputView],则调用无效
66+
* 通知隐藏IME,若当前[EditorAdapter]未关联[InputView],则调用无效,
67+
* 多个[EditText]的焦点处理逻辑,详细解释可以看[InputView.editText]的注释。
6168
*/
6269
fun EditorAdapter<*>.notifyHideIme() {
6370
host?.apply { ime?.let(::hideChecked) }
6471
}
6572

6673
/**
67-
* 通知切换显示[Editor],若当前[EditorAdapter]未关联[InputView],则调用无效
74+
* 通知切换显示[Editor],若当前[EditorAdapter]未关联[InputView],则调用无效,
75+
* 多个[EditText]的焦点处理逻辑,详细解释可以看[InputView.editText]的注释。
6876
*
6977
* 1. 当前未显示[editor],则显示[editor]。
7078
* 2. 当前已显示[editor],则显示IME。

inputview/src/main/kotlin/com/xiaocydx/inputview/ImeAnimator.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17-
@file:SuppressLint("ClickableViewAccessibility")
18-
1917
package com.xiaocydx.inputview
2018

21-
import android.annotation.SuppressLint
2219
import android.view.View
2320
import android.view.View.OnAttachStateChangeListener
2421
import android.view.Window
@@ -34,8 +31,15 @@ import com.xiaocydx.inputview.compat.ReflectCompat
3431

3532
/**
3633
* 复用[InputView]的动画实现,需要先调用[init]或[initCompat]完成初始化,
37-
* 该函数不能跟[InputView]一直使用,两者不是共存关系,只能选择其中一个。
34+
* 该函数不能跟[InputView]一起使用,两者不是共存关系,只能选择其中一个。
35+
*
36+
* 多个[EditText]的焦点处理逻辑:
37+
* 1. 调用[ImeAnimator.showIme]显示IME,会让[editText]获得焦点。
38+
* 2. 调用[ImeAnimator.hideIme]隐藏IME,或者通过其它方式隐藏IME,
39+
* 会清除`currentFocus`的焦点,`currentFocus`不一定是[editText]。
3840
*
41+
* 首次调用按[durationMillis]和[interpolator]创建[EditorAnimator],
42+
* 后续调用获取的是首次调用创建的[EditorAnimator]:
3943
* ```
4044
* InputView.init(window)
4145
* val animator = InputView.animator(window, editText)
@@ -50,8 +54,7 @@ import com.xiaocydx.inputview.compat.ReflectCompat
5054
* )
5155
* ```
5256
*
53-
* @param editText 首次按[durationMillis]和[interpolator]创建[EditorAnimator],
54-
* 后续获取的是首次创建的[EditorAnimator],显示IME会获得焦点,隐藏IME会清除焦点。
57+
* @param editText 用于兼容Android各版本显示IME的[EditText]
5558
* @param durationMillis 参数含义跟[EditorAnimator.durationMillis]一致
5659
* @param interpolator 参数含义跟[EditorAnimator.interpolator]一致
5760
*/

inputview/src/main/kotlin/com/xiaocydx/inputview/InputView.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,13 @@ class InputView @JvmOverloads constructor(
7878
private var navBarOffset = 0
7979

8080
/**
81-
* 用于兼容Android各版本显示和隐藏IME的[EditText]
81+
* 用于兼容Android各版本显示IME的[EditText]
8282
*
83-
* **注意**:[editText]必须是[InputView]的子View或间接子View。
83+
* 多个[EditText]的焦点处理逻辑:
84+
* 1. 调用[EditorAdapter]提供的函数显示IME,会让[editText]获得焦点。
85+
* 2. 调用[EditorAdapter]提供的函数隐藏IME,或者通过其它方式隐藏IME,
86+
* 会清除`currentFocus`的焦点,`currentFocus`不一定是[editText]。
8487
*
85-
* 显示IME[editText]会获得焦点,隐藏IME会清除[editText]的焦点,
8688
* 可以通过[EditorChangedListener]处理[editText]的焦点,例如:
8789
* ```
8890
* enum class MessageEditor : Editor {
@@ -269,7 +271,7 @@ class InputView @JvmOverloads constructor(
269271
if (contentDiff != Int.MIN_VALUE) {
270272
contentView.offsetTopAndBottom(contentDiff)
271273
}
272-
updateEditBackground(top = contentView.bottom)
274+
updateEditorBackground(top = contentView.bottom)
273275
}
274276
EditorMode.ADJUST_RESIZE -> requestLayout()
275277
}
@@ -345,7 +347,7 @@ class InputView @JvmOverloads constructor(
345347
val top = bottom - it.measuredHeight
346348
it.layout(left, top, right, bottom)
347349
}
348-
updateEditBackground(top = contentView.bottom)
350+
updateEditorBackground(top = contentView.bottom)
349351
exitChange()
350352
exitLayout()
351353
}
@@ -389,7 +391,7 @@ class InputView @JvmOverloads constructor(
389391
return (editorOffset - navBarOffset).coerceAtLeast(0)
390392
}
391393

392-
private fun updateEditBackground(top: Int) {
394+
private fun updateEditorBackground(top: Int) {
393395
editorBackground?.takeIf { it.bounds.top != top }?.invalidateSelf()
394396
}
395397

0 commit comments

Comments
 (0)