Skip to content

Instantly share code, notes, and snippets.

@oleksandr-dovhaliuk-gp1
Last active February 21, 2020 10:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oleksandr-dovhaliuk-gp1/c94756c999e4df90a330 to your computer and use it in GitHub Desktop.
Save oleksandr-dovhaliuk-gp1/c94756c999e4df90a330 to your computer and use it in GitHub Desktop.
Title and Subtitle Toolbar Marquee
import android.content.Context;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;
import java.lang.reflect.Field;
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) {
if (!reflected) {
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);
}
}
@eolszewski
Copy link

@gwebalex line 84

@oleksandr-dovhaliuk-gp1
Copy link
Author

@eolszewski what is wrong in line 84?

@karishmapujara
Copy link

Hello sir
I am getting error
java.lang.NoSuchFieldException: No field mTitleTextView in class

I am using 'com.android.support:appcompat-v7:27.1.1'

Please help me

@sooperapps
Copy link

sooperapps commented Jul 11, 2018

@karishmapujara @gwebalex I suppose it happens because reflection can't find "mTitleTextView" in "field.get(this)". The problem is with THIS.

I solved it by creating an extension function for a regular Toolbar so that "this" now refers to the right class.

fun Toolbar.marqueeTitle() {
try {
val title: TextView?
val field = Toolbar::class.java.getDeclaredField("mTitleTextView")
field.isAccessible = true
title = field.get(this) as? TextView
title?.ellipsize = TextUtils.TruncateAt.MARQUEE
title?.marqueeRepeatLimit = -1
title?.isSelected = true
} catch (e: NoSuchFieldException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
} catch (e: NullPointerException) {
e.printStackTrace()
}
}

btw, "catch" branch for NPE may be redundant in my case

@drindt
Copy link

drindt commented Feb 21, 2020

fun Toolbar.marqueeTitle() { runCatching { val title: TextView? val field = Toolbar::class.java.getDeclaredField("mTitleTextView") field.isAccessible = true title = field.get(this) as? TextView title?.ellipsize = TextUtils.TruncateAt.MARQUEE title?.marqueeRepeatLimit = -1 title?.isSelected = true } }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment