Sergei Buvaka Asked:2020-07-31 02:13:25 +0800 CST2020-07-31 02:13:25 +0800 CST 2020-07-31 02:13:25 +0800 CST XML 标记中的元素排列 772 有这样的布局: 有3个TextView: “我的分数” “*1801” “已安装” 我需要“*1801”和“已安装”始终以全尺寸显示,但如果我们有一个较长的“我的帐户”并且它不适合屏幕,那么它就会被应用elipsize。同时,非常重要的是“我的账户”和“*1801”要紧挨着,就好像它是一个一样TextView。 问题是我无法弄清楚如何正确设置元素的标记。如果有人可以提供建议,我将不胜感激。 android 2 个回答 Voted Sergei Buvaka 2020-07-31T17:42:01+08:002020-07-31T17:42:01+08:00 我不得不写这个视图: class SeparateRestrictTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : ViewGroup(context, attrs, defStyleAttr) { private var inited: Boolean = false private var showSeparatedRestrictionMode: Boolean = false @get:Px private val fadeOffset: Int by lazyUnsafe { context.dpToPx(FADE_OFFSET) } init { inflate(context, R.layout.view_separate_restrict_text, this) context.obtainStyledAttributes(attrs, R.styleable.SeparateRestrictTextView).apply { if (hasValue(R.styleable.SeparateRestrictTextView_srtv_textAppearance)) { fadedText.setTextAppearance(getResourceId(R.styleable.SeparateRestrictTextView_srtv_textAppearance, View.NO_ID)) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { restrictionText.setTextAppearance(getResourceId(R.styleable.SeparateRestrictTextView_srtv_textAppearance, View.NO_ID)) } else { restrictionText.setTextAppearance(context, getResourceId(R.styleable.SeparateRestrictTextView_srtv_textAppearance, View.NO_ID)) } } recycle() } inited = true } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { measureChildWithPadding(restrictionText, widthMeasureSpec, heightMeasureSpec) measureChildWithPadding(fadedText, widthMeasureSpec, heightMeasureSpec) val desiredWidth = if (fadedText.inEllipsizedMode) { showSeparatedRestrictionMode = true measureChildWithPadding(fadedText, widthMeasureSpec, heightMeasureSpec, fadeOffset + restrictionText.measuredWidth) fadedText.measuredWidth + fadeOffset + restrictionText.measuredWidth } else { showSeparatedRestrictionMode = false fadedText.measuredWidth } val desiredHeight = max(fadedText.measuredHeight, restrictionText.measuredHeight) setMeasuredDimension( measureDimension(desiredWidth, widthMeasureSpec), measureDimension(desiredHeight, heightMeasureSpec) ) } override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { if (showSeparatedRestrictionMode) { val restrictionTop = (bottom - top - restrictionText.measuredHeight) / 2 restrictionText.layout( right - left - restrictionText.measuredWidth, restrictionTop, right - left, restrictionTop + restrictionText.measuredHeight ) } else { restrictionText.layout(0, 0, 0, 0) } val fadedTextTop = (bottom - top - fadedText.measuredHeight) / 2 val fadedTextRightRight = if (showSeparatedRestrictionMode) { right - left - restrictionText.measuredWidth - fadeOffset } else { right - left } fadedText.layout( 0, fadedTextTop, fadedTextRightRight, fadedTextTop + fadedText.measuredHeight ) } fun setContent(faded: String?, restriction: String?, separator: String) { if (faded.isNullOrEmpty() && restriction.isNullOrEmpty()) { isGone = true return } isVisible = true fadedText.text = listOfNotNull(faded?.takeIf { it.isNotEmpty() }, restriction).joinToString(separator) restrictionText.text = restriction } override fun addView(child: View?) { if (!inited) { super.addView(child) } } private fun measureDimension(desiredSize: Int, measureSpec: Int): Int { val specMode = MeasureSpec.getMode(measureSpec) val specSize = MeasureSpec.getSize(measureSpec) return when (specMode) { MeasureSpec.UNSPECIFIED -> desiredSize MeasureSpec.AT_MOST -> min(desiredSize, specSize) else -> specSize } } private fun measureChildWithPadding(child: View, parentWidthMeasureSpec: Int, parentHeightMeasureSpec: Int, rightPadding: Int = 0) { val lp = child.layoutParams val childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, rightPadding, lp.width) val childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, 0, lp.height) child.measure(childWidthMeasureSpec, childHeightMeasureSpec) } private companion object { @Dp const val FADE_OFFSET = 6f } } XML 标记: <?xml version="1.0" encoding="utf-8"?> <merge 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:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/fadedText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" /> <TextView android:id="@+id/restrictionText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:includeFontPadding="false" android:maxLines="1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </merge> 这是在 attrs 中: <declare-styleable name="SeparateRestrictTextView"> <attr name="srtv_textAppearance" format="reference" /> </declare-styleable> Best Answer Alexander Chernin 2020-07-31T19:47:48+08:002020-07-31T19:47:48+08:00 如果是这样(没有间距、填充和合并): <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:text="VISA" android:textAlignment="center" /> <TextView android:layout_width="0sp" android:layout_height="match_parent" android:layout_weight="1" android:ellipsize="end" android:maxLines="1" android:text="Мой счет" /> <EditText android:layout_width="0sp" android:layout_height="match_parent" android:layout_weight="5" android:text="*1801" /> <Button android:layout_width="wrap_content" android:layout_height="match_parent" android:text="Установлен"> Установлен </Button> </LinearLayout>
我不得不写这个视图:
XML 标记:
这是在 attrs 中:
如果是这样(没有间距、填充和合并):