[feature] 通过反射调整间隙
This commit is contained in:
@@ -115,6 +115,8 @@
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:text="----"
|
||||
app:customGap="0.5"
|
||||
app:useCustomGap="true"
|
||||
android:textColor="@color/bus_p_line_name_color"
|
||||
android:textSize="@dimen/bus_p_driver_number_plate_size"
|
||||
android:textStyle="bold"
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
android:layout_marginRight="@dimen/dp_60"
|
||||
android:textColor="@color/bus_p_station_txt_color"
|
||||
android:layout_marginLeft="@dimen/dp_90"
|
||||
app:customGap="0.5"
|
||||
app:useCustomGap="true"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/bus_p_tag"
|
||||
app:layout_constraintTop_toBottomOf="@+id/bus_p_cur_arrow_bg"/>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.mogo.och.common.module.utils;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class FieldUtils {
|
||||
|
||||
public static Field getDeclaredField(final Class<?> cls, final String fieldName, final
|
||||
boolean forceAccess) {
|
||||
if (cls == null || TextUtils.isEmpty(fieldName)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// only consider the specified class by using getDeclaredField()
|
||||
final Field field = cls.getDeclaredField(fieldName);
|
||||
if (!isAccessible(field)) {
|
||||
if (forceAccess) {
|
||||
field.setAccessible(true);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return field;
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static boolean isAccessible(final Member m) {
|
||||
return m != null && Modifier.isPublic(m.getModifiers()) && !m.isSynthetic();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,31 @@
|
||||
package com.mogo.och.common.module.wigets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewDebug;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mogo.och.common.module.R;
|
||||
import com.mogo.och.common.module.utils.FieldUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
|
||||
public class MarqueeTextView extends androidx.appcompat.widget.AppCompatTextView{
|
||||
|
||||
/**
|
||||
* 上一次设置的时间,用于过滤多余操作
|
||||
*/
|
||||
private long mLastSetTime;
|
||||
/**
|
||||
* 自定义 gap
|
||||
*/
|
||||
private float mCustomGap = 0.3f;
|
||||
/**
|
||||
* 是否使用自定义 gap
|
||||
*/
|
||||
private boolean mUseCustomGap;
|
||||
|
||||
public MarqueeTextView(Context context) {
|
||||
this(context, null);
|
||||
@@ -18,6 +37,11 @@ public class MarqueeTextView extends androidx.appcompat.widget.AppCompatTextView
|
||||
|
||||
public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MarqueeTextView);
|
||||
mCustomGap = typedArray.getFloat(R.styleable.MarqueeTextView_customGap, mCustomGap);
|
||||
mUseCustomGap = typedArray.getBoolean(R.styleable.MarqueeTextView_useCustomGap, false);
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -32,4 +56,74 @@ public class MarqueeTextView extends androidx.appcompat.widget.AppCompatTextView
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
reflectToChangeGap();
|
||||
|
||||
super.invalidate();
|
||||
}
|
||||
|
||||
private void reflectToChangeGap() {
|
||||
if (!mUseCustomGap) {
|
||||
return;
|
||||
}
|
||||
if (System.currentTimeMillis() - mLastSetTime < 1000) {
|
||||
// 1s 内不重新设置,过滤多余操作
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Class marqueClass = null;
|
||||
Class[] innerClazz = TextView.class.getDeclaredClasses();
|
||||
for (Class clazz : innerClazz) {
|
||||
if ("Marquee".equals(clazz.getSimpleName())) {
|
||||
marqueClass = clazz;
|
||||
}
|
||||
}
|
||||
|
||||
if (marqueClass == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Field field1 = FieldUtils.getDeclaredField(marqueClass, "mGhostStart", true);
|
||||
|
||||
if (field1 == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int textWidth = getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
|
||||
final float lineWidth = getLayout().getLineWidth(0);
|
||||
final float gap = mCustomGap*textWidth;
|
||||
float ghostStart = lineWidth - textWidth + gap;
|
||||
float maxScroll = ghostStart + textWidth;
|
||||
float ghostOffset = lineWidth + gap;
|
||||
float maxFadeScroll = ghostStart + lineWidth + lineWidth;
|
||||
|
||||
final Field field = FieldUtils.getDeclaredField(TextView.class, "mMarquee", true);
|
||||
if (field != null) {
|
||||
Object mMarque = field.get(this);
|
||||
if (mMarque != null) {
|
||||
mLastSetTime = System.currentTimeMillis();
|
||||
float mGhostStart = (float) field1.get(mMarque);
|
||||
if (mGhostStart != ghostStart) {
|
||||
// 需要设置的 mGhostStart 与当前 ghostStart 不相等时才去设置
|
||||
Field field2 = FieldUtils.getDeclaredField(marqueClass, "mMaxScroll", true);
|
||||
Field field3 = FieldUtils.getDeclaredField(marqueClass, "mGhostOffset", true);
|
||||
Field field4 = FieldUtils.getDeclaredField(marqueClass, "mMaxFadeScroll", true);
|
||||
|
||||
if (field2 == null || field3 == null || field4 == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
field1.set(mMarque, ghostStart);
|
||||
field2.set(mMarque, maxScroll);
|
||||
field3.set(mMarque, ghostOffset);
|
||||
field4.set(mMarque, maxFadeScroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,4 +52,9 @@
|
||||
<attr name="och_realtime_end_color" format="color" />
|
||||
<attr name="och_realtime_radius" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MarqueeTextView">
|
||||
<attr name="customGap" format="float" />
|
||||
<attr name="useCustomGap" format="boolean"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user