我正在尝试利用 Android 设计支持库中的新
Snackbar
来显示多行小吃栏,如 http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts 所示-规格:
import android.support.design.widget.Snackbar;
final String snack = "First line\nSecond line\nThird line";
Snackbar.make(mView, snack, Snackbar.LENGTH_LONG).show();
在我的 Nexus 7 上仅显示
First line...
。如何使其显示所有行?
PS:我尝试了
Toast
,它显示了所有行。
只需设置 Snackbars Textview 的
maxLines
属性即可
View snackbarView = snackbar.getView();
TextView textView = (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
textView.setMaxLines(5); // show multiple line
"com.google.android.material:material:1.0.0"
依赖项,那么您将使用此: com.google.android.material.R.id.snackbar_text
来访问 Snackbar 的 TextView。您甚至可以使用
R.id.snackbar_text
。这对我有用。
可以覆盖应用程序的values.xml中使用的预定义值
<integer name="design_snackbar_text_max_lines">5</integer>
Snackbar 默认使用该值。
使用材质组件库,您可以使用应用程序主题中的
snackbarTextViewStyle
属性来定义它:
<style name="AppTheme" parent="Theme.MaterialComponents.*">
...
<item name="snackbarTextViewStyle">@style/snackbar_text</item>
</style>
<style name="snackbar_text" parent="@style/Widget.MaterialComponents.Snackbar.TextView">
...
<item name="android:maxLines">5</item>
</style>
注意:需要库版本1.2.0。
Snackbar snackbar = Snackbar.make(view, "Text",Snackbar.LENGTH_LONG).setDuration(Snackbar.LENGTH_LONG);
View snackbarView = snackbar.getView();
TextView tv= (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
tv.setMaxLines(3);
snackbar.show();
这是我对此的发现:
Android确实支持多行小吃栏,但它的最大限制为2行,这符合设计指南,其中规定多行小吃栏的高度应为80dp(几乎是2行)
为了验证这一点,我使用了 Cheesesquare Android 示例项目。如果我使用以下字符串:
Snackbar.make(view, "Random Text \n When a second snackbar is triggered while the first is displayed", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
在这种情况下,我可以看到带有第二行文本的多行小吃栏,即“当触发第二个小吃栏时”,但如果我将此代码更改为以下实现:
Snackbar.make(view, "Random Text \n When \n a second snackbar is triggered while the first is displayed", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
我只能看到“随机文本 当 ...”。这意味着设计库有意强制文本视图最多包含 2 行。
在 kotlin 中你可以使用扩展。
// SnackbarExtensions.kt
fun Snackbar.allowInfiniteLines(): Snackbar {
return apply { (view.findViewById<View?>(R.id.snackbar_text) as? TextView?)?.isSingleLine = false }
}
用途:
Snackbar.make(view, message, Snackbar.LENGTH_LONG)
.allowInfiniteLines()
.show()
对于Material Design,参考是
com.google.android.material.R.id.snackbar_text
val snack = Snackbar.make(myView, R.string.myLongText, Snackbar.LENGTH_INDEFINITE).apply {
view.findViewById<TextView>(com.google.android.material.R.id.snackbar_text).maxLines = 10
}
snack.show()
在 Kotlin 中,你可以这样做
Snackbar.make(root_view, "Yo\nYo\nYo!", Snackbar.LENGTH_SHORT).apply {
view.snackbar_text.setSingleLine(false)
show()
}
您也可以将
setSingleLine(false)
替换为 maxLines = 3
。
Android Studio 应该提示您添加
import kotlinx.android.synthetic.main.design_layout_snackbar_include.view.*
我还没能让它再次发挥作用,所以我只会分享我认为用 Kotlin 编写的最干净的方法,其他一些人已经分享过:
import com.google.android.material.R as MaterialR
Snackbar.make(root_view, "Yo\nYo\nYo!", Snackbar.LENGTH_SHORT).apply {
val textView = view.findViewById<TextView>(MaterialR.id.snackbar_text)
textView.setSingleLine(false)
show()
}
2021 Kotlin 答案
com.google.android.material:material:1.4.0
isSingleLine = false
是必需的以及 maxLines = 5
Snackbar.make(view, "line 1\nline 2", BaseTransientBottomBar.LENGTH_INDEFINITE)
.apply {
this.view.findViewById<TextView>(com.google.android.material.R.id.snackbar_text)?.apply {
maxLines = 5
isSingleLine = false
}
}
.show()
涉及对小吃栏包含的文本视图的资源 ID 进行硬编码的建议的替代方案是迭代查找 TextView。从长远来看,它更安全,让您可以更新支持库,而不必担心 ID 更改。
示例:
public static Snackbar getSnackbar(View rootView, String message, int duration) {
Snackbar snackbar = Snackbar.make(rootView, message, duration);
ViewGroup snackbarLayout = (ViewGroup) snackbar.getView();
TextView text = null;
for (int i = 0; i < snackbarLayout.getChildCount(); i++) {
View child = snackbarLayout.getChildAt(i);
// Since action is a button, and Button extends TextView,
// Need to make sure this is the message TextView, not the
// action Button view.
if(child instanceof TextView && !(child instanceof Button)) {
text = (TextView) child;
}
}
if (text != null) {
text.setMaxLines(3);
}
return snackbar;
}
我没有使用 setMaxLines,而是使用 setSingleLine 使 textview 换行到其内容。
String yourText = "First line\nSecond line\nThird line";
Snackbar snackbar = Snackbar.make(mView, yourText, Snackbar.LENGTH_SHORT);
TextView textView =
(TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text);
textView.setSingleLine(false);
snackbar.show();
这对我有用
Snackbar snackbar = Snackbar.make(mView, "Your text string", Snackbar.LENGTH_INDEFINITE);
((TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text)).setSingleLine(false);
snackbar.show();
迟到了,但可能对某人有帮助:
public void showSnackBar(String txt, View view){
final Snackbar snackbar = Snackbar.make(view,txt,Snackbar.LENGTH_INDEFINITE)
.setAction("OK", new View.OnClickListener() {
@Override
public void onClick(View view) {
//do something
}
});
View view = snackbar.getView();
TextView textView = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
textView.setMaxLines(5);
snackbar.show();
}
我可以建议你使用
com.google.android.material.snackbar.Snackbar
。这是google推荐的方式。首先,您必须添加小吃栏。
final Snackbar snackbar = Snackbar.make(
findViewById(R.id.activity_layout),
"snackbar explanation text \n multilines \n\n here",
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.action_settings, new View.OnClickListener() {
@Override
public void onClick(View view) {
// your action here
}
});
然后添加多行支持
TextView messageView = snackbar.getView().findViewById(R.id.snackbar_text);
messageView.setMaxLines(4);
最后展示小吃栏。
snackbar.show();
一种在新版本的库发生变化时不会崩溃的方法:
Snackbar.make(...).setAction(...) {
...
}.apply {
(view.findViewById<View?>(R.id.snackbar_text) as? TextView?)?.setSingleLine(false)
}.show()
还有一种不使用 id 的方法,将 Snackbar 中的所有 TextView 设置为具有无限多行:
@UiThread
fun setAllTextViewsToHaveInfiniteLinesCount(view: View) {
when (view) {
is TextView -> view.setSingleLine(false)
is ViewGroup -> for (child in view.children)
setAllTextViewsToHaveInfiniteLinesCount(child)
}
}
Snackbar.make(...).setAction(...) {
...
}.apply {
setAllTextViewsToHaveInfiniteLinesCount(view)
}.show()
Java 中的相同功能:
@UiThread
public static void setAllTextViewsToHaveInfiniteLines(@Nullable final View view) {
if (view == null)
return;
if (view instanceof TextView)
((TextView) view).setSingleLine(false);
else if (view instanceof ViewGroup)
for (Iterator<View> iterator = ViewGroupKt.getChildren((ViewGroup) view).iterator(); iterator.hasNext(); )
setAllTextViewsToHaveInfiniteLines(iterator.next());
}
只是一个快速评论,如果您使用
com.google.android.material:material
R.id
的前缀或包应该是 com.google.android.material
val snackbarView = snackbar.view
val textView = snackbarView.findViewById<TextView>(com.google.android.material.R.id.snackbar_text)
textView.maxLines = 3
因此,当我使用谷歌最新的材料设计库时,
com.google.android.material:material:1.1.0
,我使用下面的简单代码片段来解决允许在小吃栏中添加更多行的问题。希望它对新开发者也有帮助。
TextView messageView = snackbar.getView().findViewById(R.id.snackbar_text);
messageView.setMaxLines(5);
updateMaxLine
,如果Google决定更改文本视图的id,这个解决方案不太可能被破坏)val snackBar = Snackbar.make(view, message, duration)
snackBar.view.allViews.updateMaxLine(5)
snackBar.show()
请注意,此选项将更新 Snakbar 视图中所有文本视图的最大行(老实说我认为这并不重要)
将此添加为扩展
private fun <T> Sequence<T>.updateMaxLine(maxLine : Int) {
for (view in this) {
if (view is TextView) {
view.maxLines = maxLine
}
}
}
快捷栏高度调节:
val sMsg = "Msg\n\n"
val sOk = getString(R.string.ok)
val sMoreLines = StringBuilder()
for (iCtr in 1..6) {
sMoreLines.append("\n")
}
Snackbar
.make(
this.requireActivity().findViewById(android.R.id.content),
sMsg,
Snackbar.LENGTH_INDEFINITE)
.setAction("$sMoreLines$sOk\n$sMoreLines") {
// ...
}
.show()
现在 Snackbar 上有一个方法可以做到这一点。例如:
val snackbar = Snackbar.make(view, msgResId, Snackbar.LENGTH_LONG)
snackbar.setTextMaxLines(2)
snackbar.show()