Marquee title in Toolbar / ActionBar in Android with Lollipop SDK?

风流意气都作罢 提交于 2019-11-30 19:28:52

Get the title TextView object from declared field name of TextView in Toolbar class and Marquee title of toolbar.

    TextView titleTextView = null;

    try {
        Field f = toolbar.getClass().getDeclaredField("mTitleTextView");
        f.setAccessible(true);
        titleTextView = (TextView) f.get(toolbar);

        titleTextView.setEllipsize(TruncateAt.MARQUEE);
        titleTextView.setFocusable(true);
        titleTextView.setFocusableInTouchMode(true);
        titleTextView.requestFocus();
        titleTextView.setSingleLine(true);
        titleTextView.setSelected(true);
        titleTextView.setMarqueeRepeatLimit(-1);

    } catch (NoSuchFieldException e) {
    } catch (IllegalAccessException e) {
    }

Try to put a TextView inside the Toolbar:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize" >

    <TextView
        android:id="@+id/toolbar_title"
        android:text="This will run the marquee animation forever"
        android:textSize="@dimen/abc_text_size_title_material_toolbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
        android:scrollHorizontally="true"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:singleLine="true" />

</android.support.v7.widget.Toolbar>

And then, use the Toolbar as an ActionBar and clear/disable its title:

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(null); // or, setDisplayShowTitleEnabled(false)

Figured it out eventually, it was because, from what I understand, TextViews that are set marquee need to be selected before they will actually start marqueeing. I updated my MarqueeToolbar class that I posted in the question, which can be found in this Gist: https://gist.github.com/InsanityOnABun/95c0757f2f527cc50e39

Kotlin solution to set MARQUEE for both Title and Subtitle TextViews (it just finds all TextViews inside Toolbar):

findViewById<Toolbar>(R.id.action_bar)?.let {
    setToolbarTextViewsMarquee(it)
}

fun setToolbarTextViewsMarquee(toolbar: Toolbar) {
    for (child in toolbar.children) {
        if (child is TextView) {
            setMarquee(child)
        }
    }
}

fun setMarquee(textView: TextView) {
    textView.ellipsize = TextUtils.TruncateAt.MARQUEE
    textView.isSelected = true
    textView.marqueeRepeatLimit = -1
}

So it's not necessary to add Toolbar view (android.support.v7.widget.Toolbar or androidx.appcompat.widget.Toolbar) to xml layout

You can use the default Toolbar which AppCompat theme automatically adds:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

create custom toolbar and apply title and subtitle marquee effect:

public class MarqueeToolbar extends Toolbar {

TextView title, subTitle;

public MarqueeToolbar(Context context) {
    super(context);
}

public MarqueeToolbar(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public MarqueeToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
public void setTitle(CharSequence title) {

        reflected = reflectTitle();

    super.setTitle(title);
    selectTitle();
}

@Override
public void setTitle(int resId) {
    if (!reflected) {
        reflected = reflectTitle();
    }
    super.setTitle(resId);
    selectTitle();
}

boolean reflected = false;
private boolean reflectTitle() {
    try {
        Field field = Toolbar.class.getDeclaredField("mTitleTextView");
        field.setAccessible(true);
        title = (TextView) field.get(this);
        title.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        title.setMarqueeRepeatLimit(-1);
        return true;
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
        return false;
    } catch (IllegalAccessException e) {
        e.printStackTrace();
        return false;
    } catch (NullPointerException e) {
        e.printStackTrace();
        return false;
    }
}

public void selectTitle() {
    if (title != null)
        title.setSelected(true);
}

// ------------ for Subtitle ----------

@Override

public void setSubtitle(CharSequence subTitle) {
    if (!reflectedSub) {
        reflectedSub = reflectSubTitle();
    }
    super.setSubtitle(subTitle);
    selectSubtitle();
}


@Override
public void setSubtitle(int resId) {
    if (!reflected) {
        reflectedSub = reflectSubTitle();
    }
    super.setSubtitle(resId);
    selectSubtitle();
}

boolean reflectedSub = false;
private boolean reflectSubTitle() {
    try {
        Field field = Toolbar.class.getDeclaredField("mSubtitleTextView");
        field.setAccessible(true);
        subTitle = (TextView) field.get(this);
        subTitle.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        subTitle.setMarqueeRepeatLimit(-1);
        return true;
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
        return false;
    } catch (IllegalAccessException e) {
        e.printStackTrace();
        return false;
    } catch (NullPointerException e) {
        e.printStackTrace();
        return false;
    }
}

public void selectSubtitle() {
    if (subTitle != null)
        subTitle.setSelected(true);
}

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!