pull/32/head
parent
ad5fd8fb28
commit
f982626291
@ -0,0 +1,363 @@ |
|||||||
|
package io.legado.app.ui.widget.seekbar |
||||||
|
|
||||||
|
import android.annotation.SuppressLint |
||||||
|
import android.content.Context |
||||||
|
import android.graphics.Canvas |
||||||
|
import android.graphics.drawable.Drawable |
||||||
|
import android.util.AttributeSet |
||||||
|
import android.view.KeyEvent |
||||||
|
import android.view.MotionEvent |
||||||
|
import android.widget.ProgressBar |
||||||
|
import androidx.appcompat.widget.AppCompatSeekBar |
||||||
|
import androidx.core.view.ViewCompat |
||||||
|
import io.legado.app.R |
||||||
|
import io.legado.app.lib.theme.ATH |
||||||
|
import io.legado.app.lib.theme.ThemeStore |
||||||
|
import java.lang.reflect.InvocationTargetException |
||||||
|
import java.lang.reflect.Method |
||||||
|
|
||||||
|
class VerticalSeekBar : AppCompatSeekBar { |
||||||
|
|
||||||
|
private var mIsDragging: Boolean = false |
||||||
|
private var mThumb: Drawable? = null |
||||||
|
private var mMethodSetProgressFromUser: Method? = null |
||||||
|
private var mRotationAngle = ROTATION_ANGLE_CW_90 |
||||||
|
|
||||||
|
var rotationAngle: Int |
||||||
|
get() = mRotationAngle |
||||||
|
set(angle) { |
||||||
|
require(isValidRotationAngle(angle)) { "Invalid angle specified :$angle" } |
||||||
|
|
||||||
|
if (mRotationAngle == angle) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
mRotationAngle = angle |
||||||
|
|
||||||
|
if (useViewRotation()) { |
||||||
|
val wrapper = wrapper |
||||||
|
wrapper?.applyViewRotation() |
||||||
|
} else { |
||||||
|
requestLayout() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private val wrapper: VerticalSeekBarWrapper? |
||||||
|
get() { |
||||||
|
val parent = parent |
||||||
|
|
||||||
|
return if (parent is VerticalSeekBarWrapper) { |
||||||
|
parent |
||||||
|
} else { |
||||||
|
null |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
constructor(context: Context) : super(context) { |
||||||
|
initialize(context, null, 0, 0) |
||||||
|
} |
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { |
||||||
|
initialize(context, attrs, 0, 0) |
||||||
|
} |
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super( |
||||||
|
context, |
||||||
|
attrs, |
||||||
|
defStyle |
||||||
|
) { |
||||||
|
initialize(context, attrs, defStyle, 0) |
||||||
|
} |
||||||
|
|
||||||
|
private fun initialize( |
||||||
|
context: Context, |
||||||
|
attrs: AttributeSet?, |
||||||
|
defStyleAttr: Int, |
||||||
|
defStyleRes: Int |
||||||
|
) { |
||||||
|
ATH.setTint(this, ThemeStore.accentColor(context)) |
||||||
|
ViewCompat.setLayoutDirection(this, ViewCompat.LAYOUT_DIRECTION_LTR) |
||||||
|
|
||||||
|
if (attrs != null) { |
||||||
|
val a = context.obtainStyledAttributes( |
||||||
|
attrs, |
||||||
|
R.styleable.VerticalSeekBar, |
||||||
|
defStyleAttr, |
||||||
|
defStyleRes |
||||||
|
) |
||||||
|
val rotationAngle = a.getInteger(R.styleable.VerticalSeekBar_seekBarRotation, 0) |
||||||
|
if (isValidRotationAngle(rotationAngle)) { |
||||||
|
mRotationAngle = rotationAngle |
||||||
|
} |
||||||
|
a.recycle() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun setThumb(thumb: Drawable) { |
||||||
|
mThumb = thumb |
||||||
|
super.setThumb(thumb) |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility") |
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean { |
||||||
|
return if (useViewRotation()) { |
||||||
|
onTouchEventUseViewRotation(event) |
||||||
|
} else { |
||||||
|
onTouchEventTraditionalRotation(event) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun onTouchEventTraditionalRotation(event: MotionEvent): Boolean { |
||||||
|
if (!isEnabled) { |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
when (event.action) { |
||||||
|
MotionEvent.ACTION_DOWN -> { |
||||||
|
isPressed = true |
||||||
|
onStartTrackingTouch() |
||||||
|
trackTouchEvent(event) |
||||||
|
attemptClaimDrag(true) |
||||||
|
invalidate() |
||||||
|
} |
||||||
|
|
||||||
|
MotionEvent.ACTION_MOVE -> if (mIsDragging) { |
||||||
|
trackTouchEvent(event) |
||||||
|
} |
||||||
|
|
||||||
|
MotionEvent.ACTION_UP -> { |
||||||
|
if (mIsDragging) { |
||||||
|
trackTouchEvent(event) |
||||||
|
onStopTrackingTouch() |
||||||
|
isPressed = false |
||||||
|
} else { |
||||||
|
// Touch up when we never crossed the touch slop threshold |
||||||
|
// should |
||||||
|
// be interpreted as a tap-seek to that location. |
||||||
|
onStartTrackingTouch() |
||||||
|
trackTouchEvent(event) |
||||||
|
onStopTrackingTouch() |
||||||
|
attemptClaimDrag(false) |
||||||
|
} |
||||||
|
// ProgressBar doesn't know to repaint the thumb drawable |
||||||
|
// in its inactive state when the touch stops (because the |
||||||
|
// value has not apparently changed) |
||||||
|
invalidate() |
||||||
|
} |
||||||
|
|
||||||
|
MotionEvent.ACTION_CANCEL -> { |
||||||
|
if (mIsDragging) { |
||||||
|
onStopTrackingTouch() |
||||||
|
isPressed = false |
||||||
|
} |
||||||
|
invalidate() // see above explanation |
||||||
|
} |
||||||
|
} |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
private fun onTouchEventUseViewRotation(event: MotionEvent): Boolean { |
||||||
|
val handled = super.onTouchEvent(event) |
||||||
|
|
||||||
|
if (handled) { |
||||||
|
when (event.action) { |
||||||
|
MotionEvent.ACTION_DOWN -> attemptClaimDrag(true) |
||||||
|
|
||||||
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> attemptClaimDrag(false) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return handled |
||||||
|
} |
||||||
|
|
||||||
|
private fun trackTouchEvent(event: MotionEvent) { |
||||||
|
val paddingLeft = super.getPaddingLeft() |
||||||
|
val paddingRight = super.getPaddingRight() |
||||||
|
val height = height |
||||||
|
|
||||||
|
val available = height - paddingLeft - paddingRight |
||||||
|
val y = event.y.toInt() |
||||||
|
|
||||||
|
val scale: Float |
||||||
|
var value = 0f |
||||||
|
|
||||||
|
when (mRotationAngle) { |
||||||
|
ROTATION_ANGLE_CW_90 -> value = (y - paddingLeft).toFloat() |
||||||
|
ROTATION_ANGLE_CW_270 -> value = (height - paddingLeft - y).toFloat() |
||||||
|
} |
||||||
|
|
||||||
|
scale = if (value < 0 || available == 0) { |
||||||
|
0.0f |
||||||
|
} else if (value > available) { |
||||||
|
1.0f |
||||||
|
} else { |
||||||
|
value / available.toFloat() |
||||||
|
} |
||||||
|
|
||||||
|
val max = max |
||||||
|
val progress = scale * max |
||||||
|
|
||||||
|
setProgressFromUser(progress.toInt(), true) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tries to claim the user's drag motion, and requests disallowing any |
||||||
|
* ancestors from stealing events in the drag. |
||||||
|
*/ |
||||||
|
private fun attemptClaimDrag(active: Boolean) { |
||||||
|
val parent = parent |
||||||
|
parent?.requestDisallowInterceptTouchEvent(active) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This is called when the user has started touching this widget. |
||||||
|
*/ |
||||||
|
private fun onStartTrackingTouch() { |
||||||
|
mIsDragging = true |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This is called when the user either releases his touch or the touch is |
||||||
|
* canceled. |
||||||
|
*/ |
||||||
|
private fun onStopTrackingTouch() { |
||||||
|
mIsDragging = false |
||||||
|
} |
||||||
|
|
||||||
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { |
||||||
|
if (isEnabled) { |
||||||
|
val handled: Boolean |
||||||
|
var direction = 0 |
||||||
|
|
||||||
|
when (keyCode) { |
||||||
|
KeyEvent.KEYCODE_DPAD_DOWN -> { |
||||||
|
direction = if (mRotationAngle == ROTATION_ANGLE_CW_90) 1 else -1 |
||||||
|
handled = true |
||||||
|
} |
||||||
|
KeyEvent.KEYCODE_DPAD_UP -> { |
||||||
|
direction = if (mRotationAngle == ROTATION_ANGLE_CW_270) 1 else -1 |
||||||
|
handled = true |
||||||
|
} |
||||||
|
KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT -> |
||||||
|
// move view focus to previous/next view |
||||||
|
return false |
||||||
|
else -> handled = false |
||||||
|
} |
||||||
|
|
||||||
|
if (handled) { |
||||||
|
val keyProgressIncrement = keyProgressIncrement |
||||||
|
var progress = progress |
||||||
|
|
||||||
|
progress += direction * keyProgressIncrement |
||||||
|
|
||||||
|
if (progress in 0..max) { |
||||||
|
setProgressFromUser(progress, true) |
||||||
|
} |
||||||
|
|
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return super.onKeyDown(keyCode, event) |
||||||
|
} |
||||||
|
|
||||||
|
@Synchronized |
||||||
|
override fun setProgress(progress: Int) { |
||||||
|
super.setProgress(progress) |
||||||
|
if (!useViewRotation()) { |
||||||
|
refreshThumb() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Synchronized |
||||||
|
private fun setProgressFromUser(progress: Int, fromUser: Boolean) { |
||||||
|
if (mMethodSetProgressFromUser == null) { |
||||||
|
try { |
||||||
|
val m: Method = ProgressBar::class.java.getDeclaredMethod( |
||||||
|
"setProgress", |
||||||
|
Int::class.javaPrimitiveType, |
||||||
|
Boolean::class.javaPrimitiveType |
||||||
|
) |
||||||
|
m.isAccessible = true |
||||||
|
mMethodSetProgressFromUser = m |
||||||
|
} catch (e: NoSuchMethodException) { |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if (mMethodSetProgressFromUser != null) { |
||||||
|
try { |
||||||
|
mMethodSetProgressFromUser!!.invoke(this, progress, fromUser) |
||||||
|
} catch (e: IllegalArgumentException) { |
||||||
|
} catch (e: IllegalAccessException) { |
||||||
|
} catch (e: InvocationTargetException) { |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
super.setProgress(progress) |
||||||
|
} |
||||||
|
refreshThumb() |
||||||
|
} |
||||||
|
|
||||||
|
@Synchronized |
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { |
||||||
|
if (useViewRotation()) { |
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec) |
||||||
|
} else { |
||||||
|
super.onMeasure(heightMeasureSpec, widthMeasureSpec) |
||||||
|
|
||||||
|
val lp = layoutParams |
||||||
|
|
||||||
|
if (isInEditMode && lp != null && lp.height >= 0) { |
||||||
|
setMeasuredDimension(super.getMeasuredHeight(), lp.height) |
||||||
|
} else { |
||||||
|
setMeasuredDimension(super.getMeasuredHeight(), super.getMeasuredWidth()) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { |
||||||
|
if (useViewRotation()) { |
||||||
|
super.onSizeChanged(w, h, oldw, oldh) |
||||||
|
} else { |
||||||
|
super.onSizeChanged(h, w, oldh, oldw) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Synchronized |
||||||
|
override fun onDraw(canvas: Canvas) { |
||||||
|
if (!useViewRotation()) { |
||||||
|
when (mRotationAngle) { |
||||||
|
ROTATION_ANGLE_CW_90 -> { |
||||||
|
canvas.rotate(90f) |
||||||
|
canvas.translate(0f, (-super.getWidth()).toFloat()) |
||||||
|
} |
||||||
|
ROTATION_ANGLE_CW_270 -> { |
||||||
|
canvas.rotate(-90f) |
||||||
|
canvas.translate((-super.getHeight()).toFloat(), 0f) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
super.onDraw(canvas) |
||||||
|
} |
||||||
|
|
||||||
|
// refresh thumb position |
||||||
|
private fun refreshThumb() { |
||||||
|
onSizeChanged(super.getWidth(), super.getHeight(), 0, 0) |
||||||
|
} |
||||||
|
|
||||||
|
/*package*/ |
||||||
|
internal fun useViewRotation(): Boolean { |
||||||
|
return !isInEditMode |
||||||
|
} |
||||||
|
|
||||||
|
companion object { |
||||||
|
const val ROTATION_ANGLE_CW_90 = 90 |
||||||
|
const val ROTATION_ANGLE_CW_270 = 270 |
||||||
|
|
||||||
|
private fun isValidRotationAngle(angle: Int): Boolean { |
||||||
|
return angle == ROTATION_ANGLE_CW_90 || angle == ROTATION_ANGLE_CW_270 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,184 @@ |
|||||||
|
package io.legado.app.ui.widget.seekbar |
||||||
|
|
||||||
|
import android.annotation.SuppressLint |
||||||
|
import android.content.Context |
||||||
|
import android.util.AttributeSet |
||||||
|
import android.view.Gravity |
||||||
|
import android.view.View |
||||||
|
import android.view.ViewGroup |
||||||
|
import android.widget.FrameLayout |
||||||
|
|
||||||
|
import androidx.core.view.ViewCompat |
||||||
|
import kotlin.math.max |
||||||
|
|
||||||
|
class VerticalSeekBarWrapper @JvmOverloads constructor( |
||||||
|
context: Context, |
||||||
|
attrs: AttributeSet? = null, |
||||||
|
defStyleAttr: Int = 0 |
||||||
|
) : FrameLayout(context, attrs, defStyleAttr) { |
||||||
|
|
||||||
|
private val childSeekBar: VerticalSeekBar? |
||||||
|
get() { |
||||||
|
val child = if (childCount > 0) getChildAt(0) else null |
||||||
|
return if (child is VerticalSeekBar) child else null |
||||||
|
} |
||||||
|
|
||||||
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { |
||||||
|
if (useViewRotation()) { |
||||||
|
onSizeChangedUseViewRotation(w, h, oldw, oldh) |
||||||
|
} else { |
||||||
|
onSizeChangedTraditionalRotation(w, h, oldw, oldh) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressLint("RtlHardcoded") |
||||||
|
private fun onSizeChangedTraditionalRotation(w: Int, h: Int, oldw: Int, oldh: Int) { |
||||||
|
val seekBar = childSeekBar |
||||||
|
|
||||||
|
if (seekBar != null) { |
||||||
|
val hPadding = paddingLeft + paddingRight |
||||||
|
val vPadding = paddingTop + paddingBottom |
||||||
|
val lp = seekBar.layoutParams as LayoutParams |
||||||
|
|
||||||
|
lp.width = ViewGroup.LayoutParams.WRAP_CONTENT |
||||||
|
lp.height = max(0, h - vPadding) |
||||||
|
seekBar.layoutParams = lp |
||||||
|
|
||||||
|
seekBar.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED) |
||||||
|
|
||||||
|
val seekBarMeasuredWidth = seekBar.measuredWidth |
||||||
|
seekBar.measure( |
||||||
|
MeasureSpec.makeMeasureSpec( |
||||||
|
max(0, w - hPadding), |
||||||
|
MeasureSpec.AT_MOST |
||||||
|
), |
||||||
|
MeasureSpec.makeMeasureSpec( |
||||||
|
max(0, h - vPadding), |
||||||
|
MeasureSpec.EXACTLY |
||||||
|
) |
||||||
|
) |
||||||
|
|
||||||
|
lp.gravity = Gravity.TOP or Gravity.LEFT |
||||||
|
lp.leftMargin = (max(0, w - hPadding) - seekBarMeasuredWidth) / 2 |
||||||
|
seekBar.layoutParams = lp |
||||||
|
} |
||||||
|
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh) |
||||||
|
} |
||||||
|
|
||||||
|
private fun onSizeChangedUseViewRotation(w: Int, h: Int, oldw: Int, oldh: Int) { |
||||||
|
val seekBar = childSeekBar |
||||||
|
|
||||||
|
if (seekBar != null) { |
||||||
|
val hPadding = paddingLeft + paddingRight |
||||||
|
val vPadding = paddingTop + paddingBottom |
||||||
|
seekBar.measure( |
||||||
|
MeasureSpec.makeMeasureSpec( |
||||||
|
max(0, h - vPadding), |
||||||
|
MeasureSpec.EXACTLY |
||||||
|
), |
||||||
|
MeasureSpec.makeMeasureSpec( |
||||||
|
max(0, w - hPadding), |
||||||
|
MeasureSpec.AT_MOST |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
applyViewRotation(w, h) |
||||||
|
super.onSizeChanged(w, h, oldw, oldh) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { |
||||||
|
val seekBar = childSeekBar |
||||||
|
val widthMode = MeasureSpec.getMode(widthMeasureSpec) |
||||||
|
val heightMode = MeasureSpec.getMode(heightMeasureSpec) |
||||||
|
val widthSize = MeasureSpec.getSize(widthMeasureSpec) |
||||||
|
val heightSize = MeasureSpec.getSize(heightMeasureSpec) |
||||||
|
|
||||||
|
if (seekBar != null && widthMode != MeasureSpec.EXACTLY) { |
||||||
|
val seekBarWidth: Int |
||||||
|
val seekBarHeight: Int |
||||||
|
val hPadding = paddingLeft + paddingRight |
||||||
|
val vPadding = paddingTop + paddingBottom |
||||||
|
val innerContentWidthMeasureSpec = |
||||||
|
MeasureSpec.makeMeasureSpec(max(0, widthSize - hPadding), widthMode) |
||||||
|
val innerContentHeightMeasureSpec = |
||||||
|
MeasureSpec.makeMeasureSpec(max(0, heightSize - vPadding), heightMode) |
||||||
|
|
||||||
|
if (useViewRotation()) { |
||||||
|
seekBar.measure(innerContentHeightMeasureSpec, innerContentWidthMeasureSpec) |
||||||
|
seekBarWidth = seekBar.measuredHeight |
||||||
|
seekBarHeight = seekBar.measuredWidth |
||||||
|
} else { |
||||||
|
seekBar.measure(innerContentWidthMeasureSpec, innerContentHeightMeasureSpec) |
||||||
|
seekBarWidth = seekBar.measuredWidth |
||||||
|
seekBarHeight = seekBar.measuredHeight |
||||||
|
} |
||||||
|
|
||||||
|
val measuredWidth = |
||||||
|
View.resolveSizeAndState(seekBarWidth + hPadding, widthMeasureSpec, 0) |
||||||
|
val measuredHeight = |
||||||
|
View.resolveSizeAndState(seekBarHeight + vPadding, heightMeasureSpec, 0) |
||||||
|
|
||||||
|
setMeasuredDimension(measuredWidth, measuredHeight) |
||||||
|
} else { |
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/*package*/ |
||||||
|
internal fun applyViewRotation() { |
||||||
|
applyViewRotation(width, height) |
||||||
|
} |
||||||
|
|
||||||
|
private fun applyViewRotation(w: Int, h: Int) { |
||||||
|
val seekBar = childSeekBar |
||||||
|
|
||||||
|
if (seekBar != null) { |
||||||
|
val isLTR = ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_LTR |
||||||
|
val rotationAngle = seekBar.rotationAngle |
||||||
|
val seekBarMeasuredWidth = seekBar.measuredWidth |
||||||
|
val seekBarMeasuredHeight = seekBar.measuredHeight |
||||||
|
val hPadding = paddingLeft + paddingRight |
||||||
|
val vPadding = paddingTop + paddingBottom |
||||||
|
val hOffset = (max(0, w - hPadding) - seekBarMeasuredHeight) * 0.5f |
||||||
|
val lp = seekBar.layoutParams |
||||||
|
|
||||||
|
lp.width = max(0, h - vPadding) |
||||||
|
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT |
||||||
|
|
||||||
|
seekBar.layoutParams = lp |
||||||
|
|
||||||
|
seekBar.pivotX = (if (isLTR) 0 else max(0, h - vPadding)).toFloat() |
||||||
|
seekBar.pivotY = 0f |
||||||
|
|
||||||
|
when (rotationAngle) { |
||||||
|
VerticalSeekBar.ROTATION_ANGLE_CW_90 -> { |
||||||
|
seekBar.rotation = 90f |
||||||
|
if (isLTR) { |
||||||
|
seekBar.translationX = seekBarMeasuredHeight + hOffset |
||||||
|
seekBar.translationY = 0f |
||||||
|
} else { |
||||||
|
seekBar.translationX = -hOffset |
||||||
|
seekBar.translationY = seekBarMeasuredWidth.toFloat() |
||||||
|
} |
||||||
|
} |
||||||
|
VerticalSeekBar.ROTATION_ANGLE_CW_270 -> { |
||||||
|
seekBar.rotation = 270f |
||||||
|
if (isLTR) { |
||||||
|
seekBar.translationX = hOffset |
||||||
|
seekBar.translationY = seekBarMeasuredWidth.toFloat() |
||||||
|
} else { |
||||||
|
seekBar.translationX = -(seekBarMeasuredHeight + hOffset) |
||||||
|
seekBar.translationY = 0f |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun useViewRotation(): Boolean { |
||||||
|
val seekBar = childSeekBar |
||||||
|
return seekBar?.useViewRotation() ?: false |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1024" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
|
||||||
|
<path |
||||||
|
android:fillColor="#FFFFFF" |
||||||
|
android:pathData="M462.933333 539.733333h98.133334L512 384l-49.066667 155.733333z m390.4-170.666666V170.666667h-200.106666L512 29.44 370.773333 170.666667H170.666667v200.106666L29.44 512 170.666667 653.226667V853.333333h200.106666L512 994.56 653.226667 853.333333H853.333333v-200.106666L994.56 512 853.333333 370.773333zM610.133333 682.666667l-29.866666-85.333334h-136.533334l-29.866666 85.333334H332.8L469.333333 298.666667h85.333334l136.533333 384z" /> |
||||||
|
</vector> |
Loading…
Reference in new issue