优化
This commit is contained in:
@@ -70,7 +70,7 @@ class SpeakEngineDialog(val callBack: CallBack) : BaseDialogFragment(R.layout.di
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
setLayout(0.2f, 0.9f)
|
setLayout(0.92f, 0.9f)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
@@ -91,6 +91,7 @@ class SpeakEngineDialog(val callBack: CallBack) : BaseDialogFragment(R.layout.di
|
|||||||
sysTtsViews.add(cbName)
|
sysTtsViews.add(cbName)
|
||||||
ivEdit.gone()
|
ivEdit.gone()
|
||||||
ivMenuDelete.gone()
|
ivMenuDelete.gone()
|
||||||
|
labelSys.visible()
|
||||||
cbName.text = engine.label
|
cbName.text = engine.label
|
||||||
cbName.tag = engine.name
|
cbName.tag = engine.name
|
||||||
cbName.isChecked =
|
cbName.isChecked =
|
||||||
|
|||||||
@@ -0,0 +1,323 @@
|
|||||||
|
package io.legado.app.ui.widget.text
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Path
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.View
|
||||||
|
import io.legado.app.R
|
||||||
|
import io.legado.app.lib.theme.accentColor
|
||||||
|
|
||||||
|
@Suppress("unused", "PrivatePropertyName")
|
||||||
|
class BevelLabelView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null
|
||||||
|
) : View(context, attrs) {
|
||||||
|
|
||||||
|
private val MODE_LEFT_TOP = 0
|
||||||
|
private val MODE_RIGHT_TOP = 1
|
||||||
|
private val MODE_LEFT_BOTTOM = 2
|
||||||
|
private val MODE_RIGHT_BOTTOM = 3
|
||||||
|
private val MODE_LEFT_TOP_FILL = 4
|
||||||
|
private val MODE_RIGHT_TOP_FILL = 5
|
||||||
|
private val MODE_LEFT_BOTTOM_FILL = 6
|
||||||
|
private val MODE_RIGHT_BOTTOM_FILL = 7
|
||||||
|
|
||||||
|
private var mBgColor: Int
|
||||||
|
private var mText: String
|
||||||
|
private var mTextSize: Int
|
||||||
|
private var mTextColor: Int
|
||||||
|
private var mLength: Int
|
||||||
|
private var mCorner: Int
|
||||||
|
private var mMode: Int
|
||||||
|
private var mPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||||
|
private var path: Path = Path()
|
||||||
|
private var mWidth = 0
|
||||||
|
private var mHeight: Int = 0
|
||||||
|
private var mRotate = 45 //因为默认模式是1,所以这时是45度
|
||||||
|
|
||||||
|
private var mX: Int = 0
|
||||||
|
private var mY: Int = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.BevelLabelView)
|
||||||
|
mBgColor = typedArray.getColor(
|
||||||
|
R.styleable.BevelLabelView_label_bg_color,
|
||||||
|
context.accentColor
|
||||||
|
) //默认红色
|
||||||
|
mText = typedArray.getString(R.styleable.BevelLabelView_label_text) ?: ""
|
||||||
|
mTextSize =
|
||||||
|
typedArray.getDimensionPixelOffset(
|
||||||
|
R.styleable.BevelLabelView_label_text_size,
|
||||||
|
sp2px(11)
|
||||||
|
)
|
||||||
|
mTextColor = typedArray.getColor(R.styleable.BevelLabelView_label_text_color, Color.WHITE)
|
||||||
|
mLength =
|
||||||
|
typedArray.getDimensionPixelOffset(R.styleable.BevelLabelView_label_length, dip2px(40))
|
||||||
|
mCorner = typedArray.getDimensionPixelOffset(R.styleable.BevelLabelView_label_corner, 0)
|
||||||
|
mMode = typedArray.getInt(R.styleable.BevelLabelView_label_mode, 1)
|
||||||
|
mPaint.isAntiAlias = true
|
||||||
|
typedArray.recycle()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||||
|
mWidth = MeasureSpec.getSize(widthMeasureSpec)
|
||||||
|
mHeight = mWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
mPaint.color = mBgColor
|
||||||
|
drawBackgroundText(canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun drawBackgroundText(canvas: Canvas) {
|
||||||
|
check(mWidth == mHeight) {
|
||||||
|
"width must equal to height" //标签view 是一个正方形,
|
||||||
|
}
|
||||||
|
when (mMode) {
|
||||||
|
MODE_LEFT_TOP -> {
|
||||||
|
mCorner = 0 //没有铺满的时候mCorner要归零;
|
||||||
|
leftTopMeasure()
|
||||||
|
getLeftTop()
|
||||||
|
}
|
||||||
|
MODE_RIGHT_TOP -> {
|
||||||
|
mCorner = 0
|
||||||
|
rightTopMeasure()
|
||||||
|
getRightTop()
|
||||||
|
}
|
||||||
|
MODE_LEFT_BOTTOM -> {
|
||||||
|
mCorner = 0
|
||||||
|
leftBottomMeasure()
|
||||||
|
getLeftBottom()
|
||||||
|
}
|
||||||
|
MODE_RIGHT_BOTTOM -> {
|
||||||
|
mCorner = 0
|
||||||
|
rightBottomMeasure()
|
||||||
|
getRightBottom()
|
||||||
|
}
|
||||||
|
MODE_LEFT_TOP_FILL -> {
|
||||||
|
leftTopMeasure()
|
||||||
|
getLeftTopFill()
|
||||||
|
if (mCorner != 0) {
|
||||||
|
canvas.drawPath(path, mPaint)
|
||||||
|
getLeftTop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MODE_RIGHT_TOP_FILL -> {
|
||||||
|
rightTopMeasure()
|
||||||
|
getRightTopFill()
|
||||||
|
if (mCorner != 0) {
|
||||||
|
canvas.drawPath(path, mPaint)
|
||||||
|
getRightTop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MODE_LEFT_BOTTOM_FILL -> {
|
||||||
|
leftBottomMeasure()
|
||||||
|
getLeftBottomFill()
|
||||||
|
if (mCorner != 0) {
|
||||||
|
canvas.drawPath(path, mPaint)
|
||||||
|
getLeftBottom()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MODE_RIGHT_BOTTOM_FILL -> {
|
||||||
|
rightBottomMeasure()
|
||||||
|
getRightBottomFill()
|
||||||
|
if (mCorner != 0) {
|
||||||
|
canvas.drawPath(path, mPaint)
|
||||||
|
getRightBottom()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, mPaint)
|
||||||
|
mPaint.textSize = mTextSize.toFloat()
|
||||||
|
mPaint.textAlign = Paint.Align.CENTER
|
||||||
|
mPaint.color = mTextColor
|
||||||
|
canvas.translate(mX.toFloat(), mY.toFloat())
|
||||||
|
canvas.rotate(mRotate.toFloat())
|
||||||
|
val baseLineY = (-(mPaint.descent() + mPaint.ascent())).toInt() / 2 //基线中间点的y轴计算公式
|
||||||
|
canvas.drawText(mText, 0f, baseLineY.toFloat(), mPaint)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rightBottomMeasure() {
|
||||||
|
mRotate = -45
|
||||||
|
mX = mWidth / 2 + mLength / 4
|
||||||
|
mY = mX
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun leftBottomMeasure() {
|
||||||
|
mRotate = 45
|
||||||
|
mX = mWidth / 2 - mLength / 4
|
||||||
|
mY = mHeight / 2 + mLength / 4
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rightTopMeasure() {
|
||||||
|
mRotate = 45
|
||||||
|
mX = mWidth / 2 + mLength / 4
|
||||||
|
mY = mHeight / 2 - mLength / 4
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun leftTopMeasure() {
|
||||||
|
mRotate = -45
|
||||||
|
mX = mWidth / 2 - mLength / 4
|
||||||
|
mY = mX
|
||||||
|
}
|
||||||
|
|
||||||
|
//左上角铺满
|
||||||
|
private fun getLeftTopFill() {
|
||||||
|
if (mCorner != 0) {
|
||||||
|
path.addRoundRect(
|
||||||
|
0f,
|
||||||
|
0f,
|
||||||
|
(mWidth / 2).toFloat(),
|
||||||
|
(mHeight / 2).toFloat(),
|
||||||
|
floatArrayOf(mCorner.toFloat(), mCorner.toFloat(), 0f, 0f, 0f, 0f, 0f, 0f),
|
||||||
|
Path.Direction.CW
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
path.moveTo(0f, 0f)
|
||||||
|
path.lineTo(mWidth.toFloat(), 0f)
|
||||||
|
path.lineTo(0f, mHeight.toFloat())
|
||||||
|
path.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//左上角不铺满
|
||||||
|
private fun getLeftTop() {
|
||||||
|
path.moveTo(if (mCorner != 0) mCorner.toFloat() else (mWidth - mLength).toFloat(), 0f)
|
||||||
|
path.lineTo(mWidth.toFloat(), 0f)
|
||||||
|
path.lineTo(0f, mHeight.toFloat())
|
||||||
|
path.lineTo(0f, if (mCorner != 0) mCorner.toFloat() else (mHeight - mLength).toFloat())
|
||||||
|
path.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
//左下角铺满
|
||||||
|
private fun getLeftBottomFill() {
|
||||||
|
if (mCorner != 0) {
|
||||||
|
path.addRoundRect(
|
||||||
|
0f,
|
||||||
|
(mHeight / 2).toFloat(),
|
||||||
|
(mWidth / 2).toFloat(),
|
||||||
|
mHeight.toFloat(),
|
||||||
|
floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, mCorner.toFloat(), mCorner.toFloat()),
|
||||||
|
Path.Direction.CW
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
path.moveTo(0f, 0f)
|
||||||
|
path.lineTo(mWidth.toFloat(), mHeight.toFloat())
|
||||||
|
path.lineTo(0f, mHeight.toFloat())
|
||||||
|
path.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//左下角不铺满
|
||||||
|
private fun getLeftBottom() {
|
||||||
|
path.moveTo(0f, 0f)
|
||||||
|
path.lineTo(mWidth.toFloat(), mHeight.toFloat())
|
||||||
|
path.lineTo(
|
||||||
|
if (mCorner != 0) mCorner.toFloat() else (mWidth - mLength).toFloat(),
|
||||||
|
mHeight.toFloat()
|
||||||
|
)
|
||||||
|
path.lineTo(0f, if (mCorner != 0) (mHeight - mCorner).toFloat() else mLength.toFloat())
|
||||||
|
path.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
//右上角铺满
|
||||||
|
private fun getRightTopFill() {
|
||||||
|
if (mCorner != 0) {
|
||||||
|
path.addRoundRect(
|
||||||
|
(mWidth / 2).toFloat(),
|
||||||
|
0f,
|
||||||
|
mWidth.toFloat(),
|
||||||
|
(mHeight / 2).toFloat(),
|
||||||
|
floatArrayOf(0f, 0f, mCorner.toFloat(), mCorner.toFloat(), 0f, 0f, 0f, 0f),
|
||||||
|
Path.Direction.CW
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
path.moveTo(0f, 0f)
|
||||||
|
path.lineTo(mWidth.toFloat(), 0f)
|
||||||
|
path.lineTo(mWidth.toFloat(), mHeight.toFloat())
|
||||||
|
path.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//右上角不铺满
|
||||||
|
private fun getRightTop() {
|
||||||
|
path.moveTo(0f, 0f)
|
||||||
|
path.lineTo(if (mCorner != 0) (mWidth - mCorner).toFloat() else mLength.toFloat(), 0f)
|
||||||
|
path.lineTo(
|
||||||
|
mWidth.toFloat(),
|
||||||
|
if (mCorner != 0) mCorner.toFloat() else (mHeight - mLength).toFloat()
|
||||||
|
)
|
||||||
|
path.lineTo(mWidth.toFloat(), mHeight.toFloat())
|
||||||
|
path.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
//右下角铺满
|
||||||
|
private fun getRightBottomFill() {
|
||||||
|
if (mCorner != 0) {
|
||||||
|
path.addRoundRect(
|
||||||
|
(mWidth / 2).toFloat(),
|
||||||
|
(mHeight / 2).toFloat(),
|
||||||
|
mWidth.toFloat(),
|
||||||
|
mHeight.toFloat(),
|
||||||
|
floatArrayOf(0f, 0f, 0f, 0f, mCorner.toFloat(), mCorner.toFloat(), 0f, 0f),
|
||||||
|
Path.Direction.CW
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
path.moveTo(mWidth.toFloat(), 0f)
|
||||||
|
path.lineTo(mWidth.toFloat(), mHeight.toFloat())
|
||||||
|
path.lineTo(0f, mHeight.toFloat())
|
||||||
|
path.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//右下角不铺满
|
||||||
|
private fun getRightBottom() {
|
||||||
|
path.moveTo(mWidth.toFloat(), 0f)
|
||||||
|
path.lineTo(
|
||||||
|
mWidth.toFloat(),
|
||||||
|
if (mCorner != 0) (mHeight - mCorner).toFloat() else mLength.toFloat()
|
||||||
|
)
|
||||||
|
path.lineTo(
|
||||||
|
if (mCorner != 0) (mWidth - mCorner).toFloat() else mLength.toFloat(),
|
||||||
|
mHeight.toFloat()
|
||||||
|
)
|
||||||
|
path.lineTo(0f, mHeight.toFloat())
|
||||||
|
path.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sp 转换大小
|
||||||
|
*/
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
|
private fun sp2px(sp: Int): Int {
|
||||||
|
return TypedValue.applyDimension(
|
||||||
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
sp.toFloat(),
|
||||||
|
resources.displayMetrics
|
||||||
|
)
|
||||||
|
.toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dip 转换大小
|
||||||
|
*/
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
|
private fun dip2px(dip: Int): Int {
|
||||||
|
return TypedValue.applyDimension(
|
||||||
|
TypedValue.COMPLEX_UNIT_DIP,
|
||||||
|
dip.toFloat(),
|
||||||
|
resources.displayMetrics
|
||||||
|
)
|
||||||
|
.toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="8dp">
|
android:padding="8dp">
|
||||||
|
|
||||||
<io.legado.app.lib.theme.view.ThemeRadioButton
|
<io.legado.app.lib.theme.view.ThemeRadioButton
|
||||||
android:id="@+id/cb_name"
|
android:id="@+id/cb_name"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
tools:ignore="RtlSymmetry" />
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@id/iv_edit"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@+id/iv_edit"
|
android:id="@+id/iv_edit"
|
||||||
@@ -23,20 +25,34 @@
|
|||||||
android:contentDescription="@string/edit"
|
android:contentDescription="@string/edit"
|
||||||
android:padding="6dp"
|
android:padding="6dp"
|
||||||
android:src="@drawable/ic_edit"
|
android:src="@drawable/ic_edit"
|
||||||
android:tint="@color/primaryText" />
|
android:tint="@color/primaryText"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/iv_menu_delete"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@+id/iv_menu_delete"
|
android:id="@+id/iv_menu_delete"
|
||||||
android:layout_width="36dp"
|
android:layout_width="36dp"
|
||||||
android:layout_height="36dp"
|
android:layout_height="36dp"
|
||||||
android:padding="6dp"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="6dp"
|
||||||
android:src="@drawable/ic_clear_all"
|
android:src="@drawable/ic_clear_all"
|
||||||
android:tint="@color/primaryText"
|
android:tint="@color/primaryText"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="1.0"
|
||||||
tools:ignore="RtlHardcoded" />
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
<View
|
<io.legado.app.ui.widget.text.BevelLabelView
|
||||||
android:layout_width="12dp"
|
android:id="@+id/label_sys"
|
||||||
android:layout_height="36dp" />
|
android:layout_width="36dp"
|
||||||
|
android:layout_height="36dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:label_mode="right_top"
|
||||||
|
app:label_length="24dp"
|
||||||
|
app:label_text="SYS"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -213,4 +213,32 @@
|
|||||||
<declare-styleable name="Preference">
|
<declare-styleable name="Preference">
|
||||||
<attr name="isBottomBackground" />
|
<attr name="isBottomBackground" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
<!--斜角标签-->
|
||||||
|
<declare-styleable name="BevelLabelView">
|
||||||
|
<!--背景颜色-->
|
||||||
|
<attr name="label_bg_color" format="color|reference" />
|
||||||
|
<!--文字-->
|
||||||
|
<attr name="label_text" format="string" />
|
||||||
|
<!-- 文字颜色-->
|
||||||
|
<attr name="label_text_color" format="color|reference" />
|
||||||
|
<!--文字大小-->
|
||||||
|
<attr name="label_text_size" format="dimension" />
|
||||||
|
|
||||||
|
<attr name="label_length" format="dimension" />
|
||||||
|
<!-- 圆角-->
|
||||||
|
<attr name="label_corner" format="dimension" />
|
||||||
|
|
||||||
|
<attr name="label_mode">
|
||||||
|
<!-- fill是沾满整个,-->
|
||||||
|
<enum name="left_top" value="0" />
|
||||||
|
<enum name="right_top" value="1" />
|
||||||
|
<enum name="left_bottom" value="2" />
|
||||||
|
<enum name="right_bottom" value="3" />
|
||||||
|
<enum name="left_top_fill" value="4" />
|
||||||
|
<enum name="right_top_fill" value="5" />
|
||||||
|
<enum name="left_bottom_fill" value="6" />
|
||||||
|
<enum name="right_bottom_fill" value="7" />
|
||||||
|
</attr>
|
||||||
|
</declare-styleable>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user