Título del centro de la barra de herramientas de Android y fuente personalizada

Estoy tratando de encontrar la forma correcta de usar una fuente personalizada para el título de la barra de herramientas y centrarla en la barra de herramientas (requisito del cliente).

Por el momento, estoy usando el viejo ActionBar, y estaba configurando el título para vaciar el valor, y usando setCustomView para poner mi fuente personalizada TextView y centrarla usando ActionBar.LayoutParams.

¿Hay una mejor manera de hacer eso? Usando la nueva barra de herramientas como mi barra de acción.

Para utilizar un título personalizado en la Toolbar todo lo que debe hacer es recordar que la Toolbar es solo un elegante grupo de vistas, por lo que puede agregar un título personalizado como este:

    

Esto significa que puede TextView estilo a la vista de TextView la TextView desee porque es solo una vista de texto normal. Entonces, en tu actividad puedes acceder al título de la siguiente manera:

 Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar_top); TextView mTitle = (TextView) toolbarTop.findViewById(R.id.toolbar_title); 

El título ToolBar es elogiable. Cualquier personalización que hagas debe hacerse en el tema. Te daré un ejemplo.

Diseño de la barra de herramientas:

   

Estilos:

     

no tenemos acceso directo al título TextBar title TextView, entonces usamos reflection para acceder a él.

  private TextView getActionBarTextView() { TextView titleTextView = null; try { Field f = mToolBar.getClass().getDeclaredField("mTitleTextView"); f.setAccessible(true); titleTextView = (TextView) f.get(mToolBar); } catch (NoSuchFieldException e) { } catch (IllegalAccessException e) { } return titleTextView; } 

Esto es solo para ayudar a unir todas las piezas usando la respuesta de @ MrEngineer13 con los comentarios de @Jonik y @Rick Sanchez con el orden correcto para ayudar a lograr el título centrado fácilmente.

El diseño con TextAppearance.AppCompat.Widget.ActionBar.Title :

     

La forma de lograr con el orden correcto:

  Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title); setSupportActionBar(toolbar); mTitle.setText(toolbar.getTitle()); getSupportActionBar().setDisplayShowTitleEnabled(false); 

Por favor, no te olvides de votar la respuesta @ MrEngineer13 !!!

Aquí hay un proyecto de ejemplo ToolbarCenterTitleSample

enter image description here

Espero ayudar a alguien más;)

Aquí está el enfoque dependiente del texto del título para encontrar la instancia de TextView desde la Toolbar de Toolbar .

  public static TextView getToolbarTitleView(ActionBarActivity activity, Toolbar toolbar){ ActionBar actionBar = activity.getSupportActionBar(); CharSequence actionbarTitle = null; if(actionBar != null) actionbarTitle = actionBar.getTitle(); actionbarTitle = TextUtils.isEmpty(actionbarTitle) ? toolbar.getTitle() : actionbarTitle; if(TextUtils.isEmpty(actionbarTitle)) return null; // can't find if title not set for(int i= 0; i < toolbar.getChildCount(); i++){ View v = toolbar.getChildAt(i); if(v != null && v instanceof TextView){ TextView t = (TextView) v; CharSequence title = t.getText(); if(!TextUtils.isEmpty(title) && actionbarTitle.equals(title) && t.getId() == View.NO_ID){ //Toolbar does not assign id to views with layout params SYSTEM, hence getId() == View.NO_ID //in same manner subtitle TextView can be obtained. return t; } } } return null; } 

Nadie ha mencionado esto, pero hay algunos atributos para la Toolbar de Toolbar :

app:titleTextColor para configurar el color del texto del título

app:titleTextAppearance para configurar el aspecto del texto del título

app:titleMargin para establecer el margen

Y hay otros márgenes laterales específicos como marginStart , etc.

Definir la siguiente clase:

 public class CenteredToolbar extends Toolbar { private TextView centeredTitleTextView; public CenteredToolbar(Context context) { super(context); } public CenteredToolbar(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public CenteredToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public void setTitle(@StringRes int resId) { String s = getResources().getString(resId); setTitle(s); } @Override public void setTitle(CharSequence title) { getCenteredTitleTextView().setText(title); } @Override public CharSequence getTitle() { return getCenteredTitleTextView().getText().toString(); } public void setTypeface(Typeface font) { getCenteredTitleTextView().setTypeface(font); } private TextView getCenteredTitleTextView() { if (centeredTitleTextView == null) { centeredTitleTextView = new TextView(getContext()); centeredTitleTextView.setTypeface(...); centeredTitleTextView.setSingleLine(); centeredTitleTextView.setEllipsize(TextUtils.TruncateAt.END); centeredTitleTextView.setGravity(Gravity.CENTER); centeredTitleTextView.setTextAppearance(getContext(), R.style.TextAppearance_AppCompat_Widget_ActionBar_Title); Toolbar.LayoutParams lp = new Toolbar.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); lp.gravity = Gravity.CENTER; centeredTitleTextView.setLayoutParams(lp); addView(centeredTitleTextView); } return centeredTitleTextView; } } 

… y luego solo usarlo en lugar de la Toolbar de Toolbar habitual de esta manera:

     

Todavía necesita estas 2 líneas de código en su Activity (como con la Toolbar estándar):

 Toolbar toolbar = (Toolbar) findViewByid(R.id.toolbar); // note that your activity doesn't need to know that it is actually a custom Toolbar setSupportActionBar(binding.toolbar); 

¡Eso es! No necesita ocultar el título estándar alineado a la izquierda, no necesita duplicar el mismo código XML una y otra vez, etc., simplemente use CenteredToolbar como si fuera la Toolbar predeterminada. También puede establecer su fuente personalizada programáticamente ya que ahora tiene acceso directo a TextView . Espero que esto ayude.

Yo uso esta solución:

 static void centerToolbarTitle(@NonNull final Toolbar toolbar) { final CharSequence title = toolbar.getTitle(); final ArrayList outViews = new ArrayList<>(1); toolbar.findViewsWithText(outViews, title, View.FIND_VIEWS_WITH_TEXT); if (!outViews.isEmpty()) { final TextView titleView = (TextView) outViews.get(0); titleView.setGravity(Gravity.CENTER); final Toolbar.LayoutParams layoutParams = (Toolbar.LayoutParams) titleView.getLayoutParams(); layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; toolbar.requestLayout(); //also you can use titleView for changing font: titleView.setTypeface(Typeface); } } 
  public class TestActivity extends AppCompatActivity { private Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.activity_test); toolbar = (Toolbar) findViewById(R.id.tool_bar); // Attaching the layout to the toolbar object setSupportActionBar(toolbar); customizeToolbar(toolbar); } public void customizeToolbar(Toolbar toolbar){ // Save current title and subtitle final CharSequence originalTitle = toolbar.getTitle(); final CharSequence originalSubtitle = toolbar.getSubtitle(); // Temporarily modify title and subtitle to help detecting each toolbar.setTitle("title"); toolbar.setSubtitle("subtitle"); for(int i = 0; i < toolbar.getChildCount(); i++){ View view = toolbar.getChildAt(i); if(view instanceof TextView){ TextView textView = (TextView) view; if(textView.getText().equals("title")){ // Customize title's TextView Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT); params.gravity = Gravity.CENTER_HORIZONTAL; textView.setLayoutParams(params); // Apply custom font using the Calligraphy library Typeface typeface = TypefaceUtils.load(getAssets(), "fonts/myfont-1.otf"); textView.setTypeface(typeface); } else if(textView.getText().equals("subtitle")){ // Customize subtitle's TextView Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT); params.gravity = Gravity.CENTER_HORIZONTAL; textView.setLayoutParams(params); // Apply custom font using the Calligraphy library Typeface typeface = TypefaceUtils.load(getAssets(), "fonts/myfont-2.otf"); textView.setTypeface(typeface); } } } // Restore title and subtitle toolbar.setTitle(originalTitle); toolbar.setSubtitle(originalSubtitle); } } 

Sin la barra de herramientas TextView, podemos personalizar la fuente usando el código siguiente

 getSupportActionBar().setDisplayShowTitleEnabled(false); or getActionBar().setDisplayShowTitleEnabled(false); public void updateActionbar(String title){ SpannableString spannableString = new SpannableString(title); spannableString.setSpan(new TypefaceSpanString(this, "futurastdmedium.ttf"), 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); mToolbar.setTitle(spannableString); } 

Diseño:

    

Código:

  Toolbar mToolbar = parent.findViewById(R.id.toolbar_top); TextView mToolbarCustomTitle = parent.findViewById(R.id.toolbar_title); //setup width of custom title to match in parent toolbar mToolbar.postDelayed(new Runnable() { @Override public void run () { int maxWidth = mToolbar.getWidth(); int titleWidth = mToolbarCustomTitle.getWidth(); int iconWidth = maxWidth - titleWidth; if (iconWidth > 0) { //icons (drawer, menu) are on left and right side int width = maxWidth - iconWidth * 2; mToolbarCustomTitle.setMinimumWidth(width); mToolbarCustomTitle.getLayoutParams().width = width; } } }, 0); 

Puede usar como el siguiente

     

No sé si algo cambió en la biblioteca de appcompat, pero es bastante trivial, no hay necesidad de reflexión.

 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); // loop through all toolbar children right after setting support // action bar because the text view has no id assigned // also make sure that the activity has some title here // because calling setText() with an empty string actually // removes the text view from the toolbar TextView toolbarTitle = null; for (int i = 0; i < toolbar.getChildCount(); ++i) { View child = toolbar.getChildAt(i); // assuming that the title is the first instance of TextView // you can also check if the title string matches if (child instanceof TextView) { toolbarTitle = (TextView)child; break; } } 

Solución que utilicé para este problema:

  public static void applyFontForToolbarTitle(Activity a){ Toolbar toolbar = (Toolbar) a.findViewById(R.id.app_bar); for(int i = 0; i < toolbar.getChildCount(); i++){ View view = toolbar.getChildAt(i); if(view instanceof TextView){ TextView tv = (TextView) view; if(tv.getText().equals(a.getTitle())){ tv.setTypeface(getRuneTypefaceBold(a)); break; } } } } 

Para la gravedad central, creo que sería necesario cambiar los parámetros de diseño a match_parent horizontalmente y luego:

 tv.setGravity(Gravity.CENTER); 

Resolví esta solución, y este es un código siguiente:

    

Y puede cambiar el título / etiqueta, en Actividad, escriba los códigos a continuación:

 Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar_top); 

TextView mTitle = (TextView) toolbarTop.findViewById (R.id.toolbar_title); mTitle.setText (“@ cadena / ….”);

Desde android.support.v7.appcompat 24.2 Toolbar tiene el método setTitleTextAppearance y puede establecer su fuente sin textview externo.

crear nuevo estilo en styles.xml

  

y usarlo

 mToolbar.setTitleTextAppearance(this, R.style.RobotoBoldTextAppearance); 

Una forma muy rápida y fácil de establecer una fuente personalizada es usar un titleTextAppearance personalizadoTextAppearance con una fontFamily :

Agregar a styles.xml :

  

En su carpeta res, cree una carpeta de fonts (Ej: varela_round_regular.ttf )

Lea la guía oficial para obtener más información https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html

Aunque agregar una vista de texto a la barra de herramientas puede resolver el problema de la restricción del estilo del título, existe un problema. Como no lo estamos agregando a un diseño, no tenemos demasiado control sobre su ancho. Podemos usar wrap_content o match_parent.

Ahora considere un escenario en el que tengamos una vista de búsqueda como un botón en el borde derecho de la barra de herramientas. Si el contenido del título es más, irá sobre el botón oscureciéndolo. No hay forma de controlar esto si no se establece un ancho en la etiqueta y es algo que no se debe hacer si se quiere tener un diseño receptivo.

Entonces, aquí hay una solución que funcionó para mí, que es ligeramente diferente de agregar una vista de texto a la barra de herramientas. En lugar de eso, agregue la barra de herramientas y la vista de texto a un diseño relativo y asegúrese de que la vista de texto esté en la parte superior de la barra de herramientas. Entonces podemos usar los márgenes apropiados y asegurarnos de que la vista de texto aparezca donde queremos que aparezca.

Asegúrese de configurar la barra de herramientas para que no muestre el título.

Aquí está el XML para esta solución:

       

Resuelve el problema @ ankur-chaudhary mencionado anteriormente.

Tratar

 @Override public void onBackPressed() { if(getTitle().equals(getResources().getString(R.string.app_name))) { super.onBackPressed();} else { //set visiblity } } 
 private void makeTitleCenter(String title, Toolbar toolbar) { if (title != null && !TextUtils.isEmpty(title.trim())) { final String tag = " "; if (getSupportActionBar() != null) { getSupportActionBar().setTitle(tag); } TextView titleTv = null; View leftBtn = null; for (int i = 0; i < toolbar.getChildCount(); i++) { View view = toolbar.getChildAt(i); CharSequence text = null; if (view instanceof TextView && (text = ((TextView) view).getText()) != null && text.equals(tag)) { titleTv = (TextView) view; } else if (view instanceof ImageButton) { leftBtn = view; } } if (titleTv != null) { final TextView fTitleTv = titleTv; final View fLeftBtn = leftBtn; fTitleTv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { fTitleTv.getViewTreeObserver().removeOnGlobalLayoutListener(this); int leftWidgetWidth = fLeftBtn != null ? fLeftBtn.getWidth() : 0; fTitleTv.setPadding(DimenUtil.getResources().getDisplayMetrics().widthPixels / 2 - leftWidgetWidth - fTitleTv.getWidth() / 2, 0, 0, 0); fTitleTv.requestLayout(); } }); } } } 

Configuración android:gravity="center" funcionó para mí

Sin estilo nada. Toolbar es básicamente un ViewGroup Todo lo que necesitas hacer es establecer la gravedad de los elementos en él.

   

Pasé varios días buscando una solución universal. Mi barra de herramientas funciona con el menú de Android y el ícono de navegación.

Al principio, necesitas crear una clase de barra de herramientas personalizada. Esta clase debe tener el cálculo de las posiciones centradas en el título (rellenos):

  class CenteredToolbar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : Toolbar(context, attrs, defStyleAttr) { init { addOnLayoutChangeListener(object : View.OnLayoutChangeListener { override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) { val titleTextView = findViewById(R.id.centerTitle) val x = titleTextView.x.toInt() val x2 = x + titleTextView.width val fullWidth = width val fullCenter = fullWidth / 2 val offsetLeft = Math.abs(fullCenter - x) val offsetRight = Math.abs(x2 - fullCenter) val differOffset = Math.abs(offsetLeft - offsetRight) if (offsetLeft > offsetRight) { titleTextView.setPadding(differOffset, 0, 0, 0) } else if (offsetRight > offsetLeft) { titleTextView.setPadding(0, 0, differOffset, 0) } removeOnLayoutChangeListener(this) } }) } override fun setTitle(resId: Int) = getTitleView().setText(resId) override fun setTitle(title: CharSequence?) = getTitleView().setText(title) fun getTitleView(): TextView = findViewById(R.id.centerTitle) } 

En segundo lugar, necesita crear una barra de herramientas de diseño:

    

Eso es todo

Actualización de la respuesta de @ MrEngineer13: para alinear el centro del título en cualquier caso, incluido el icono Hamburger, menús de opciones, puede agregar un FrameLayout en la barra de herramientas de esta manera:

       
     

Ninguna de las soluciones anteriores funcionó para mí. Descubrí que solo anulando el comportamiento predeterminado de la barra de acciones podría implementar mi vista personalizada.

Prueba este código:

getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); getSupportActionBar().setCustomView(R.layout.toolbar_home);

 Typeface face= Typeface.createFromAsset(getAssets(), "font/font.ttf"); // your custom font Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTypeface(face); setSupportActionBar(toolbar); 

Otro tutorial:

  1. Ejemplo de barra de herramientas de Android
  2. Usar fuente personalizada en Android
  3. Tutorial de ActionBar con un ejemplo