| | |
| | | package com.example.expand_button |
| | | |
| | | class ExpandButton { |
| | | import android.animation.ValueAnimator |
| | | import android.content.Context |
| | | import android.graphics.Canvas |
| | | import android.graphics.drawable.Drawable |
| | | import android.text.Spannable |
| | | import android.text.SpannableStringBuilder |
| | | import android.text.style.ClickableSpan |
| | | import android.util.AttributeSet |
| | | import android.view.Gravity |
| | | import android.view.MotionEvent |
| | | import android.view.View |
| | | import androidx.appcompat.widget.AppCompatTextView |
| | | import androidx.core.content.ContextCompat |
| | | |
| | | /** |
| | | * 可展开的按钮控件 |
| | | * 初始状态显示单个字符,点击后展开显示完整文字 |
| | | * 展开后的每个字符都可以单独点击 |
| | | */ |
| | | class ExpandButton @JvmOverloads constructor( |
| | | context: Context, |
| | | attrs: AttributeSet? = null, |
| | | defStyleAttr: Int = 0 |
| | | ) : AppCompatTextView(context, attrs, defStyleAttr) { |
| | | |
| | | // 修改属性 |
| | | private data class LegendItem( |
| | | val selectedIcon: Drawable, |
| | | val unselectedIcon: Drawable, |
| | | val description: String, |
| | | var isSelected: Boolean = true |
| | | ) |
| | | |
| | | private var legendItems: List<LegendItem> = listOf() |
| | | private var itemSpacing: Float = context.resources.displayMetrics.density * 16 // 图例项之间的水平间距 |
| | | private var iconSize: Int = (24 * context.resources.displayMetrics.density).toInt() // 图标大小 |
| | | private var iconTextSpacing: Float = context.resources.displayMetrics.density * 4 // 图标和文字之间的垂直间距 |
| | | |
| | | // 展开时显示的完整文字 |
| | | private var expandedText: String = "标注点: 当前位置\n区域: 配送范围" |
| | | // 收起时显示的单个字符 |
| | | private var collapsedText: String = "图例" |
| | | // 当前是否处于展开状态 |
| | | private var isExpanded: Boolean = false |
| | | // 动画持续时间,默认300毫秒 |
| | | private var animationDuration: Long = 300 |
| | | // 字符点击事件监听器 |
| | | private var onCharClickListener: ((Char, Int) -> Unit)? = null |
| | | // 字间距,默认为2dp |
| | | private var customLetterSpacing: Float = context.resources.displayMetrics.density * 2 |
| | | |
| | | // 三角形图标 |
| | | private val triangleDrawable: Drawable = ContextCompat.getDrawable( |
| | | context, |
| | | R.drawable.ic_triangle |
| | | )!!.mutate() |
| | | |
| | | // 图标旋转角度 |
| | | private var triangleRotation = 0f |
| | | |
| | | // 三角形图标与文字的间距,默认为8dp |
| | | private var triangleMargin: Float = 3 * context.resources.displayMetrics.density |
| | | |
| | | // 添加新属性 |
| | | private var textLines: List<String> = listOf() |
| | | |
| | | // 添加点击回调接口 |
| | | interface OnLegendItemClickListener { |
| | | fun onLegendItemClick(position: Int, isSelected: Boolean) |
| | | } |
| | | |
| | | private var legendItemClickListener: OnLegendItemClickListener? = null |
| | | |
| | | // 修改图例项的总高度计算 |
| | | private val legendItemHeight: Int |
| | | get() = iconSize + iconTextSpacing.toInt() + paint.textSize.toInt() + paint.descent().toInt() - paint.ascent().toInt() |
| | | |
| | | // 添加展开后的字体大小属性 |
| | | private var expandedTextSize: Float = textSize |
| | | |
| | | // 添加一个变量保存默认字体大小 |
| | | private var defaultTextSize: Float = 0f |
| | | |
| | | // 添加一个属性定义三角形图标的点击区域扩展范围 |
| | | private val triangleClickPadding: Float = 15f * context.resources.displayMetrics.density // 20dp |
| | | |
| | | // 添加一个标识符,用于区分不同的 ExpandButton 实例 |
| | | private var buttonId: String = "default" |
| | | |
| | | companion object { |
| | | private const val PREFS_NAME = "expand_button_prefs" |
| | | private const val KEY_LEGEND_STATES = "legend_states" |
| | | } |
| | | |
| | | init { |
| | | // 保存 XML 中设置的默认字体大小 |
| | | defaultTextSize = textSize |
| | | |
| | | // 读取自定义属性 |
| | | context.theme.obtainStyledAttributes( |
| | | attrs, |
| | | R.styleable.ExpandButton, |
| | | defStyleAttr, |
| | | 0 |
| | | ).apply { |
| | | try { |
| | | customLetterSpacing = getDimension(R.styleable.ExpandButton_letterSpacing, customLetterSpacing) |
| | | expandedText = getString(R.styleable.ExpandButton_expandedText) ?: "标注点: 当前位置\n区域: 配送范围" |
| | | collapsedText = getString(R.styleable.ExpandButton_collapsedText) ?: "图例" |
| | | animationDuration = getInteger(R.styleable.ExpandButton_animDuration, 300).toLong() |
| | | triangleMargin = getDimension(R.styleable.ExpandButton_triangleMargin, triangleMargin) |
| | | itemSpacing = getDimension(R.styleable.ExpandButton_itemSpacing, itemSpacing) |
| | | iconSize = getDimension(R.styleable.ExpandButton_iconSize, iconSize.toFloat()).toInt() |
| | | iconTextSpacing = getDimension(R.styleable.ExpandButton_iconTextSpacing, iconTextSpacing) |
| | | expandedTextSize = getDimension(R.styleable.ExpandButton_expandedTextSize, defaultTextSize) |
| | | } finally { |
| | | recycle() |
| | | } |
| | | } |
| | | |
| | | // 设置初始文本和宽度 |
| | | if (collapsedText.isNotEmpty()) { |
| | | text = collapsedText |
| | | post { |
| | | // 确保初始宽度为收起状态的宽度 |
| | | layoutParams = layoutParams.apply { |
| | | width = paint.measureText(collapsedText).toInt() + paddingLeft + paddingRight |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 修改触摸事件处理 |
| | | setOnTouchListener(null) // 移除原有的触摸监听器 |
| | | |
| | | // 移除原有的点击监听器 |
| | | setOnClickListener(null) |
| | | |
| | | // 设置左边距,为图标留出空间 |
| | | compoundDrawablePadding = triangleMargin.toInt() |
| | | setPadding( |
| | | (16 * context.resources.displayMetrics.density + triangleMargin).toInt(), // 左边距增加,为图标留空间 |
| | | paddingTop, |
| | | paddingRight, |
| | | paddingBottom |
| | | ) |
| | | |
| | | // 设置单行显示,防止高度变化 |
| | | maxLines = if (isExpanded) Int.MAX_VALUE else 1 |
| | | isSingleLine = !isExpanded |
| | | |
| | | // 设置文字垂直居中 |
| | | gravity = Gravity.CENTER_VERTICAL |
| | | |
| | | // 设置默认的内边距 |
| | | val defaultPadding = (8 * context.resources.displayMetrics.density).toInt() |
| | | setPadding( |
| | | (16 * context.resources.displayMetrics.density + triangleMargin).toInt(), // 左边距增加,为图标留空间 |
| | | defaultPadding, // 上边距 |
| | | defaultPadding, // 右边距 |
| | | defaultPadding // 下边距 |
| | | ) |
| | | } |
| | | |
| | | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { |
| | | super.onMeasure(widthMeasureSpec, heightMeasureSpec) |
| | | |
| | | if (isExpanded) { |
| | | // 展开状态下的高度计算 |
| | | val desiredHeight = legendItemHeight + paddingTop + paddingBottom |
| | | setMeasuredDimension(measuredWidth, desiredHeight) |
| | | } |
| | | } |
| | | |
| | | override fun onDraw(canvas: Canvas) { |
| | | // 绘制展开/收起图标 |
| | | drawTriangle(canvas) |
| | | |
| | | if (!isExpanded) { |
| | | // 收起状态使用默认字体大小 |
| | | paint.textSize = defaultTextSize |
| | | super.onDraw(canvas) |
| | | return |
| | | } |
| | | |
| | | // 展开状态使用展开后的字体大小 |
| | | paint.textSize = expandedTextSize |
| | | |
| | | // 计算所有图例项中最宽的宽度 |
| | | val maxWidth = legendItems.maxOf { item -> |
| | | maxOf(paint.measureText(item.description), iconSize.toFloat()) |
| | | } |
| | | |
| | | // 计算总宽度(添加首尾的边距) |
| | | val totalWidth = legendItems.size * maxWidth + |
| | | (legendItems.size + 1) * itemSpacing // 修改这里,添加一个额外的间距 |
| | | |
| | | // 计算起始x坐标,使整体水平居中 |
| | | var x = (width - totalWidth) / 2 + itemSpacing // 添加起始边距 |
| | | |
| | | // 计算垂直居中的y坐标,考虑上下边距 |
| | | val centerY = height / 2f |
| | | |
| | | legendItems.forEachIndexed { index, item -> |
| | | // 计算当前图例项的起始位置(移除index > 0的判断) |
| | | val itemStartX = x |
| | | |
| | | // 计算图标的水平位置(居中于图例项) |
| | | val iconLeft = itemStartX + (maxWidth - iconSize) / 2 |
| | | |
| | | // 计算文字的位置 |
| | | val textWidth = paint.measureText(item.description) |
| | | val textX = itemStartX + (maxWidth - textWidth) / 2 |
| | | |
| | | // 绘制图标,根据选中状态选择不同的图标 |
| | | val iconTop = paddingTop + (height - legendItemHeight) / 2 |
| | | val currentIcon = if (item.isSelected) item.selectedIcon else item.unselectedIcon |
| | | currentIcon.setBounds( |
| | | iconLeft.toInt(), |
| | | iconTop.toInt(), |
| | | (iconLeft + iconSize).toInt(), |
| | | (iconTop + iconSize).toInt() |
| | | ) |
| | | currentIcon.draw(canvas) |
| | | |
| | | // 绘制文字,根据选中状态使用不同的颜色 |
| | | paint.color = if (item.isSelected) |
| | | currentTextColor |
| | | else |
| | | 0xFF999999.toInt() // 灰色 |
| | | val textY = iconTop + iconSize + iconTextSpacing - paint.ascent() |
| | | canvas.drawText(item.description, textX, textY, paint) |
| | | |
| | | // 更新下一个图例项的起始位置 |
| | | x = itemStartX + maxWidth + itemSpacing |
| | | } |
| | | |
| | | // 恢复画笔颜色 |
| | | paint.color = currentTextColor |
| | | } |
| | | |
| | | // 将原来的onDraw中的三角形绘制逻辑提取出来 |
| | | private fun drawTriangle(canvas: Canvas) { |
| | | canvas.save() |
| | | |
| | | val iconSize = triangleDrawable.intrinsicWidth |
| | | val iconLeft = paddingLeft - iconSize - compoundDrawablePadding |
| | | val iconTop = (height - iconSize) / 2 |
| | | |
| | | triangleDrawable.setBounds( |
| | | iconLeft, |
| | | iconTop, |
| | | iconLeft + iconSize, |
| | | iconTop + iconSize |
| | | ) |
| | | |
| | | canvas.rotate( |
| | | triangleRotation, |
| | | (iconLeft + iconSize / 2).toFloat(), |
| | | (iconTop + iconSize / 2).toFloat() |
| | | ) |
| | | |
| | | triangleDrawable.draw(canvas) |
| | | |
| | | canvas.restore() |
| | | } |
| | | |
| | | /** |
| | | * 设置字间距 |
| | | * @param spacing 间距值(像素) |
| | | */ |
| | | fun setCustomLetterSpacing(spacing: Float) { |
| | | this.customLetterSpacing = spacing |
| | | if (isExpanded) { |
| | | setExpandedClickableText() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置展开和收起时显示的文字 |
| | | * @param expanded 展开时显示的完整文字 |
| | | * @param collapsed 收起时显示的单个字符 |
| | | */ |
| | | fun setExpandText(expanded: String, collapsed: String) { |
| | | this.expandedText = expanded |
| | | this.collapsedText = collapsed |
| | | text = collapsedText |
| | | } |
| | | |
| | | /** |
| | | * 设置单个字符点击监听器 |
| | | * @param listener 点击回调,参数为被点击的字符和位置 |
| | | * char: 被点击的字符 |
| | | * position: 字符在文本中的位置(从0开始) |
| | | */ |
| | | fun setOnCharClickListener(listener: (char: Char, position: Int) -> Unit) { |
| | | this.onCharClickListener = listener |
| | | } |
| | | |
| | | /** |
| | | * 设置展开/收起动画的持续时间 |
| | | * @param duration 动画持续时间(毫秒) |
| | | */ |
| | | fun setAnimationDuration(duration: Long) { |
| | | this.animationDuration = duration |
| | | } |
| | | |
| | | /** |
| | | * 切换展开/收起状态 |
| | | */ |
| | | private fun toggleExpand() { |
| | | isExpanded = !isExpanded |
| | | |
| | | // 计算收起和展开状态的宽度 |
| | | val collapsedWidth = run { |
| | | paint.textSize = defaultTextSize |
| | | val width = paint.measureText(collapsedText).toInt() + paddingLeft + paddingRight |
| | | paint.textSize = if (isExpanded) expandedTextSize else defaultTextSize |
| | | width |
| | | } |
| | | |
| | | val expandedWidth = calculateExpandedWidth() |
| | | |
| | | // 创建宽度动画 |
| | | ValueAnimator.ofInt( |
| | | if (isExpanded) collapsedWidth else expandedWidth, |
| | | if (isExpanded) expandedWidth else collapsedWidth |
| | | ).apply { |
| | | duration = animationDuration |
| | | addUpdateListener { animator -> |
| | | layoutParams = layoutParams.apply { |
| | | width = animator.animatedValue as Int |
| | | } |
| | | requestLayout() |
| | | } |
| | | start() |
| | | } |
| | | |
| | | // 创建图标旋转动画 |
| | | ValueAnimator.ofFloat( |
| | | if (isExpanded) 0f else 180f, |
| | | if (isExpanded) 180f else 0f |
| | | ).apply { |
| | | duration = animationDuration |
| | | addUpdateListener { animator -> |
| | | triangleRotation = animator.animatedValue as Float |
| | | invalidate() |
| | | } |
| | | start() |
| | | } |
| | | |
| | | // 更新文本和字体大小 |
| | | if (isExpanded) { |
| | | paint.textSize = expandedTextSize |
| | | } else { |
| | | text = collapsedText |
| | | paint.textSize = defaultTextSize |
| | | setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, defaultTextSize) |
| | | } |
| | | |
| | | invalidate() |
| | | } |
| | | |
| | | /** |
| | | * 计算展开后的总宽度 |
| | | */ |
| | | private fun calculateExpandedWidth(): Int { |
| | | // 临时保存当前字体大小 |
| | | val currentTextSize = paint.textSize |
| | | // 设置为展开状态的字体大小 |
| | | paint.textSize = expandedTextSize |
| | | |
| | | try { |
| | | // 计算所有图例项中最宽的宽度 |
| | | val maxWidth = legendItems.maxOf { item -> |
| | | maxOf(paint.measureText(item.description), iconSize.toFloat()) |
| | | } |
| | | |
| | | // 计算总宽度 = 所有图例项的宽度 + 所有间距(包括首尾) + 左右内边距 |
| | | return (legendItems.size * maxWidth + |
| | | (legendItems.size + 1) * itemSpacing + |
| | | paddingLeft + paddingRight).toInt() |
| | | } finally { |
| | | // 恢复原来的字体大小 |
| | | paint.textSize = currentTextSize |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置展开后的可点击文本 |
| | | */ |
| | | private fun setExpandedClickableText() { |
| | | val builder = SpannableStringBuilder() |
| | | |
| | | // 计算所有图例项中最宽的宽度 |
| | | val maxWidth = legendItems.maxOf { item -> |
| | | maxOf(paint.measureText(item.description), iconSize.toFloat()) |
| | | } |
| | | |
| | | // 计算总宽度 |
| | | val totalWidth = legendItems.size * maxWidth + |
| | | (legendItems.size - 1) * itemSpacing |
| | | |
| | | // 计算整体水平居中需要的起始空格 |
| | | val startPadding = ((width - totalWidth) / 2 / paint.measureText(" ")).toInt() |
| | | if (startPadding > 0) { |
| | | builder.append(" ".repeat(startPadding)) |
| | | } |
| | | |
| | | // 添加垂直空间,为图标预留位置 |
| | | val verticalSpaces = ((iconSize + iconTextSpacing) / paint.textSize).toInt() |
| | | builder.append("\n".repeat(verticalSpaces)) |
| | | |
| | | legendItems.forEachIndexed { index, item -> |
| | | if (index > 0) { |
| | | // 在图例项之间添加水平间距 |
| | | builder.append(" ".repeat((itemSpacing / paint.measureText(" ")).toInt())) |
| | | } |
| | | |
| | | // 计算水平居中所需的空格数 |
| | | val textWidth = paint.measureText(item.description) |
| | | val paddingSpaces = ((maxWidth - textWidth) / 2 / paint.measureText(" ")).toInt() |
| | | |
| | | // 添加左侧空格实现居中 |
| | | if (paddingSpaces > 0) { |
| | | builder.append(" ".repeat(paddingSpaces)) |
| | | } |
| | | |
| | | // 添加描述文本 |
| | | val startPosition = builder.length |
| | | builder.append(item.description) |
| | | |
| | | // 添加右侧空格以确保宽度一致 |
| | | val remainingSpaces = ((maxWidth - textWidth) / paint.measureText(" ")).toInt() - paddingSpaces |
| | | if (remainingSpaces > 0) { |
| | | builder.append(" ".repeat(remainingSpaces)) |
| | | } |
| | | |
| | | // 为文字设置点击事件 |
| | | val clickableSpan = object : ClickableSpan() { |
| | | override fun onClick(view: View) { |
| | | onCharClickListener?.invoke(item.description[0], index) |
| | | } |
| | | |
| | | override fun updateDrawState(ds: android.text.TextPaint) { |
| | | super.updateDrawState(ds) |
| | | ds.isUnderlineText = false |
| | | ds.color = currentTextColor |
| | | } |
| | | } |
| | | |
| | | builder.setSpan( |
| | | clickableSpan, |
| | | startPosition, |
| | | startPosition + item.description.length, |
| | | Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
| | | ) |
| | | } |
| | | |
| | | // 设置文本对齐方式为居中 |
| | | gravity = Gravity.CENTER |
| | | |
| | | text = builder |
| | | movementMethod = android.text.method.LinkMovementMethod.getInstance() |
| | | } |
| | | |
| | | /** |
| | | * 判断点击是否在三角形图标区域内 |
| | | */ |
| | | private fun isClickOnTriangle(x: Float): Boolean { |
| | | val iconSize = triangleDrawable.intrinsicWidth |
| | | val iconLeft = paddingLeft - iconSize - compoundDrawablePadding |
| | | |
| | | // 扩大点击区域:左右各增加 triangleClickPadding |
| | | return x <= (paddingLeft + triangleClickPadding) && |
| | | x >= (iconLeft - triangleClickPadding) |
| | | } |
| | | |
| | | /** |
| | | * 设置三角形图标与文字的间距 |
| | | * @param margin 间距值(像素) |
| | | */ |
| | | fun setTriangleMargin(margin: Float) { |
| | | this.triangleMargin = margin |
| | | compoundDrawablePadding = margin.toInt() |
| | | setPadding( |
| | | (16 * context.resources.displayMetrics.density + margin).toInt(), |
| | | paddingTop, |
| | | paddingRight, |
| | | paddingBottom |
| | | ) |
| | | } |
| | | |
| | | /** |
| | | * 设置按钮的唯一标识符 |
| | | * @param id 标识符 |
| | | */ |
| | | fun setButtonId(id: String) { |
| | | this.buttonId = id |
| | | // 加载保存的状态 |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 设置图例内容 |
| | | */ |
| | | @JvmName("setLegendsList") |
| | | fun setLegends(items: List<Quadruple<Drawable, Drawable, String, Boolean>>) { |
| | | legendItems = items.map { (selectedIcon, unselectedIcon, description, isSelected) -> |
| | | selectedIcon.setBounds(0, 0, iconSize, iconSize) |
| | | unselectedIcon.setBounds(0, 0, iconSize, iconSize) |
| | | LegendItem(selectedIcon, unselectedIcon, description, isSelected) |
| | | } |
| | | |
| | | if (!isExpanded) { |
| | | text = collapsedText |
| | | } else { |
| | | invalidate() |
| | | } |
| | | requestLayout() |
| | | } |
| | | |
| | | // 添加一个 Java 友好的方法 |
| | | @JvmName("setLegendsArray") |
| | | fun setLegends(vararg items: Quadruple<Drawable, Drawable, String, Boolean>) { |
| | | setLegends(items.toList()) |
| | | } |
| | | |
| | | // 添加一个数据类来表示四元组 |
| | | data class Quadruple<A, B, C, D>( |
| | | val first: A, |
| | | val second: B, |
| | | val third: C, |
| | | val fourth: D |
| | | ) |
| | | |
| | | // 添加一个便捷的扩展函数来创建 Quadruple |
| | | fun <A, B, C, D> quadrupleOf(first: A, second: B, third: C, fourth: D): Quadruple<A, B, C, D> { |
| | | return Quadruple(first, second, third, fourth) |
| | | } |
| | | |
| | | /** |
| | | * 添加设置监听器的方法 |
| | | */ |
| | | fun setOnLegendItemClickListener(listener: OnLegendItemClickListener) { |
| | | legendItemClickListener = listener |
| | | } |
| | | |
| | | /** |
| | | * 处理触摸事件 |
| | | */ |
| | | override fun onTouchEvent(event: MotionEvent): Boolean { |
| | | when (event.action) { |
| | | MotionEvent.ACTION_DOWN -> { |
| | | // 检查点击是否在三角形图标区域内 |
| | | if (isClickOnTriangle(event.x)) { |
| | | toggleExpand() |
| | | return true |
| | | } |
| | | |
| | | // 如果是展开状态,检查是否点击了图例项 |
| | | if (isExpanded) { |
| | | val clickedIndex = getClickedItemIndex(event.x, event.y) |
| | | if (clickedIndex != -1) { |
| | | toggleItemSelection(clickedIndex) |
| | | return true |
| | | } |
| | | } else if (!isExpanded && event.x > paddingLeft) { |
| | | // 在收起状态下,点击非三角形区域也展开 |
| | | toggleExpand() |
| | | return true |
| | | } |
| | | } |
| | | } |
| | | return super.onTouchEvent(event) |
| | | } |
| | | |
| | | /** |
| | | * 获取点击位置对应的图例项索引 |
| | | */ |
| | | private fun getClickedItemIndex(x: Float, y: Float): Int { |
| | | if (!isExpanded) return -1 |
| | | |
| | | val maxWidth = legendItems.maxOf { item -> |
| | | maxOf(paint.measureText(item.description), iconSize.toFloat()) |
| | | } |
| | | |
| | | val totalWidth = legendItems.size * maxWidth + |
| | | (legendItems.size - 1) * itemSpacing |
| | | |
| | | val startX = (width - totalWidth) / 2 |
| | | val iconTop = paddingTop + (height - legendItemHeight) / 2 |
| | | val iconBottom = iconTop + legendItemHeight |
| | | |
| | | // 检查垂直方向是否在图例项范围内 |
| | | if (y < iconTop || y > iconBottom) return -1 |
| | | |
| | | // 检查水平方向点击的是哪个图例项 |
| | | legendItems.forEachIndexed { index, _ -> |
| | | val itemStartX = startX + index * (maxWidth + itemSpacing) |
| | | val itemEndX = itemStartX + maxWidth |
| | | if (x >= itemStartX && x <= itemEndX) { |
| | | return index |
| | | } |
| | | } |
| | | return -1 |
| | | } |
| | | |
| | | /** |
| | | * 切换图例项的选中状态 |
| | | */ |
| | | private fun toggleItemSelection(index: Int) { |
| | | if (index < 0 || index >= legendItems.size) return |
| | | |
| | | legendItems[index].isSelected = !legendItems[index].isSelected |
| | | legendItemClickListener?.onLegendItemClick( |
| | | index, |
| | | legendItems[index].isSelected |
| | | ) |
| | | |
| | | invalidate() |
| | | } |
| | | |
| | | /** |
| | | * 设置展开后的字体大小 |
| | | * @param size 字体大小(像素) |
| | | */ |
| | | fun setExpandedTextSize(size: Float) { |
| | | this.expandedTextSize = size |
| | | if (isExpanded) { |
| | | invalidate() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置展开后的字体大小(SP) |
| | | * @param sp 字体大小(SP) |
| | | */ |
| | | fun setExpandedTextSizeSp(sp: Float) { |
| | | setExpandedTextSize(sp * context.resources.displayMetrics.scaledDensity) |
| | | } |
| | | } |