Risposte:
Sono d'accordo che questo non è completamente supportato, ma ecco cosa ho fatto. È possibile utilizzare una vista personalizzata per la barra delle azioni (verrà visualizzata tra l'icona e gli elementi delle azioni). Sto usando una vista personalizzata e ho il titolo nativo disabilitato. Tutte le mie attività ereditano da una singola attività, che ha questo codice in onCreate:
this.getActionBar().setDisplayShowCustomEnabled(true);
this.getActionBar().setDisplayShowTitleEnabled(false);
LayoutInflater inflator = LayoutInflater.from(this);
View v = inflator.inflate(R.layout.titleview, null);
//if you need to customize anything else about the text, do it here.
//I'm using a custom TextView with a custom font in my layout xml so all I need to do is set title
((TextView)v.findViewById(R.id.title)).setText(this.getTitle());
//assign the view to the actionbar
this.getActionBar().setCustomView(v);
E il mio layout xml (R.layout.titleview nel codice sopra) è simile al seguente:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent" >
<com.your.package.CustomTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:textSize="20dp"
android:maxLines="1"
android:ellipsize="end"
android:text="" />
</RelativeLayout>
Puoi farlo usando una TypefaceSpan
classe personalizzata . È superiore customView
all'approccio sopra indicato perché non si rompe quando si utilizzano altri elementi della barra delle azioni come l'espansione delle viste delle azioni.
L'uso di una tale classe sarebbe simile a questo:
SpannableString s = new SpannableString("My Title");
s.setSpan(new TypefaceSpan(this, "MyTypeface.otf"), 0, s.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// Update the action bar title with the TypefaceSpan instance
ActionBar actionBar = getActionBar();
actionBar.setTitle(s);
Alla TypefaceSpan
classe personalizzata viene passato il contesto Attività e il nome di un carattere tipografico nella assets/fonts
directory. Carica il file e memorizza nella cache una nuova Typeface
istanza in memoria. L'implementazione completa di TypefaceSpan
è sorprendentemente semplice:
/**
* Style a {@link Spannable} with a custom {@link Typeface}.
*
* @author Tristan Waddington
*/
public class TypefaceSpan extends MetricAffectingSpan {
/** An <code>LruCache</code> for previously loaded typefaces. */
private static LruCache<String, Typeface> sTypefaceCache =
new LruCache<String, Typeface>(12);
private Typeface mTypeface;
/**
* Load the {@link Typeface} and apply to a {@link Spannable}.
*/
public TypefaceSpan(Context context, String typefaceName) {
mTypeface = sTypefaceCache.get(typefaceName);
if (mTypeface == null) {
mTypeface = Typeface.createFromAsset(context.getApplicationContext()
.getAssets(), String.format("fonts/%s", typefaceName));
// Cache the loaded Typeface
sTypefaceCache.put(typefaceName, mTypeface);
}
}
@Override
public void updateMeasureState(TextPaint p) {
p.setTypeface(mTypeface);
// Note: This flag is required for proper typeface rendering
p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
}
@Override
public void updateDrawState(TextPaint tp) {
tp.setTypeface(mTypeface);
// Note: This flag is required for proper typeface rendering
tp.setFlags(tp.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
}
}
Copia semplicemente la classe sopra nel tuo progetto e implementala nel onCreate
metodo della tua attività come mostrato sopra.
textAllCaps
attributo è impostato su true sul TextView sottostante (ad esempio tramite un tema), il carattere personalizzato non verrà visualizzato. Questo è stato un problema per me quando ho applicato questa tecnica agli elementi della scheda della barra delle azioni.
assets/fonts/
. Se basta buttare i file .ttf / .otf tra le attività e non in una sottocartella, è necessario modificare la seguente riga di codice di conseguenza: String.format("fonts/%s", typefaceName)
. Ho perso 10 minuti buoni cercando di capirlo. In caso contrario, riceveraijava.lang.RuntimeException: Unable to start activity ComponentInfo{com.your.pckage}: java.lang.RuntimeException: native typeface cannot be made
int titleId = getResources().getIdentifier("action_bar_title", "id",
"android");
TextView yourTextView = (TextView) findViewById(titleId);
yourTextView.setTextColor(getResources().getColor(R.color.black));
yourTextView.setTypeface(face);
Da Android Support Library v26 + Android Studio 3.0 in poi, questo processo è diventato facile come un semplice gesto!
Attenersi alla seguente procedura per modificare il carattere del titolo della barra degli strumenti:
res > font
come da Font in XMLIn res > values > styles
, incolla quanto segue ( usa la tua immaginazione qui! )
<style name="TitleBarTextAppearance" parent="android:TextAppearance">
<item name="android:fontFamily">@font/your_desired_font</item>
<item name="android:textSize">23sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">@android:color/white</item>
</style>
Inserisci una nuova riga nelle proprietà della barra degli strumenti app:titleTextAppearance="@style/TextAppearance.TabsFont"
come mostrato di seguito
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:titleTextAppearance="@style/TitleBarTextAppearance"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
Goditi lo stile del carattere del titolo della barra delle azioni personalizzato !!
La libreria Calligraphy ti consente di impostare un carattere personalizzato tramite il tema dell'app, che si applicherebbe anche alla barra delle azioni.
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<item name="android:textViewStyle">@style/AppTheme.Widget.TextView</item>
</style>
<style name="AppTheme.Widget"/>
<style name="AppTheme.Widget.TextView" parent="android:Widget.Holo.Light.TextView">
<item name="fontPath">fonts/Roboto-ThinItalic.ttf</item>
</style>
Tutto ciò che serve per attivare Calligraphy è collegarlo al tuo contesto di attività:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(new CalligraphyContextWrapper(newBase));
}
L'attributo personalizzato predefinito è fontPath
, ma è possibile fornire il proprio attributo personalizzato per il percorso inizializzandolo nella propria classe Applicazione con CalligraphyConfig.Builder
. L'uso di android:fontFamily
è stato scoraggiato.
È un brutto hack ma puoi farlo in questo modo (poiché action_bar_title è nascosto):
try {
Integer titleId = (Integer) Class.forName("com.android.internal.R$id")
.getField("action_bar_title").get(null);
TextView title = (TextView) getWindow().findViewById(titleId);
// check for null and manipulate the title as see fit
} catch (Exception e) {
Log.e(TAG, "Failed to obtain action bar title reference");
}
Questo codice è per i dispositivi post-GINGERBREAD ma può essere facilmente esteso per funzionare anche con la barra delle azioni Sherlock
PS In base al commento di @pjv c'è un modo migliore per trovare l'ID del titolo della barra delle azioni
final int titleId =
Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
Il codice seguente funzionerà per tutte le versioni. L'ho verificato su un dispositivo con pan di zenzero e su un dispositivo JellyBean
private void actionBarIdForAll()
{
int titleId = 0;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
{
titleId = getResources().getIdentifier("action_bar_title", "id", "android");
}
else
{
// This is the id is from your app's generated R class when ActionBarActivity is used for SupportActionBar
titleId = R.id.action_bar_title;
}
if(titleId>0)
{
// Do whatever you want ? It will work for all the versions.
// 1. Customize your fonts
// 2. Infact, customize your whole title TextView
TextView titleView = (TextView)findViewById(titleId);
titleView.setText("RedoApp");
titleView.setTextColor(Color.CYAN);
}
}
usa la nuova barra degli strumenti nella libreria di supporto progetta la tua barra delle azioni come tua o usa il codice seguente
Gonfiare Textview non è una buona opzione per provare il generatore di stringhe Spannable
Typeface font2 = Typeface.createFromAsset(getAssets(), "fonts/<your font in assets folder>");
SpannableStringBuilder SS = new SpannableStringBuilder("MY Actionbar Tittle");
SS.setSpan (new CustomTypefaceSpan("", font2), 0, SS.length(),Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
actionBar.setTitle(ss);
copia sotto classe
public class CustomTypefaceSpan extends TypefaceSpan{
private final Typeface newType;
public CustomTypefaceSpan(String family, Typeface type) {
super(family);
newType = type;
}
@Override
public void updateDrawState(TextPaint ds) {
applyCustomTypeFace(ds, newType);
}
@Override
public void updateMeasureState(TextPaint paint) {
applyCustomTypeFace(paint, newType);
}
private static void applyCustomTypeFace(Paint paint, Typeface tf) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int fake = oldStyle & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(tf);
}
}
ActionBar actionBar = getSupportActionBar();
TextView tv = new TextView(getApplicationContext());
Typeface typeface = ResourcesCompat.getFont(this, R.font.monotype_corsiva);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, // Width of TextView
RelativeLayout.LayoutParams.WRAP_CONTENT); // Height of TextView
tv.setLayoutParams(lp);
tv.setText("Your Text"); // ActionBar title text
tv.setTextSize(25);
tv.setTextColor(Color.WHITE);
tv.setTypeface(typeface, typeface.ITALIC);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
actionBar.setCustomView(tv);
typeface.ITALIC
con Typeface.ITALIC
nessun avviso di membro statico
Se si desidera impostare il carattere tipografico su tutte le visualizzazioni di testo nell'intera attività, è possibile utilizzare qualcosa del genere:
public static void setTypefaceToAll(Activity activity)
{
View view = activity.findViewById(android.R.id.content).getRootView();
setTypefaceToAll(view);
}
public static void setTypefaceToAll(View view)
{
if (view instanceof ViewGroup)
{
ViewGroup g = (ViewGroup) view;
int count = g.getChildCount();
for (int i = 0; i < count; i++)
setTypefaceToAll(g.getChildAt(i));
}
else if (view instanceof TextView)
{
TextView tv = (TextView) view;
setTypeface(tv);
}
}
public static void setTypeface(TextView tv)
{
TypefaceCache.setFont(tv, TypefaceCache.FONT_KOODAK);
}
E TypefaceCache:
import java.util.TreeMap;
import android.graphics.Typeface;
import android.widget.TextView;
public class TypefaceCache {
//Font names from asset:
public static final String FONT_ROBOTO_REGULAR = "fonts/Roboto-Regular.ttf";
public static final String FONT_KOODAK = "fonts/Koodak.ttf";
private static TreeMap<String, Typeface> fontCache = new TreeMap<String, Typeface>();
public static Typeface getFont(String fontName) {
Typeface tf = fontCache.get(fontName);
if(tf == null) {
try {
tf = Typeface.createFromAsset(MyApplication.getAppContext().getAssets(), fontName);
}
catch (Exception e) {
return null;
}
fontCache.put(fontName, tf);
}
return tf;
}
public static void setFont(TextView tv, String fontName)
{
tv.setTypeface(getFont(fontName));
}
}
Ho appena fatto quanto segue all'interno della funzione onCreate ():
TypefaceSpan typefaceSpan = new TypefaceSpan("font_to_be_used");
SpannableString str = new SpannableString("toolbar_text");
str.setSpan(typefaceSpan,0, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
getSupportActionBar().setTitle(str);
Sto usando le librerie di supporto, se non le usi suppongo che dovresti passare a getActionBar () invece di getSupportActionBar ().
In Android Studio 3 puoi aggiungere caratteri personalizzati seguendo queste istruzioni https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html e quindi utilizzare il carattere appena aggiunto in " font_to_be_used"
Per aggiungere alla risposta di @ Sam_D, ho dovuto fare questo per farlo funzionare:
this.setTitle("my title!");
((TextView)v.findViewById(R.id.title)).setText(this.getTitle());
TextView title = ((TextView)v.findViewById(R.id.title));
title.setEllipsize(TextUtils.TruncateAt.MARQUEE);
title.setMarqueeRepeatLimit(1);
// in order to start strolling, it has to be focusable and focused
title.setFocusable(true);
title.setSingleLine(true);
title.setFocusableInTouchMode(true);
title.requestFocus();
Sembra eccessivo - facendo riferimento a v.findViewById (R.id.title)) due volte - ma è l'unico modo in cui mi lascerebbe fare.
Per aggiornare la risposta corretta.
in primo luogo: imposta il titolo su falso, perché stiamo usando la vista personalizzata
actionBar.setDisplayShowTitleEnabled(false);
secondo: creare titleview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent" >
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:textSize="20dp"
android:maxLines="1"
android:ellipsize="end"
android:text="" />
</RelativeLayout>
Infine :
//font file must be in the phone db so you have to create download file code
//check the code on the bottom part of the download file code.
TypeFace font = Typeface.createFromFile("/storage/emulated/0/Android/data/"
+ BuildConfig.APPLICATION_ID + "/files/" + "font name" + ".ttf");
if(font != null) {
LayoutInflater inflator = LayoutInflater.from(this);
View v = inflator.inflate(R.layout.titleview, null);
TextView titleTv = ((TextView) v.findViewById(R.id.title));
titleTv.setText(title);
titleTv.setTypeface(font);
actionBar.setCustomView(v);
} else {
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(" " + title); // Need to add a title
}
SCARICA IL FILE: perché sto archiviando il file nel cloud, quindi ho un link per scaricarlo.
/**downloadFile*/
public void downloadFile(){
String DownloadUrl = //url here
File file = new File("/storage/emulated/0/Android/data/" + BuildConfig.APPLICATION_ID + "/files/");
File[] list = file.listFiles();
if(list == null || list.length <= 0) {
BroadcastReceiver onComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
try{
showContentFragment(false);
} catch (Exception e){
}
}
};
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadUrl));
request.setVisibleInDownloadsUi(false);
request.setDestinationInExternalFilesDir(this, null, ModelManager.getInstance().getCurrentApp().getRegular_font_name() + ".ttf");
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
} else {
for (File files : list) {
if (!files.getName().equals("font_name" + ".ttf")) {
BroadcastReceiver onComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
try{
showContentFragment(false);
} catch (Exception e){
}
}
};
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadUrl));
request.setVisibleInDownloadsUi(false);
request.setDestinationInExternalFilesDir(this, null, "font_name" + ".ttf");
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
} else {
showContentFragment(false);
break;
}
}
}
}
Non è richiesta alcuna visualizzazione di testo personalizzata!
Innanzitutto, disabilita il titolo nella toobar nel tuo codice java: getSupportActionBar (). SetDisplayShowTitleEnabled (false);
Quindi, aggiungi semplicemente un oggetto TextView nella barra degli strumenti:
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="18sp"
android:fontFamily="@font/roboto" />
</android.support.v7.widget.Toolbar>
Prova a usare questo
TextView headerText= new TextView(getApplicationContext());
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT);
headerText.setLayoutParams(lp);
headerText.setText("Welcome!");
headerText.setTextSize(20);
headerText.setTextColor(Color.parseColor("#FFFFFF"));
Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/wesfy_regular.ttf");
headerText.setTypeface(tf);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setCustomView(headerText);
Dobbiamo usare le riflessioni per raggiungere questo obiettivo
final int titleId = activity.getResources().getIdentifier("action_bar_title", "id", "android");
final TextView title;
if (activity.findViewById(titleId) != null) {
title = (TextView) activity.findViewById(titleId);
title.setTextColor(Color.BLACK);
title.setTextColor(configs().getColor(ColorKey.GENERAL_TEXT));
title.setTypeface(configs().getTypeface());
} else {
try {
Field f = bar.getClass().getDeclaredField("mTitleTextView");
f.setAccessible(true);
title = (TextView) f.get(bar);
title.setTextColor(Color.BLACK);
title.setTypeface(configs().getTypeface());
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {
}
}
PROVA QUESTO
public void findAndSetFont(){
getActionBar().setTitle("SOME TEST TEXT");
scanForTextViewWithText(this,"SOME TEST TEXT",new SearchTextViewInterface(){
@Override
public void found(TextView title) {
}
});
}
public static void scanForTextViewWithText(Activity activity,String searchText, SearchTextViewInterface searchTextViewInterface){
if(activity == null|| searchText == null || searchTextViewInterface == null)
return;
View view = activity.findViewById(android.R.id.content).getRootView();
searchForTextViewWithTitle(view, searchText, searchTextViewInterface);
}
private static void searchForTextViewWithTitle(View view, String searchText, SearchTextViewInterface searchTextViewInterface)
{
if (view instanceof ViewGroup)
{
ViewGroup g = (ViewGroup) view;
int count = g.getChildCount();
for (int i = 0; i < count; i++)
searchForTextViewWithTitle(g.getChildAt(i), searchText, searchTextViewInterface);
}
else if (view instanceof TextView)
{
TextView textView = (TextView) view;
if(textView.getText().toString().equals(searchText))
if(searchTextViewInterface!=null)
searchTextViewInterface.found(textView);
}
}
public interface SearchTextViewInterface {
void found(TextView title);
}