[英]Android: How to remove end blank space from Textview with marquee
我已经创建了带有选取框的 TextView,但我想删除 end 之间的空格并再次开始显示文本。
这是屏幕
http://i.stack.imgur.com/dfdT8.png
这是我的布局
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:text="dkfjdkf jdfjfsfjkfa asdfjakjfdkasf sfdjaskfjdksf sfdjsfjk gfhgfhfai ggfghgf" />
利用 :
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
如果通过空格你指的是TextView之前和之后的那些黑色条纹,你可以将你的布局调整为android:layout_width="match_parent"
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:text="dkfjdkf jdfjfsfjkfa asdfjakjfdkasf sfdjaskfjdksf sfdjsfjk gfhgfhfai ggfghgf" />
此外,请确保该 TextView 的父布局未应用任何边距
当API 28引入对非 SDK 接口的限制时,此解决方案一直有效。
我遇到了同样的问题,我在网上找不到解决方案。 通过查看TextView 的源代码并参考 其他提供控制滚动速度选项的答案,我自己设法解决了这个问题。
查看源代码,它将间隙或空白空间设置为 TextView 大小的 1/3。 因此,如果您的 TextView 是 600 像素宽,它将在消息的开头和结尾之间创建 200 像素的间隙。 该解决方案旨在使该值可配置。
棘手的部分是您需要覆盖的逻辑都在超类的私有类、字段和方法中。 这使得解决方案变得不那么简单。
将此类添加到您的项目中... CustomTextView.java
public class CustomTextView extends AppCompatTextView {
private static final float NEW_GAP = 0F;
Object marqueeObject;
Field mStatusField;
Field mGhostStartField;
Field mMaxScrollField;
Field mGhostOffsetField;
Field mFadeStopField;
Field mMaxFadeScrollField;
public CustomTextView(Context context) {
super(context);
setSelected(true);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setSelected(true);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setSelected(true);
}
@Override
protected void onDraw(Canvas canvas) {
try {
initMarqueeObject();
if (didMarqueeRestart()) {
// We need to update the values each time it restarts
updateMarqueeFieldValues();
}
}
catch(Exception exception) {
exception.printStackTrace();
}
super.onDraw(canvas);
}
private void initMarqueeObject() throws Exception {
if (marqueeObject == null) {
Field marqueeField = getClass().getSuperclass().getSuperclass().getDeclaredField("mMarquee"); // use if extending from AppCompatTextView
// Field marqueeField = getClass().getSuperclass().getDeclaredField("mMarquee"); // use if extending from TextView
marqueeField.setAccessible(true);
marqueeObject = marqueeField.get(this);
initMarqueeFields();
}
}
private void initMarqueeFields() throws Exception {
mStatusField = marqueeObject.getClass().getDeclaredField("mStatus");
mStatusField.setAccessible(true);
mGhostStartField = marqueeObject.getClass().getDeclaredField("mGhostStart");
mGhostStartField.setAccessible(true);
mMaxScrollField = marqueeObject.getClass().getDeclaredField("mMaxScroll");
mMaxScrollField.setAccessible(true);
mGhostOffsetField = marqueeObject.getClass().getDeclaredField("mGhostOffset");
mGhostOffsetField.setAccessible(true);
mFadeStopField = marqueeObject.getClass().getDeclaredField("mFadeStop");
mFadeStopField.setAccessible(true);
mMaxFadeScrollField = marqueeObject.getClass().getDeclaredField("mMaxFadeScroll");
mMaxFadeScrollField.setAccessible(true);
}
private boolean didMarqueeRestart() throws Exception {
byte currentState = mStatusField.getByte(marqueeObject);
return currentState == 0x1; // 0x1 is the byte object for the MARQUEE_STARTING state
}
private void updateMarqueeFieldValues() throws Exception {
float textWidth = getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
float originalGap = textWidth / 3.0F;
// We have to calculate the lineWidth based on the original value
float originalValueStartValue = mGhostStartField.getFloat(marqueeObject);
float lineWidth = originalValueStartValue + textWidth - originalGap;
float mGhostStart = lineWidth - textWidth + NEW_GAP;
mGhostStartField.setFloat(marqueeObject, mGhostStart);
mMaxScrollField.setFloat(marqueeObject, mGhostStart + textWidth);
mGhostOffsetField.setFloat(marqueeObject, lineWidth + NEW_GAP);
mFadeStopField.setFloat(marqueeObject, lineWidth);
mMaxFadeScrollField.setFloat(marqueeObject, mGhostStart + lineWidth + lineWidth);
}
}
您现在可以使用NEW_GAP
变量轻松调整额外的空白空间。 在本例中,它设置为 0 像素。 将该常数设置为您希望使用的任何像素值。
注意:此解决方案是从AppCompatTextView
扩展而来的。 如果您从TextView
扩展,您应该取消注释initMarqueeObject()
方法中的相关代码。
然后只需使用这个新类代替 XML 中的旧 TextView ......
<com.yourpackagename.CustomTextView
android:focusable="true"
android:focusableInTouchMode="true"
android:singleLine="true"
android:scrollHorizontally="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
无需在代码中调用setSelected(true)
,因为这是在新类内部完成的。
这可能不会永远有效,因为如果他们重命名某些变量或在未来版本中更改TextView
的逻辑,它将中断。 但它在我测试过的所有版本上都运行良好。
希望这会有所帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.