自Android 23以来,android:foreground XML属性(以及相应的setForeground() 方法 )应该可用于所有视图,而不仅仅是以前的FrameLayout实例。
然而,由于某种原因,每当我创建一个从TextView ->视图继承的Button实例时,我似乎都无法显示前景。
下面是一个不起作用的示例按钮定义,它显示了前景:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="Primary Full Width"
style="@style/Button.Primary" />下面是Button.Primary风格的定义:
<style name="Button.Primary" parent="Widget.AppCompat.Button">
<item name="android:background">@drawable/button_primary_background_selector</item>
<item name="android:foreground">@drawable/button_primary_foreground_selector</item>
<item name="android:textAppearance">@style/TextAppearance.FF.Button</item>
<item name="android:minHeight">80dp</item>
<item name="android:height">80dp</item>
<item name="android:minWidth">200dp</item>
<item name="android:defaultWidth">288dp</item>
<item name="android:maxWidth">400dp</item>
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
<item name="android:gravity">center_vertical|center_horizontal</item>
<item name="android:paddingStart">70dp</item>
<item name="android:paddingEnd">70dp</item>
<item name="android:stateListAnimator">@null</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">end</item>
<item name="android:drawablePadding">10dp</item>
</style>我已经确认,在样式中或在foreground定义中设置<Button>属性不会改变任何事情,无论前景如何都不能显示。背景显示正确,就像文本一样,它只是缺少的前景。
我还尝试将前景设置为实色,而不是状态选择器可绘制,但没有成功。
发布于 2018-06-21 18:02:30
在逐个删除样式元素并重新测试之后,我将问题缩小到在样式中包含android:singleLine属性。
删除该属性使得使用我的样式的任何TextViews或按钮都能正确地显示前景可按需要绘制。在定义了TextView.java的singleLine的实现中,我仍然很难确定设置这个属性是如何导致find被忽略的,但是如果我发现了这个答案,我会更新这个答案。
我知道对singleLine的使用是不可取的,但不幸的是,我仍然需要singleLine / ellipsize属性组合提供的功能,这些属性在用maxLines使用替换时是不可用的。
编辑:写了我上面的答案后,我决定做一些更多的调查,并发现了一些更多的细节。
首先,我创建了一个从AppCompatButton扩展的自定义视图,这样我就可以尝试重新实现singleLine / ellipsize提供的功能(即,通过用空格替换换行符来在单行上显示文本,然后在文本离开视图时添加省略号)。
通过阅读TextView源代码,我发现了当singleLine属性设置为true时调用的一段代码:
private void applySingleLine(boolean singleLine, boolean applyTransformation,
boolean changeMaxLines) {
mSingleLine = singleLine;
if (singleLine) {
setLines(1);
setHorizontallyScrolling(true);
if (applyTransformation) {
setTransformationMethod(SingleLineTransformationMethod.getInstance());
}
}
...
}因此,我尝试提取这些行并添加到我自己的实现中:
private void updateMaxlinesLocally(int maxLines) {
if (maxLines == 1) {
Log.d("Button", "max lines was 1, setting to single line equivalent");
setLines(1);
setHorizontallyScrolling(true);
setTransformationMethod(SingleLineTransformationMethod.getInstance());
// reset any text that may have already been set
setText(getText());
} else {
Log.d("Button", "max lines was : " + maxLines);
}
}但是,当这段代码运行时,我在前面看到了同样的问题,在这个问题上,前景图形将不再可见。
经过进一步的测试,我能够将问题缩小到setHorizontallyScrolling(true)方法调用。如果我只是在我的自定义实现之外注释了这一行,我就能够保留我以前拥有的singleLine / ellipsize功能,以及预期的前景绘图显示!将其缩小到该方法仍然无法帮助我找出TextView基础实现中的根本原因,但是如果有人对此有任何详细了解,请随时评论并提供更多信息。
下面是我的最后一个自定义Button类,它简单地查看maxLines属性,并在将maxLines设置为1时模拟旧的maxLines功能,从而避免了方法调用,这将阻止from显示。万一有用..。
public class Button extends AppCompatButton {
public Button(Context context) {
super(context);
init(context, null, 0);
}
public Button(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public Button(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
@Override
public void setMaxLines(int maxLines) {
super.setMaxLines(maxLines);
updateMaxlinesLocally(maxLines);
}
private void init(Context context, AttributeSet attributeSet, int defStyleAttr) {
int[] set = {
android.R.attr.maxLines
};
TypedArray a = context.obtainStyledAttributes(
attributeSet, R.styleable.Button);
int maxLines = a.getInt(R.styleable.Button_android_maxLines, -1);
a.recycle();
updateMaxlinesLocally(maxLines);
}
private void updateMaxlinesLocally(int maxLines) {
if (maxLines == 1) {
Log.d("Button", "max lines was 1, setting to single line equivalent");
setLines(1);
// The act of setting horizontally scrolling to true is what disables foregrounds from
// showing...
// setHorizontallyScrolling(true);
setTransformationMethod(SingleLineTransformationMethod.getInstance());
// reset any text that may have already been set
setText(getText());
} else {
Log.d("Button", "max lines was : " + maxLines);
}
}}
来自attrs.xml:
<declare-styleable name="Button">
<attr name="android:maxLines" format="integer" />
</declare-styleable>发布于 2019-09-12 06:39:14
正如基思setHorizontallyScrolling(true)所说,滚动会使前景消失。人们可以很容易地再现这个问题。
但是为什么水平滚动会影响前景呢?
设置水平(或垂直滚动)会告诉TextView它包含的区域比它的布局边界更大。
如果您打印scrollX / scrollY值,通常它不会是零,而是一个非常大的数字,即使内容不能被用户滚动。
另一方面,前台是用来滚动内容的,因此它基本上是从画布的(0, 0) (而不是可见内容的左上角)开始绘制的。所以它被拉得离实际的视野很远。您可以为此打开View.java的onDrawForeground源代码。
我能做什么
setHorizontallyScrolling(false)属性或任何包含滚动的内容后,通过调用singleline来禁用滚动。注意不要启用滚动,尝试初始化/更新视图。setBounds和scrollY来更新边界https://stackoverflow.com/questions/50974994
复制相似问题