Last active
February 21, 2020 10:42
-
-
Save oleksandr-dovhaliuk-gp1/c94756c999e4df90a330 to your computer and use it in GitHub Desktop.
Title and Subtitle Toolbar Marquee
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
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
@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