叠加层中带有 wrap_content 的 TextView 未扩展到完整内容宽度
TextView with wrap_content in overlay not extending to full content width
在我的应用程序中,我有一个带有 TextView 的叠加层,它具有动态文本大小和内容,可以使用触摸进行移动。目标是使叠加层与文本大小相同。使用 WRAP_CONTENT 作为叠加层,不会将包含文本的 LinearLayout 扩展到文本的全宽。
该示例加载与 Activity 的内容视图相同的布局和叠加层。
使用 MATCH_PARENT,完整的 TextView 可以显示在 Overlay 中,但这会使覆盖无法用于触摸事件,因为可以触摸整个宽度。如果没有 LinearLayout,它也不会扩展到全宽。
对于小于此最大宽度的宽度,wrap_content 按预期工作,对于高度 wrap_content,在向文本添加更多行时按预期工作于整个设备高度。
如何在不使 TextView 或 LinearLayout 比文本宽的情况下将 TextView 扩展到文本的整个宽度?
示例如下所示:
MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val view = LayoutInflater.from(this).inflate(R.layout.activity_main, null)
val params = WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
0,
PixelFormat.TRANSLUCENT
)
params.gravity = Gravity.START
(getSystemService(WINDOW_SERVICE) as WindowManager).addView(view, params)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f66">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is a long test text. This is a long test text. This is a long test text. This is a long test text. This is a long test text. This is a long test text. "
android:maxLines="1"
android:background="#6f6" />
</LinearLayout>
(在AndroidManifest.xml中需要<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
)
等到 TextView 布局完成后添加叠加层。然后你可以强制你需要的宽度 - 像这样:
findViewById<TextView>(R.id.textView).doOnNextLayout { textView ->
val view = LayoutInflater.from(this).inflate(R.layout.activity_main, null)
val params = WindowManager.LayoutParams(
textView.width,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
0,
PixelFormat.TRANSLUCENT
)
params.gravity = Gravity.START
val wm = getSystemService(WINDOW_SERVICE) as WindowManager
wm.addView(view, params)
}
不清楚为什么添加的 LinearLayout 及其 TextView 的宽度受到限制。
阅读 Cheticamps 的回答后,我进行了更多搜索并找到了一个解决方案,该解决方案仅适用于一个视图实例并且会自动调整大小。
扩展TextView
(或AppCompatTextView
)并覆盖onMeasure
:
class UnlimWidthTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : AppCompatTextView(context, attrs) {
val unlimitedWidth = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(unlimitedWidth, heightMeasureSpec)
}
}
注意这一点,因为它完全消除了对文本最大宽度的限制。
原来的widthMeasureSpec
总是有420px的宽度和MeasureSpec.AT_MOST
的模式,这解释了问题中显示的行为。
不过我没有找到这个 420px 的限制是从哪里来的。
高度具有屏幕高度 - 导航栏和 MeasureSpec.AT_MOST
的预期值,因此它的行为符合预期。
在我的应用程序中,我有一个带有 TextView 的叠加层,它具有动态文本大小和内容,可以使用触摸进行移动。目标是使叠加层与文本大小相同。使用 WRAP_CONTENT 作为叠加层,不会将包含文本的 LinearLayout 扩展到文本的全宽。
该示例加载与 Activity 的内容视图相同的布局和叠加层。 使用 MATCH_PARENT,完整的 TextView 可以显示在 Overlay 中,但这会使覆盖无法用于触摸事件,因为可以触摸整个宽度。如果没有 LinearLayout,它也不会扩展到全宽。 对于小于此最大宽度的宽度,wrap_content 按预期工作,对于高度 wrap_content,在向文本添加更多行时按预期工作于整个设备高度。
如何在不使 TextView 或 LinearLayout 比文本宽的情况下将 TextView 扩展到文本的整个宽度?
示例如下所示:
MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val view = LayoutInflater.from(this).inflate(R.layout.activity_main, null)
val params = WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
0,
PixelFormat.TRANSLUCENT
)
params.gravity = Gravity.START
(getSystemService(WINDOW_SERVICE) as WindowManager).addView(view, params)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f66">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is a long test text. This is a long test text. This is a long test text. This is a long test text. This is a long test text. This is a long test text. "
android:maxLines="1"
android:background="#6f6" />
</LinearLayout>
(在AndroidManifest.xml中需要<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
)
等到 TextView 布局完成后添加叠加层。然后你可以强制你需要的宽度 - 像这样:
findViewById<TextView>(R.id.textView).doOnNextLayout { textView ->
val view = LayoutInflater.from(this).inflate(R.layout.activity_main, null)
val params = WindowManager.LayoutParams(
textView.width,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
0,
PixelFormat.TRANSLUCENT
)
params.gravity = Gravity.START
val wm = getSystemService(WINDOW_SERVICE) as WindowManager
wm.addView(view, params)
}
不清楚为什么添加的 LinearLayout 及其 TextView 的宽度受到限制。
阅读 Cheticamps 的回答后,我进行了更多搜索并找到了一个解决方案,该解决方案仅适用于一个视图实例并且会自动调整大小。
扩展TextView
(或AppCompatTextView
)并覆盖onMeasure
:
class UnlimWidthTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : AppCompatTextView(context, attrs) {
val unlimitedWidth = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(unlimitedWidth, heightMeasureSpec)
}
}
注意这一点,因为它完全消除了对文本最大宽度的限制。
原来的widthMeasureSpec
总是有420px的宽度和MeasureSpec.AT_MOST
的模式,这解释了问题中显示的行为。
不过我没有找到这个 420px 的限制是从哪里来的。
高度具有屏幕高度 - 导航栏和 MeasureSpec.AT_MOST
的预期值,因此它的行为符合预期。