限制源编辑框的最大行数,滚动到其他输入框更容易

pull/2343/head
kunfei 2 years ago
parent a03298d805
commit e8b4046277
  1. 74
      app/src/main/java/io/legado/app/ui/widget/code/CodeView.kt
  2. 84
      app/src/main/java/io/legado/app/ui/widget/text/ScrollMultiAutoCompleteTextView.kt
  3. 4
      app/src/main/java/io/legado/app/ui/widget/text/ScrollTextView.kt

@ -1,6 +1,5 @@
package io.legado.app.ui.widget.code package io.legado.app.ui.widget.code
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Paint import android.graphics.Paint
@ -13,9 +12,8 @@ import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import android.text.style.ReplacementSpan import android.text.style.ReplacementSpan
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView import io.legado.app.ui.widget.text.ScrollMultiAutoCompleteTextView
import java.util.* import java.util.*
import java.util.regex.Matcher import java.util.regex.Matcher
import java.util.regex.Pattern import java.util.regex.Pattern
@ -23,7 +21,7 @@ import kotlin.math.roundToInt
@Suppress("unused") @Suppress("unused")
class CodeView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : class CodeView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
AppCompatMultiAutoCompleteTextView(context, attrs) { ScrollMultiAutoCompleteTextView(context, attrs) {
private var tabWidth = 0 private var tabWidth = 0
private var tabWidthInCharacters = 0 private var tabWidthInCharacters = 0
@ -39,12 +37,6 @@ class CodeView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
private val mSyntaxPatternMap: MutableMap<Pattern, Int> = HashMap() private val mSyntaxPatternMap: MutableMap<Pattern, Int> = HashMap()
private var mIndentCharacterList = mutableListOf('{', '+', '-', '*', '/', '=') private var mIndentCharacterList = mutableListOf('{', '+', '-', '*', '/', '=')
//滑动距离的最大边界
private var mOffsetHeight = 0
//是否到顶或者到底的标志
private var mBottomFlag = false
private val mUpdateRunnable = Runnable { private val mUpdateRunnable = Runnable {
val source = text val source = text
highlightWithoutChange(source) highlightWithoutChange(source)
@ -110,46 +102,6 @@ class CodeView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
addTextChangedListener(mEditorTextWatcher) addTextChangedListener(mEditorTextWatcher)
} }
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
initOffsetHeight()
}
override fun onTextChanged(
text: CharSequence,
start: Int,
lengthBefore: Int,
lengthAfter: Int
) {
super.onTextChanged(text, start, lengthBefore, lengthAfter)
initOffsetHeight()
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
//如果是新的按下事件,则对mBottomFlag重新初始化
mBottomFlag = mOffsetHeight <= 0
}
return super.dispatchTouchEvent(event)
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
val result = super.onTouchEvent(event)
//如果是需要拦截,则再拦截,这个方法会在onScrollChanged方法之后再调用一次
if (!mBottomFlag) parent.requestDisallowInterceptTouchEvent(true)
return result
}
override fun onScrollChanged(horiz: Int, vert: Int, oldHoriz: Int, oldVert: Int) {
super.onScrollChanged(horiz, vert, oldHoriz, oldVert)
if (vert == mOffsetHeight || vert == 0) {
//这里触发父布局或祖父布局的滑动事件
parent.requestDisallowInterceptTouchEvent(false)
mBottomFlag = true
}
}
override fun showDropDown() { override fun showDropDown() {
val screenPoint = IntArray(2) val screenPoint = IntArray(2)
getLocationOnScreen(screenPoint) getLocationOnScreen(screenPoint)
@ -165,28 +117,6 @@ class CodeView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
super.showDropDown() super.showDropDown()
} }
private fun initOffsetHeight() {
val mLayoutHeight: Int
//获得内容面板
val mLayout = layout ?: return
//获得内容面板的高度
mLayoutHeight = mLayout.height
//获取上内边距
val paddingTop: Int = totalPaddingTop
//获取下内边距
val paddingBottom: Int = totalPaddingBottom
//获得控件的实际高度
val mHeight: Int = measuredHeight
//计算滑动距离的边界
mOffsetHeight = mLayoutHeight + paddingTop + paddingBottom - mHeight
if (mOffsetHeight <= 0) {
scrollTo(0, 0)
}
}
private fun autoIndent( private fun autoIndent(
source: CharSequence, source: CharSequence,
dest: Spanned, dest: Spanned,

@ -0,0 +1,84 @@
package io.legado.app.ui.widget.text
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView
open class ScrollMultiAutoCompleteTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : AppCompatMultiAutoCompleteTextView(context, attrs) {
//滑动距离的最大边界
private var mOffsetHeight = 0
//是否到顶或者到底的标志
private var mBottomFlag = false
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
initOffsetHeight()
}
override fun onTextChanged(
text: CharSequence,
start: Int,
lengthBefore: Int,
lengthAfter: Int
) {
super.onTextChanged(text, start, lengthBefore, lengthAfter)
initOffsetHeight()
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
//如果是新的按下事件,则对mBottomFlag重新初始化
mBottomFlag = mOffsetHeight <= 0
}
return super.dispatchTouchEvent(event)
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
val result = super.onTouchEvent(event)
//如果是需要拦截,则再拦截,这个方法会在onScrollChanged方法之后再调用一次
if (!mBottomFlag) parent.requestDisallowInterceptTouchEvent(true)
return result
}
override fun onScrollChanged(horiz: Int, vert: Int, oldHoriz: Int, oldVert: Int) {
super.onScrollChanged(horiz, vert, oldHoriz, oldVert)
if (vert == mOffsetHeight || vert == 0) {
//这里触发父布局或祖父布局的滑动事件
parent.requestDisallowInterceptTouchEvent(false)
mBottomFlag = true
}
}
private fun initOffsetHeight() {
val mLayoutHeight: Int
//获得内容面板
val mLayout = layout ?: return
//获得内容面板的高度
mLayoutHeight = mLayout.height
//获取上内边距
val paddingTop: Int = totalPaddingTop
//获取下内边距
val paddingBottom: Int = totalPaddingBottom
//获得控件的实际高度
val mHeight: Int = measuredHeight
//计算滑动距离的边界
mOffsetHeight = mLayoutHeight + paddingTop + paddingBottom - mHeight
if (mOffsetHeight <= 0) {
scrollTo(0, 0)
}
}
}

@ -55,10 +55,6 @@ class ScrollTextView(context: Context, attrs: AttributeSet?) : AppCompatTextView
//如果是新的按下事件,则对mBottomFlag重新初始化 //如果是新的按下事件,则对mBottomFlag重新初始化
mBottomFlag = mOffsetHeight <= 0 mBottomFlag = mOffsetHeight <= 0
} }
//如果已经不要这次事件,则传出取消的信号,这里的作用不大
if (mBottomFlag) {
event.action = MotionEvent.ACTION_CANCEL
}
return super.dispatchTouchEvent(event) return super.dispatchTouchEvent(event)
} }

Loading…
Cancel
Save