自Android 23起,android:foreground
XML属性(以及相应的setForeground()
method)应可用于所有View,而不仅仅是以前的FrameLayout实例。
但是,由于某种原因,每当我创建一个从TextView-> View继承的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>
属性不会改变任何内容,无论如何前景都不会显示。背景和文字一样正确显示,只是缺少前景。
我还尝试将前景设置为纯色,而不是可绘制的状态选择器,但没有成功。
答案 0 :(得分:0)
逐一删除样式元素并进行重新测试后,我将问题缩小为在样式中包含android:singleLine
属性。
删除此属性后,使用我的样式的所有TextViews或Button都将根据需要正确显示前景可绘制对象。查看定义了singleLine
的{{3}}的实现,我仍在努力确定设置此属性如何导致前景被忽略,但是如果发现,我将更新此答案。
我知道singleLine
的使用已被弃用,但不幸的是,我仍然需要singleLine
/ ellipsize
属性的组合所提供的功能,而这些属性在用{{1替换时是不可用的}}的用法。
编辑:在写完上面的答案后,我决定进行更多调查,并发现更多细节。
首先,我创建了一个自AppCompatButton扩展的自定义视图,因此我可以尝试重新实现所提供的功能maxLines
/ singleLine
(即,用换行符替换为一行显示文本)空格,然后在文本从视图中跑出时添加省略号)。
通读TextView.java,发现ellipsize
属性设置为true时会调用一段代码:
singleLine
所以我尝试提取这些行并将其添加到自己的实现中:
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
功能,并且前台可绘制对象按预期显示!缩小到该方法仍然无法帮助我找出TextView基本实现的根本原因,但是如果有人对此有任何详细信息,请随时评论更多信息。
这是我最后的自定义Button类,它仅查看ellipsize
属性,并在maxLines
设置为1时模拟旧的singleLine
功能,避免了会阻止前台运行的方法从显示。万一有用的话...
maxLines
}
并来自attrs.xml:
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);
}
}
答案 1 :(得分:0)
如Keith setHorizontallyScrolling(true)
所述,滚动使前景消失。可以轻松重现该问题。
但是为什么水平滚动会影响前景?
设置水平(或垂直滚动)指示TextView
包含的区域大于其布局范围。
如果打印scrollX
/ scrollY
值,即使内容不能被用户滚动,通常也不会是零,而是一个很大的数字。
另一方面,前景设计为随内容滚动,因此它基本上是从画布的(0, 0)
开始绘制的,而不是可见内容的左上角。因此,它的绘制距离实际视图范围很远。您可以为此View.java
的源代码打开onDrawForeground
。
我该怎么办
setHorizontallyScrolling(false)
属性或任何暗示滚动的功能后,通过调用singleline
来禁用滚动。当心不要在尝试初始化/更新视图时启用滚动。setBounds
和scrollX
scrollY
的边界