pull/32/head
gedoor 6 years ago
parent b400ab884b
commit 2539b1a67f
  1. 233
      app/src/main/java/io/legado/app/ui/widget/BadgeView.kt
  2. 207
      app/src/main/java/io/legado/app/ui/widget/RotateLoading.kt
  3. 56
      app/src/main/java/io/legado/app/ui/widget/image/CoverImageView.kt
  4. 92
      app/src/main/java/io/legado/app/ui/widget/image/FilletImageView.kt
  5. 175
      app/src/main/res/layout/item_bookshelf_list.xml
  6. 6
      app/src/main/res/values/attrs.xml

@ -0,0 +1,233 @@
package io.legado.app.ui.widget
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RoundRectShape
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.FrameLayout.LayoutParams
import android.widget.TabWidget
import androidx.appcompat.widget.AppCompatTextView
import io.legado.app.R
/**
* Created by milad heydari on 5/6/2016.
*/
class BadgeView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = android.R.attr.textViewStyle
) : AppCompatTextView(context, attrs, defStyle) {
/**
* @return Returns true if view is hidden on badge value 0 or null;
*/
/**
* @param hideOnNull the hideOnNull to set
*/
var isHideOnNull = true
set(hideOnNull) {
field = hideOnNull
text = text
}
private var radius: Float = 0.toFloat()
val badgeCount: Int?
get() {
if (text == null) {
return null
}
val text = text.toString()
try {
return Integer.parseInt(text)
} catch (e: NumberFormatException) {
return null
}
}
var badgeGravity: Int
get() {
val params = layoutParams as LayoutParams
return params.gravity
}
set(gravity) {
val params = layoutParams as LayoutParams
params.gravity = gravity
layoutParams = params
}
val badgeMargin: IntArray
get() {
val params = layoutParams as LayoutParams
return intArrayOf(params.leftMargin, params.topMargin, params.rightMargin, params.bottomMargin)
}
init {
init()
}
private fun init() {
if (layoutParams !is LayoutParams) {
val layoutParams = LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.CENTER
)
setLayoutParams(layoutParams)
}
// set default font
setTextColor(Color.WHITE)
//setTypeface(Typeface.DEFAULT_BOLD);
setTextSize(TypedValue.COMPLEX_UNIT_SP, 11f)
setPadding(dip2Px(5f), dip2Px(1f), dip2Px(5f), dip2Px(1f))
radius = 8f
// set default background
setBackground(radius, Color.parseColor("#d3321b"))
gravity = Gravity.CENTER
// default values
isHideOnNull = true
setBadgeCount(0)
minWidth = dip2Px(16f)
minHeight = dip2Px(16f)
}
fun setBackground(dipRadius: Float, badgeColor: Int) {
val radius = dip2Px(dipRadius)
val radiusArray = floatArrayOf(
radius.toFloat(),
radius.toFloat(),
radius.toFloat(),
radius.toFloat(),
radius.toFloat(),
radius.toFloat(),
radius.toFloat(),
radius.toFloat()
)
val roundRect = RoundRectShape(radiusArray, null, null)
val bgDrawable = ShapeDrawable(roundRect)
bgDrawable.paint.color = badgeColor
background = bgDrawable
}
fun setBackground(badgeColor: Int) {
setBackground(radius, badgeColor)
}
/**
* @see android.widget.TextView.setText
*/
override fun setText(text: CharSequence, type: BufferType) {
if (isHideOnNull && TextUtils.isEmpty(text)) {
visibility = View.GONE
} else {
visibility = View.VISIBLE
}
super.setText(text, type)
}
fun setBadgeCount(count: Int) {
text = count.toString()
if (count == 0) {
visibility = View.GONE
}
}
fun setHighlight(highlight: Boolean) {
setBackground(resources.getColor(if (highlight) R.color.highlight else R.color.darker_gray))
}
fun setBadgeMargin(dipMargin: Int) {
setBadgeMargin(dipMargin, dipMargin, dipMargin, dipMargin)
}
fun setBadgeMargin(leftDipMargin: Int, topDipMargin: Int, rightDipMargin: Int, bottomDipMargin: Int) {
val params = layoutParams as LayoutParams
params.leftMargin = dip2Px(leftDipMargin.toFloat())
params.topMargin = dip2Px(topDipMargin.toFloat())
params.rightMargin = dip2Px(rightDipMargin.toFloat())
params.bottomMargin = dip2Px(bottomDipMargin.toFloat())
layoutParams = params
}
fun incrementBadgeCount(increment: Int) {
val count = badgeCount
if (count == null) {
setBadgeCount(increment)
} else {
setBadgeCount(increment + count)
}
}
fun decrementBadgeCount(decrement: Int) {
incrementBadgeCount(-decrement)
}
/**
* Attach the BadgeView to the TabWidget
* @param target the TabWidget to attach the BadgeView
* @param tabIndex index of the tab
*/
fun setTargetView(target: TabWidget, tabIndex: Int) {
val tabView = target.getChildTabViewAt(tabIndex)
setTargetView(tabView)
}
/**
* Attach the BadgeView to the target view
* @param target the view to attach the BadgeView
*/
fun setTargetView(target: View?) {
if (parent != null) {
(parent as ViewGroup).removeView(this)
}
if (target == null) {
return
}
if (target.parent is FrameLayout) {
(target.parent as FrameLayout).addView(this)
} else if (target.parent is ViewGroup) {
// use a new FrameLayout container for adding badge
val parentContainer = target.parent as ViewGroup
val groupIndex = parentContainer.indexOfChild(target)
parentContainer.removeView(target)
val badgeContainer = FrameLayout(context)
val parentLayoutParams = target.layoutParams
badgeContainer.layoutParams = parentLayoutParams
target.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
parentContainer.addView(badgeContainer, groupIndex, parentLayoutParams)
badgeContainer.addView(target)
badgeContainer.addView(this)
}
}
/**
* converts dip to px
*/
private fun dip2Px(dip: Float): Int {
return (dip * context.resources.displayMetrics.density + 0.5f).toInt()
}
}

@ -0,0 +1,207 @@
package io.legado.app.ui.widget
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import android.view.animation.LinearInterpolator
import io.legado.app.R
/**
* RotateLoading
* Created by Victor on 2015/4/28.
*/
class RotateLoading : View {
private var mPaint: Paint? = null
private var loadingRectF: RectF? = null
private var shadowRectF: RectF? = null
private var topDegree = 10
private var bottomDegree = 190
private var arc: Float = 0.toFloat()
private var thisWidth: Int = 0
private var changeBigger = true
private var shadowPosition: Int = 0
var isStart = false
private set
var loadingColor: Int = 0
private var speedOfDegree: Int = 0
private var speedOfArc: Float = 0.toFloat()
constructor(context: Context) : super(context) {
initView(context, null)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
initView(context, attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
initView(context, attrs)
}
private fun initView(context: Context, attrs: AttributeSet?) {
loadingColor = Color.WHITE
thisWidth = dpToPx(context, DEFAULT_WIDTH.toFloat())
shadowPosition = dpToPx(getContext(), DEFAULT_SHADOW_POSITION.toFloat())
speedOfDegree = DEFAULT_SPEED_OF_DEGREE
if (null != attrs) {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RotateLoading)
loadingColor = typedArray.getColor(R.styleable.RotateLoading_loading_color, Color.WHITE)
thisWidth = typedArray.getDimensionPixelSize(
R.styleable.RotateLoading_loading_width,
dpToPx(context, DEFAULT_WIDTH.toFloat())
)
shadowPosition = typedArray.getInt(R.styleable.RotateLoading_shadow_position, DEFAULT_SHADOW_POSITION)
speedOfDegree = typedArray.getInt(R.styleable.RotateLoading_loading_speed, DEFAULT_SPEED_OF_DEGREE)
typedArray.recycle()
}
speedOfArc = (speedOfDegree / 4).toFloat()
mPaint = Paint()
mPaint!!.color = loadingColor
mPaint!!.isAntiAlias = true
mPaint!!.style = Paint.Style.STROKE
mPaint!!.strokeWidth = thisWidth.toFloat()
mPaint!!.strokeCap = Paint.Cap.ROUND
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
arc = 10f
loadingRectF =
RectF((2 * thisWidth).toFloat(), (2 * thisWidth).toFloat(), (w - 2 * thisWidth).toFloat(), (h - 2 * thisWidth).toFloat())
shadowRectF = RectF(
(2 * thisWidth + shadowPosition).toFloat(),
(2 * thisWidth + shadowPosition).toFloat(),
(w - 2 * thisWidth + shadowPosition).toFloat(),
(h - 2 * thisWidth + shadowPosition).toFloat()
)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (!isStart) {
return
}
mPaint!!.color = Color.parseColor("#1a000000")
canvas.drawArc(shadowRectF!!, topDegree.toFloat(), arc, false, mPaint!!)
canvas.drawArc(shadowRectF!!, bottomDegree.toFloat(), arc, false, mPaint!!)
mPaint!!.color = loadingColor
canvas.drawArc(loadingRectF!!, topDegree.toFloat(), arc, false, mPaint!!)
canvas.drawArc(loadingRectF!!, bottomDegree.toFloat(), arc, false, mPaint!!)
topDegree += speedOfDegree
bottomDegree += speedOfDegree
if (topDegree > 360) {
topDegree = topDegree - 360
}
if (bottomDegree > 360) {
bottomDegree = bottomDegree - 360
}
if (changeBigger) {
if (arc < 160) {
arc += speedOfArc
invalidate()
}
} else {
if (arc > speedOfDegree) {
arc -= 2 * speedOfArc
invalidate()
}
}
if (arc >= 160 || arc <= 10) {
changeBigger = !changeBigger
invalidate()
}
}
fun start() {
startAnimator()
isStart = true
invalidate()
}
fun stop() {
stopAnimator()
invalidate()
}
private fun startAnimator() {
val scaleXAnimator = ObjectAnimator.ofFloat(this, "scaleX", 0.0f, 1f)
val scaleYAnimator = ObjectAnimator.ofFloat(this, "scaleY", 0.0f, 1f)
scaleXAnimator.setDuration(300)
scaleXAnimator.setInterpolator(LinearInterpolator())
scaleYAnimator.setDuration(300)
scaleYAnimator.setInterpolator(LinearInterpolator())
val animatorSet = AnimatorSet()
animatorSet.playTogether(scaleXAnimator, scaleYAnimator)
animatorSet.start()
}
private fun stopAnimator() {
val scaleXAnimator = ObjectAnimator.ofFloat(this, "scaleX", 1f, 0f)
val scaleYAnimator = ObjectAnimator.ofFloat(this, "scaleY", 1f, 0f)
scaleXAnimator.setDuration(300)
scaleXAnimator.setInterpolator(LinearInterpolator())
scaleYAnimator.setDuration(300)
scaleYAnimator.setInterpolator(LinearInterpolator())
val animatorSet = AnimatorSet()
animatorSet.playTogether(scaleXAnimator, scaleYAnimator)
animatorSet.addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) {
}
override fun onAnimationEnd(animation: Animator) {
isStart = false
}
override fun onAnimationCancel(animation: Animator) {
}
override fun onAnimationRepeat(animation: Animator) {
}
})
animatorSet.start()
}
fun dpToPx(context: Context, dpVal: Float): Int {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.resources.displayMetrics).toInt()
}
companion object {
private val DEFAULT_WIDTH = 6
private val DEFAULT_SHADOW_POSITION = 2
private val DEFAULT_SPEED_OF_DEGREE = 10
}
}

@ -0,0 +1,56 @@
package io.legado.app.ui.widget.image
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Path
import android.util.AttributeSet
class CoverImageView : androidx.appcompat.widget.AppCompatImageView {
internal var width: Float = 0.toFloat()
internal var height: Float = 0.toFloat()
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
width = getWidth().toFloat()
height = getHeight().toFloat()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val measuredWidth = MeasureSpec.getSize(widthMeasureSpec)
val measuredHeight = measuredWidth * 7 / 5
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY))
}
override fun onDraw(canvas: Canvas) {
if (width >= 10 && height > 10) {
@SuppressLint("DrawAllocation")
val path = Path()
//四个圆角
path.moveTo(10f, 0f)
path.lineTo(width - 10, 0f)
path.quadTo(width, 0f, width, 10f)
path.lineTo(width, height - 10)
path.quadTo(width, height, width - 10, height)
path.lineTo(10f, height)
path.quadTo(0f, height, 0f, height - 10)
path.lineTo(0f, 10f)
path.quadTo(0f, 0f, 10f, 0f)
canvas.clipPath(path)
}
super.onDraw(canvas)
}
fun setHeight(height: Int) {
val width = height * 5 / 7
minimumWidth = width
}
}

@ -0,0 +1,92 @@
package io.legado.app.ui.widget.image
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Path
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView
import io.legado.app.R
class FilletImageView : AppCompatImageView {
internal var width: Float = 0.toFloat()
internal var height: Float = 0.toFloat()
private var leftTopRadius: Int = 0
private var rightTopRadius: Int = 0
private var rightBottomRadius: Int = 0
private var leftBottomRadius: Int = 0
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context, attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init(context, attrs)
}
private fun init(context: Context, attrs: AttributeSet) {
// 读取配置
val array = context.obtainStyledAttributes(attrs, R.styleable.FilletImageView)
val defaultRadius = 5
val radius = array.getDimensionPixelOffset(R.styleable.FilletImageView_radius, defaultRadius)
leftTopRadius = array.getDimensionPixelOffset(R.styleable.FilletImageView_left_top_radius, defaultRadius)
rightTopRadius = array.getDimensionPixelOffset(R.styleable.FilletImageView_right_top_radius, defaultRadius)
rightBottomRadius =
array.getDimensionPixelOffset(R.styleable.FilletImageView_right_bottom_radius, defaultRadius)
leftBottomRadius = array.getDimensionPixelOffset(R.styleable.FilletImageView_left_bottom_radius, defaultRadius)
//如果四个角的值没有设置,那么就使用通用的radius的值。
if (defaultRadius == leftTopRadius) {
leftTopRadius = radius
}
if (defaultRadius == rightTopRadius) {
rightTopRadius = radius
}
if (defaultRadius == rightBottomRadius) {
rightBottomRadius = radius
}
if (defaultRadius == leftBottomRadius) {
leftBottomRadius = radius
}
array.recycle()
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
width = getWidth().toFloat()
height = getHeight().toFloat()
}
override fun onDraw(canvas: Canvas) {
//这里做下判断,只有图片的宽高大于设置的圆角距离的时候才进行裁剪
val maxLeft = Math.max(leftTopRadius, leftBottomRadius)
val maxRight = Math.max(rightTopRadius, rightBottomRadius)
val minWidth = maxLeft + maxRight
val maxTop = Math.max(leftTopRadius, rightTopRadius)
val maxBottom = Math.max(leftBottomRadius, rightBottomRadius)
val minHeight = maxTop + maxBottom
if (width >= minWidth && height > minHeight) {
@SuppressLint("DrawAllocation") val path = Path()
//四个角:右上,右下,左下,左上
path.moveTo(leftTopRadius.toFloat(), 0f)
path.lineTo(width - rightTopRadius, 0f)
path.quadTo(width, 0f, width, rightTopRadius.toFloat())
path.lineTo(width, height - rightBottomRadius)
path.quadTo(width, height, width - rightBottomRadius, height)
path.lineTo(leftBottomRadius.toFloat(), height)
path.quadTo(0f, height, 0f, height - leftBottomRadius)
path.lineTo(0f, leftTopRadius.toFloat())
path.quadTo(0f, 0f, leftTopRadius.toFloat(), 0f)
canvas.clipPath(path)
}
super.onDraw(canvas)
}
}

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
tools:ignore="UnusedAttribute">
<io.legado.app.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="60dp"
android:layout_height="80dp"
android:layout_margin="8dp"
android:contentDescription="@string/img_cover"
android:scaleType="centerCrop"
android:src="@drawable/img_cover_default"
android:transitionName="img_cover"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UnusedAttribute" />
<FrameLayout
android:id="@+id/fl_has_new"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_name">
<io.legado.app.ui.widget.BadgeView
android:id="@+id/bv_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_margin="5dp"
android:includeFontPadding="false"
tools:ignore="RtlHardcoded" />
<com.victor.loading.rotate.RotateLoading
android:id="@+id/rl_loading"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_gravity="right"
android:visibility="invisible"
app:loading_color="@color/colorAccent"
app:loading_width="2dp"
tools:ignore="RtlHardcoded" />
</FrameLayout>
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:includeFontPadding="false"
android:paddingLeft="4dp"
android:singleLine="true"
android:text="@string/book_name"
android:textColor="@color/tv_text_default"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/tv_author"
app:layout_constraintLeft_toRightOf="@+id/iv_cover"
app:layout_constraintRight_toLeftOf="@id/fl_has_new"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_author"
android:layout_width="@dimen/desc_icon_size"
android:layout_height="@dimen/desc_icon_size"
android:layout_marginLeft="8dp"
android:contentDescription="@string/author"
android:paddingStart="2dp"
android:paddingEnd="2dp"
android:src="@drawable/ic_author"
app:layout_constraintBottom_toBottomOf="@+id/tv_author"
app:layout_constraintLeft_toRightOf="@+id/iv_cover"
app:layout_constraintTop_toTopOf="@+id/tv_author"
app:tint="@color/tv_text_secondary"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_author"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:maxLines="1"
android:paddingEnd="6dp"
android:text="@string/author"
android:textColor="@color/tv_text_secondary"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@+id/tv_read"
app:layout_constraintLeft_toRightOf="@+id/iv_author"
app:layout_constraintRight_toLeftOf="@id/fl_has_new"
app:layout_constraintTop_toBottomOf="@+id/tv_name"
tools:ignore="RtlSymmetry" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_read"
android:layout_width="@dimen/desc_icon_size"
android:layout_height="@dimen/desc_icon_size"
android:layout_marginLeft="8dp"
android:contentDescription="@string/read_dur_progress"
android:paddingStart="2dp"
android:paddingEnd="2dp"
android:src="@drawable/ic_history"
app:layout_constraintBottom_toBottomOf="@+id/tv_read"
app:layout_constraintLeft_toRightOf="@+id/iv_cover"
app:layout_constraintTop_toTopOf="@+id/tv_read"
app:tint="@color/tv_text_secondary"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_read"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:singleLine="true"
android:text="@string/read_dur_progress"
android:textColor="@color/tv_text_secondary"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@id/tv_last"
app:layout_constraintLeft_toRightOf="@+id/iv_read"
app:layout_constraintRight_toLeftOf="@id/fl_has_new"
app:layout_constraintTop_toBottomOf="@+id/tv_author" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_last"
android:layout_width="@dimen/desc_icon_size"
android:layout_height="@dimen/desc_icon_size"
android:layout_marginLeft="8dp"
android:contentDescription="@string/book_search_last"
android:paddingStart="2dp"
android:paddingEnd="2dp"
android:src="@drawable/ic_book_last"
app:layout_constraintBottom_toBottomOf="@+id/tv_last"
app:layout_constraintLeft_toRightOf="@+id/iv_cover"
app:layout_constraintTop_toTopOf="@+id/tv_last"
app:tint="@color/tv_text_secondary"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_last"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:singleLine="true"
android:text="@string/book_search_last"
android:textColor="@color/tv_text_secondary"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/iv_last"
app:layout_constraintRight_toLeftOf="@id/fl_has_new"
app:layout_constraintTop_toBottomOf="@+id/tv_read" />
<View
android:id="@+id/vw_select"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/btn_bg_press"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -101,4 +101,10 @@
<attr name="icons" format="reference"/>
</declare-styleable>
<declare-styleable name="RotateLoading">
<attr name="loading_width" format="dimension"/>
<attr name="loading_color" format="color"/>
<attr name="shadow_position" format="integer"/>
<attr name="loading_speed" format="integer"/>
</declare-styleable>
</resources>
Loading…
Cancel
Save