mirror of
https://github.com/gedoor/legado.git
synced 2024-08-30 09:23:26 +08:00
限制源编辑框的最大行数,滚动到其他输入框更容易
This commit is contained in:
parent
a03298d805
commit
e8b4046277
@ -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…
Reference in New Issue
Block a user