Commit 15b3536e authored by wanglei's avatar wanglei

...

parent b762cd2f
......@@ -58,10 +58,9 @@ dependencies {
//第三方UI
implementation("io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.4")
implementation("com.github.lukelorusso:VerticalSeekBar:1.2.5")
implementation("com.github.angcyo.DslTablayout:TabLayout:3.5.5")
implementation("com.github.angcyo.DslTablayout:ViewPager2Delegate:3.5.5")
implementation("com.github.bosphere:android-verticalslider:1.0.3")
// implementation("com.github.lukelorusso:VerticalSeekBar:1.2.5")
//mlkit
implementation("com.google.android.gms:play-services-mlkit-document-scanner:16.0.0-beta1")
......
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
package com.base.pdfviewerscannerwhite.ui.view
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.cardview.widget.CardView
import androidx.core.view.ViewCompat
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.utils.LogEx
import kotlin.math.max
import kotlin.math.roundToInt
/**
* A nicer, redesigned and vertical SeekBar
*/
class VerticalSeekBar : FrameLayout {
private val TAG = "VerticalSeekBar"
constructor(context: Context) : super(context) {
LogEx.logDebug(TAG, "init1")
initAttributes(context, null)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
LogEx.logDebug(TAG, "init2")
initAttributes(context, attrs)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
LogEx.logDebug(TAG, "init3")
initAttributes(context, attrs)
}
companion object {
private const val DEFAULT_MAX_VALUE = 100
private const val DEFAULT_PROGRESS = 50
private const val DEFAULT_DRAWABLE_BACKGROUND: String = "#00000000"
private const val DEFAULT_DRAWABLE_PROGRESS_START: String = "#00000000"
private const val DEFAULT_DRAWABLE_PROGRESS_END: String = "#00000000"
}
enum class Placeholder {
OUTSIDE,
INSIDE,
MIDDLE
}
private var onProgressChangeListener: ((Int) -> Unit)? = null
private var onPressListener: ((Int) -> Unit)? = null
private var onReleaseListener: ((Int) -> Unit)? = null
var clickToSetProgress = true
set(value) {
field = value
applyAttributes()
}
var barCornerRadius: Int = 0
set(value) {
field = value
applyAttributes()
}
var barBackgroundDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var barBackgroundStartColor: Int = Color.parseColor(DEFAULT_DRAWABLE_BACKGROUND)
set(value) {
field = value
barBackgroundDrawable = null
applyAttributes()
}
var barBackgroundEndColor: Int = Color.parseColor(DEFAULT_DRAWABLE_BACKGROUND)
set(value) {
field = value
barBackgroundDrawable = null
applyAttributes()
}
var barProgressDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var barProgressStartColor: Int = Color.parseColor(DEFAULT_DRAWABLE_PROGRESS_START)
set(value) {
field = value
barProgressDrawable = null
applyAttributes()
}
var barProgressEndColor: Int = Color.parseColor(DEFAULT_DRAWABLE_PROGRESS_END)
set(value) {
field = value
barProgressDrawable = null
applyAttributes()
}
var barWidth: Int? = null
set(value) {
field = value
applyAttributes()
}
var minLayoutWidth: Int = 0
set(value) {
field = value
applyAttributes()
}
var minLayoutHeight: Int = 0
set(value) {
field = value
applyAttributes()
}
var maxPlaceholderDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var maxPlaceholderPosition = Placeholder.MIDDLE
set(value) {
field = value
applyAttributes()
}
var minPlaceholderDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var minPlaceholderPosition = Placeholder.MIDDLE
set(value) {
field = value
applyAttributes()
}
var showThumb = true
set(value) {
field = value
applyAttributes()
}
var thumbContainerColor: Int = Color.WHITE
set(value) {
field = value
applyAttributes()
}
var thumbContainerCornerRadius: Int = 0
set(value) {
field = value
applyAttributes()
}
var thumbPlaceholderDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var useThumbToSetProgress = true
set(value) {
field = value
applyAttributes()
}
var maxValue = DEFAULT_MAX_VALUE
set(value) {
val newValue = when {
value < 1 -> 1
else -> value
}
if (progress > newValue) progress = newValue
field = newValue
updateViews()
}
var progress: Int = DEFAULT_PROGRESS
set(value) {
val newValue = when {
value < 0 -> 0
value > maxValue -> maxValue
else -> value
}
if (field != newValue) {
onProgressChangeListener?.invoke(newValue)
}
field = newValue
updateViews()
}
private var yDelta: Int = 0
private var initEnded =
false // if true allows the view to be updated after setting an attribute programmatically
lateinit var container: FrameLayout
lateinit var thumb: FrameLayout
lateinit var barCardView: CardView
lateinit var barBackground: View
lateinit var barProgress: View
lateinit var maxPlaceholder: ImageView
lateinit var minPlaceholder: ImageView
private fun initAttributes(context: Context, attrs: AttributeSet?) {
val view = inflate(context, R.layout.layout_verticalseekbar, this)
container = findViewById(R.id.container)
thumb = findViewById(R.id.thumb)
barCardView = findViewById(R.id.barCardView)
barBackground = findViewById(R.id.barBackground)
barProgress = findViewById(R.id.barProgress)
maxPlaceholder = findViewById(R.id.maxPlaceholder)
minPlaceholder = findViewById(R.id.minPlaceholder)
if (attrs != null) {
val attributes =
context.obtainStyledAttributes(attrs, R.styleable.VerticalSeekBar, 0, 0)
LogEx.logDebug(TAG, "attributes=$attributes")
try {
clickToSetProgress =
attributes.getBoolean(
R.styleable.VerticalSeekBar_vsb_click_to_set_progress,
clickToSetProgress
)
barCornerRadius = attributes.getLayoutDimension(
R.styleable.VerticalSeekBar_vsb_bar_corner_radius,
barCornerRadius
)
barBackgroundStartColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_bar_background_gradient_start,
barBackgroundStartColor
)
barBackgroundEndColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_bar_background_gradient_end,
barBackgroundEndColor
)
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_bar_background)?.also {
barBackgroundDrawable = it
}
barProgressStartColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_bar_progress_gradient_start,
barProgressStartColor
)
barProgressEndColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_bar_progress_gradient_end,
barProgressEndColor
)
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_bar_progress).also {
barProgressDrawable = it
}
barWidth = attributes.getDimensionPixelSize(
R.styleable.VerticalSeekBar_vsb_bar_width,
barWidth ?: container.layoutParams.width
)
attributes.getLayoutDimension(
R.styleable.VerticalSeekBar_android_layout_width,
minLayoutWidth
).also {
container.layoutParams.width =
if (it != -1 && it < minLayoutWidth) minLayoutWidth // wrap_content
else it
}
attributes.getLayoutDimension(
R.styleable.VerticalSeekBar_android_layout_height,
minLayoutHeight
).also {
container.layoutParams.height =
if (it != -1 && it < minLayoutHeight) minLayoutHeight // wrap_content
else it
}
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_max_placeholder_src).also {
maxPlaceholderDrawable = it
}
maxPlaceholderPosition = Placeholder.values()[attributes.getInt(
R.styleable.VerticalSeekBar_vsb_max_placeholder_position,
maxPlaceholderPosition.ordinal
)]
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_min_placeholder_src).also {
minPlaceholderDrawable = it
}
minPlaceholderPosition = Placeholder.values()[attributes.getInt(
R.styleable.VerticalSeekBar_vsb_min_placeholder_position,
minPlaceholderPosition.ordinal
)]
showThumb =
attributes.getBoolean(R.styleable.VerticalSeekBar_vsb_show_thumb, showThumb)
thumbContainerColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_thumb_container_tint,
thumbContainerColor
)
thumbContainerCornerRadius = attributes.getLayoutDimension(
R.styleable.VerticalSeekBar_vsb_thumb_container_corner_radius,
thumbContainerCornerRadius
)
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_thumb_placeholder_src).also {
thumbPlaceholderDrawable = it
}
attributes.getInt(R.styleable.VerticalSeekBar_vsb_max_value, maxValue).also {
maxValue = it
}
attributes.getInt(R.styleable.VerticalSeekBar_vsb_progress, progress).also {
progress = it
}
useThumbToSetProgress =
attributes.getBoolean(
R.styleable.VerticalSeekBar_vsb_use_thumb_to_set_progress,
useThumbToSetProgress
)
} finally {
attributes.recycle()
}
}
initEnded = true
applyAttributes()
}
fun setOnProgressChangeListener(listener: ((Int) -> Unit)?) {
this.onProgressChangeListener = listener
}
fun setOnPressListener(listener: ((Int) -> Unit)?) {
this.onPressListener = listener
}
fun setOnReleaseListener(listener: ((Int) -> Unit)?) {
this.onReleaseListener = listener
}
//region PROTECTED METHODS
protected fun Context.dpToPixel(dp: Float): Float =
dp * (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
protected fun Context.pixelToDp(px: Float): Float =
px / (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
//endregion
@SuppressLint("ClickableViewAccessibility")
private fun applyAttributes() {
if (initEnded) {
initEnded = false // will be released at the end
var thumbCardView: CardView? = null // nullable for customization
try {
thumbCardView = thumb.findViewById(R.id.thumbCardView)
} catch (ignored: NoSuchFieldError) {
}
var thumbPlaceholder: ImageView? = null // nullable for customization
try {
thumbPlaceholder = findViewById<FrameLayout>(R.id.thumb).findViewById(R.id.thumbPlaceholder)
} catch (ignored: NoSuchFieldError) {
}
// Customizing drawableCardView
barCardView.layoutParams.width = barWidth ?: 0
// Customizing drawableBackground
if (barBackgroundDrawable == null) barBackgroundDrawable = GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf(barBackgroundStartColor, barBackgroundEndColor)
).apply { cornerRadius = 0f }
barBackground.background = barBackgroundDrawable
// Customizing drawableProgress
if (barProgressDrawable == null) barProgressDrawable = GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf(barProgressStartColor, barProgressEndColor)
).apply { cornerRadius = 0f }
barProgress.background = barProgressDrawable
// Applying card corner radius
barCardView.radius = barCornerRadius.toFloat()
thumbCardView?.radius = thumbContainerCornerRadius.toFloat()
// Applying custom placeholders
maxPlaceholder.setImageDrawable(maxPlaceholderDrawable) // can also be null
minPlaceholder.setImageDrawable(minPlaceholderDrawable) // can also be null
// Let's shape the thumb
val thumbMeasureIncrease =
if (thumbCardView != null) (ViewCompat.getElevation(thumbCardView)
+ context.dpToPixel(1F)).roundToInt()
else 0
if (showThumb) {
thumbPlaceholderDrawable?.also { thumbPlaceholder?.setImageDrawable(it) } // CANNOT be null
thumb.visibility = View.VISIBLE
val states = arrayOf(
intArrayOf(android.R.attr.state_enabled), // enabled
intArrayOf(-android.R.attr.state_enabled), // disabled
intArrayOf(-android.R.attr.state_checked), // unchecked
intArrayOf(android.R.attr.state_pressed) // pressed
)
val colors = arrayOf(
thumbContainerColor,
thumbContainerColor,
thumbContainerColor,
thumbContainerColor
).toIntArray()
if (thumbCardView != null)
ViewCompat.setBackgroundTintList(thumbCardView, ColorStateList(states, colors))
thumb.measure(0, 0)
thumb.layoutParams = (thumb.layoutParams as LayoutParams).apply {
width = thumb.measuredWidth + thumbMeasureIncrease
height = thumb.measuredHeight + thumbMeasureIncrease
thumbCardView?.layoutParams =
(thumbCardView?.layoutParams as LayoutParams).apply {
topMargin = thumbMeasureIncrease / 2
}
}
} else thumb.visibility = View.GONE
// Adding some margin to drawableCardView, maxPlaceholder and minPlaceholder
val maxPlaceholderLayoutParams = (maxPlaceholder.layoutParams as LayoutParams)
val minPlaceholderLayoutParams = (minPlaceholder.layoutParams as LayoutParams)
barCardView.layoutParams = (barCardView.layoutParams as LayoutParams).apply {
val thumbHalfHeight =
if (showThumb) thumb.measuredHeight / 2
else 0
val maxPlaceholderHalfHeight = (maxPlaceholder.drawable?.intrinsicHeight ?: 0) / 2
when (maxPlaceholderPosition) {
Placeholder.INSIDE -> {
topMargin = thumbHalfHeight
maxPlaceholderLayoutParams.topMargin = topMargin
}
Placeholder.OUTSIDE -> {
topMargin = maxPlaceholder.drawable.intrinsicHeight +
if (thumbHalfHeight > maxPlaceholder.drawable.intrinsicHeight)
thumbHalfHeight - maxPlaceholder.drawable.intrinsicHeight
else 0
maxPlaceholderLayoutParams.topMargin =
topMargin - maxPlaceholder.drawable.intrinsicHeight
}
else -> {
topMargin = max(thumbHalfHeight, maxPlaceholderHalfHeight)
maxPlaceholderLayoutParams.topMargin = topMargin - maxPlaceholderHalfHeight
}
}
maxPlaceholderLayoutParams.bottomMargin = maxPlaceholderLayoutParams.topMargin
maxPlaceholder.layoutParams = maxPlaceholderLayoutParams
val minPlaceholderHalfHeight = (minPlaceholder.drawable?.intrinsicHeight ?: 0) / 2
when (minPlaceholderPosition) {
Placeholder.INSIDE -> {
bottomMargin = thumbHalfHeight
minPlaceholderLayoutParams.bottomMargin = bottomMargin
}
Placeholder.OUTSIDE -> {
bottomMargin = minPlaceholder.drawable.intrinsicHeight +
if (thumbHalfHeight > minPlaceholder.drawable.intrinsicHeight)
thumbHalfHeight - minPlaceholder.drawable.intrinsicHeight
else 0
minPlaceholderLayoutParams.bottomMargin =
bottomMargin - minPlaceholder.drawable.intrinsicHeight
}
else -> {
bottomMargin = max(thumbHalfHeight, minPlaceholderHalfHeight)
minPlaceholderLayoutParams.bottomMargin =
bottomMargin - minPlaceholderHalfHeight
}
}
bottomMargin += thumbMeasureIncrease
minPlaceholderLayoutParams.bottomMargin += thumbMeasureIncrease
minPlaceholderLayoutParams.topMargin = maxPlaceholderLayoutParams.bottomMargin
minPlaceholder.layoutParams = minPlaceholderLayoutParams
}
// here we intercept the click on the thumb
if (showThumb && useThumbToSetProgress) thumb.setOnTouchListener { thumb, event ->
val rawY = event.rawY.roundToInt()
when (event.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_DOWN -> { // here we get the max top y coordinate (yDelta)
yDelta = rawY +
(barCardView.layoutParams as LayoutParams).topMargin -
(thumb.layoutParams as LayoutParams).topMargin -
thumb.measuredHeight / 2
onPressListener?.invoke(progress)
}
MotionEvent.ACTION_MOVE -> {
val positionY = rawY - yDelta // here we calculate the displacement
val fillHeight = barCardView.measuredHeight
when { // here we update progress
positionY in 1 until fillHeight -> {
val newValue =
maxValue - (positionY.toFloat() * maxValue / fillHeight)
progress = newValue.roundToInt()
}
positionY <= 0 -> progress = maxValue
positionY >= fillHeight -> progress = 0
}
}
MotionEvent.ACTION_UP -> onReleaseListener?.invoke(progress)
}
true
} else thumb.setOnTouchListener(null)
// here we intercept the click on the bar
if (clickToSetProgress) barCardView.setOnTouchListener { bar, event ->
val positionY = event.y.roundToInt()
val action = {
val fillHeight = bar.measuredHeight
when { // here we update progress
positionY in 1 until fillHeight -> {
val newValue = maxValue - (positionY.toFloat() * maxValue / fillHeight)
progress = newValue.roundToInt()
}
positionY <= 0 -> progress = maxValue
positionY >= fillHeight -> progress = 0
}
}
when (event.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_DOWN -> {
action.invoke()
onPressListener?.invoke(progress)
}
MotionEvent.ACTION_MOVE -> if (useThumbToSetProgress) action.invoke()
MotionEvent.ACTION_UP -> onReleaseListener?.invoke(progress)
}
true
} else barCardView.setOnTouchListener(null)
initEnded = true
updateViews()
}
}
/**
* Inside here the views are repositioned based on the new value
*/
private fun updateViews() {
if (initEnded) post {
val barCardViewLayoutParams = barCardView.layoutParams as LayoutParams
val fillHeight =
height - barCardViewLayoutParams.topMargin - barCardViewLayoutParams.bottomMargin
val marginByProgress = fillHeight - (progress * fillHeight / maxValue)
thumb.layoutParams = (thumb.layoutParams as LayoutParams).apply {
topMargin = marginByProgress
val thumbHalfHeight = if (showThumb) thumb.measuredHeight / 2 else 0
if (barCardViewLayoutParams.topMargin > thumbHalfHeight) {
val displacement = barCardViewLayoutParams.topMargin - thumbHalfHeight
topMargin += displacement
}
}
barProgress.translationY =
(barBackground.height * (maxValue - progress) / maxValue).toFloat()
invalidate()
}
}
}
......@@ -21,15 +21,15 @@
</com.artifex.mupdfdemo.MuPDFReaderView>
<com.lukelorusso.verticalseekbar.VerticalSeekBar
<com.base.pdfviewerscannerwhite.ui.view.VerticalSeekBar
android:id="@+id/vertical_seekbar"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:vsb_bar_background="#00FA6146"
app:vsb_bar_progress="#00FA6146"
app:vsb_bar_background="@color/transparent"
app:vsb_bar_progress="@color/transparent"
app:vsb_show_thumb="true" />
</FrameLayout>
......
......@@ -130,7 +130,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_animator_top" />
<com.lukelorusso.verticalseekbar.VerticalSeekBar
<com.base.pdfviewerscannerwhite.ui.view.VerticalSeekBar
android:id="@+id/vertical_seekbar"
android:layout_width="30dp"
android:layout_height="match_parent"
......
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/transparent">
<androidx.cardview.widget.CardView
android:id="@+id/barCardView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
app:cardBackgroundColor="@color/transparent"
app:cardElevation="0dp">
<View
android:id="@+id/barBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent" />
<View
android:id="@+id/barProgress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent" />
</androidx.cardview.widget.CardView>
<FrameLayout
android:id="@+id/maxPlaceholderLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@color/transparent">
<ImageView
android:id="@+id/maxPlaceholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@null" />
</FrameLayout>
<FrameLayout
android:id="@+id/minPlaceholderLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="@color/transparent">
<ImageView
android:id="@+id/minPlaceholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="@null" />
</FrameLayout>
<FrameLayout
android:id="@+id/thumb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<androidx.cardview.widget.CardView
android:id="@+id/thumbCardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:cardElevation="0dp">
<ImageView
android:id="@+id/thumbPlaceholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null" />
</androidx.cardview.widget.CardView>
</FrameLayout>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="VerticalSeekBar">
<attr name="vsb_click_to_set_progress" format="boolean" />
<attr name="vsb_bar_corner_radius" format="dimension" />
<attr name="vsb_bar_width" format="dimension" />
<attr name="vsb_bar_background" format="reference|color" />
<attr name="vsb_bar_background_gradient_start" format="color" />
<attr name="vsb_bar_background_gradient_end" format="color" />
<attr name="vsb_bar_progress" format="reference|color" />
<attr name="vsb_bar_progress_gradient_start" format="color" />
<attr name="vsb_bar_progress_gradient_end" format="color" />
<attr name="vsb_progress" format="integer" />
<attr name="vsb_max_value" format="integer" />
<attr name="vsb_min_placeholder_position" format="enum">
<enum name="outside" value="0"/>
<enum name="inside" value="1"/>
<enum name="middle" value="2"/>
</attr>
<attr name="vsb_min_placeholder_src" format="reference" />
<attr name="vsb_max_placeholder_position" format="enum">
<enum name="outside" value="0"/>
<enum name="inside" value="1"/>
<enum name="middle" value="2"/>
</attr>
<attr name="vsb_max_placeholder_src" format="reference" />
<attr name="vsb_show_thumb" format="boolean" />
<attr name="vsb_thumb_container_corner_radius" format="dimension" />
<attr name="vsb_thumb_container_tint" format="color" />
<attr name="vsb_thumb_placeholder_src" format="integer" />
<attr name="vsb_use_thumb_to_set_progress" format="boolean" />
<attr name="android:layout_width" />
<attr name="android:layout_height" />
</declare-styleable>
</resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment