ChatGPT解决这个技术问题 Extra ChatGPT

Android toolbar center title and custom font

I'm trying to figure out the right way to use a custom font for the toolbar title, and center it in the toolbar (client requirement).

At the moment, i'm using the good old ActionBar, and I was setting the title to empty value, and using setCustomView to put my custom font TextView and center it using ActionBar.LayoutParams.

Is there a better way to do that? Using the new Toolbar as my ActionBar.

MaterialToolbar supports centering toolbar and it supports changing font too, see: material.io/components/app-bars-top/…

S
Sushil

To use a custom title in your Toolbar all you need to do is remember is that Toolbar is just a fancy ViewGroup so you can add a custom title like so:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_top"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?android:attr/actionBarSize"
    android:background="@color/action_bar_bkgnd"
    app:theme="@style/ToolBarTheme" >


     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Toolbar Title"
        android:layout_gravity="center"
        android:id="@+id/toolbar_title" />


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

This means that you can style the TextView however you would like because it's just a regular TextView. So in your activity you can access the title like so:

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

suggest use android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" instead.
If anyone else can't remove the default app name title, do this: 1. Call setSupportActionBar(yourToolbar) 2. Call getSupportActionBar().setDisplayShowTitleEnabled(false);
To keep using default styles for the customised TextView, try something like style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" (see this answer).
adding android:paddingRight="?attr/actionBarSize" can help to center the text in the middle of your screen in the case you have a button (home, navigation drawer, etc)
What will be happened when there is Hamburger icon on Toolbar? It will be not in center of complete toolbar width, it will be in center of ToolbarWidth - HamburgerIconWidth.
G
Gueorgui Obregon

This's just to help to join all pieces using @MrEngineer13 answer with @Jonik and @Rick Sanchez comments with the right order to help to achieve title centered easly!!

The layout with TextAppearance.AppCompat.Widget.ActionBar.Title :

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay">

        <TextView
            android:id="@+id/toolbar_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"                      
            style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
            android:layout_gravity="center" />

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

The way to achieve with the right order:

    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);

Please don't forget to upvote @MrEngineer13 answer !!!

Here is a sample project ToolbarCenterTitleSample

https://i.stack.imgur.com/T1B7t.png

Hope to help somebody else ;)


if I set setDisplayHomeAsUpEnabled(true) and setDisplayShowHomeEnabled(true); to enalbe back arrow. Then title is not coming center. I have tried like setting actionBar.setTitle(""); and setDisplayShowTitleEnabled(false). But still not able to solve the issue
Are you tested it for a Scrolling Activity ?
it's true that with the back arrow, the title is not centered (it's off to the right by half the width of the back arrow). I suppose if I were really determined I'd programmatically add enough margin to the right of the textbox as necessary in order to center the text.
B
Binoy Babu

The ToolBar title is stylable. Any customization you make has to be made in the theme. I'll give you an example.

Toolbar layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    style="@style/ToolBarStyle.Event"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    android:minHeight="@dimen/abc_action_bar_default_height_material" />

Styles:

<style name="ToolBarStyle" parent="ToolBarStyle.Base"/>

<style name="ToolBarStyle.Base" parent="">
    <item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
    <item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
</style>

<style name="ToolBarStyle.Event" parent="ToolBarStyle">
    <item name="titleTextAppearance">@style/TextAppearance.Widget.Event.Toolbar.Title</item>
</style>

<style name="TextAppearance.Widget.Event.Toolbar.Title" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
    <!--Any text styling can be done here-->
    <item name="android:textStyle">normal</item>
    <item name="android:textSize">@dimen/event_title_text_size</item>
</style>

This is the correct way. Adding another TextView is a bit hacky, but the reflection answer is just plain evil.
Clean, but you can't set a custom font from style. Sadly.
Neither can you change the alignment of the title.
This does not center the text.
Does not center text as the OP asked for.
A
Akash Singh

we don't have direct access to the ToolBar title TextView so we use reflection to access it.

  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;
}

Although this is hacky, this solution works for me after trying to find a way to get access to the toolbar textview. Thank you.
Worked nicely for the Title. But when tried to obtain the mSubtitleTextView like this, it resulted in an exception. Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setTypeface(android.graphics.Typeface)' on a null object reference
Note: You can only access the "mTitleTextView" field, after you set the toolbar title! The field is lazy initialized by its first use.
What if you obfuscate your code with ProGuard and mTitleTextView becomes abcde12345?
@voghDev getDeclaredField will throw NoSuchFieldException in that case, resulting in the code not working.
f
fraggjkee

Define the following class:

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;
    }
}

...and then just use it instead of regular Toolbar like this:

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent">

        <your.packagename.here.CenteredToolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            android:theme="?attr/actionBarTheme"
            app:title="@string/reset_password_page_title"/>

        <!-- Other views -->

</RelativeLayout>

You still need these 2 lines of code in your Activity (as with standard Toolbar):

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);

That's it! You don't need to hide the standard left-aligned title, don't need to duplicate the same XML code over and over, etc., just use CenteredToolbar like if it was default Toolbar. You can also set your custom font programatically since you now have direct access to the TextView. Hope this helps.


Thanks! The best solution, only not to forget to import to toolbar the "v7.widget"
I know this is quite old but... how can I change text color? I've tried in XML with app:titleTextColor and in code with centeredTitleTextView.setColor. Any ideas, @fraggjkee?
centeredTitleTextView.setTextColor(...) should work
Shouldn't it be LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)?
hi what is binding?
N
Nikola Despotoski

Here is title text dependant approach to find TextView instance from 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;
}

u
user3210008

MaterialToolbar from Material Components 1.4.0-alpha02 now has the ability to center the toolbar's title by setting the titleCentered attribute to true:

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appBarLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/topAppBar"
        style="@style/Widget.MaterialComponents.Toolbar.Primary"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:titleCentered="true" />

</com.google.android.material.appbar.AppBarLayout>

This is the best answer ever. plz to vote up to help others seeing it 👍🏼
Got error attribute titleCentered not found
A
Ali Bdeir

No one has mentioned this, but there are some attributes for Toolbar:

app:titleTextColor for setting the title text color

app:titleTextAppearance for setting the title text appearance

app:titleMargin for setting the margin

And there are other specific-side margins such as marginStart, etc.


Perfect Solution.. if you are aware of FontOverride, just create style in styles.xml <style name="customFontTextAppearanceStyle"> <item name="android:textSize">18sp</item> <item name="android:typeface">monospace</item> and apply it in toolbar app:titleTextAppearance="@styles/customFontTextAppearanceStyle"
I used this method but nothing happened to my toolbar ! i created a new '<style>' and set it to app:titleTextAppearanc="style name" on the android.support.v7.widget.Toolbar TAG
what about the centering thing?
V
Vadim Kotov

I use this solution:

static void centerToolbarTitle(@NonNull final Toolbar toolbar) {
    final CharSequence title = toolbar.getTitle();
    final ArrayList<View> 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);
    }
}

Works very well, but for some reason it doesn't center properly with toolbars that don't have an item button.
An addition: if you have a navdrawer or back icon on toolbar, title not stay exactly center. I add an empty setting menu icon for this situation. My empty menu item is:
d
dsh

Without toolbar TextView we can customize font by using below code

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);
}

If you just need to change font, this seems like the most clean solution. NOTE: TypefaceSpanString is just this: stackoverflow.com/a/17961854
B
Bishan
    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);
    }
}

solution works great when you put out last two lines of code, it shouldn't be inside the for loop: // Restore title and subtitle toolbar.setTitle(originalTitle); toolbar.setSubtitle(originalSubtitle);
m
maros136

Layout:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_top"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="@color/action_bar_bkgnd"
    app:theme="@style/ToolBarTheme" >

     <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Toolbar Title"
        android:layout_gravity="center"
        android:gravity="center"
        android:id="@+id/toolbar_title" />
</android.support.v7.widget.Toolbar>

Code:

    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);

I think "int width = maxWidth - titleWidth * 2; " should be "int width = maxWidth - iconWidth * 2;", thinks!
v
vovahost

A very quick and easy way to set a custom font is to use a custom titleTextAppearance with a fontFamily:

Add to styles.xml:

<style name="ToolbarTitle" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
    <item name="android:textSize">16sp</item>
    <item name="android:textColor">#FF202230</item>
    <item name="android:fontFamily">@font/varela_round_regular</item>
</style>

In your res folder create a font folder (Ex: varela_round_regular.ttf)

Read the official guide to find out more https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html


h
headsvk

I don't know if anything changed in the appcompat library but it's fairly trivial, no need for reflection.

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;
    }
}

M
Monet_z_Polski

Solution that I used for this problem:

 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;
                }
            }
        }
    }

For center gravity I think it would be necessary to change layout params to match_parent horizontally and then:

tv.setGravity(Gravity.CENTER);

H
Hai Rom

I solved this solution , And this is a following codes:

<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Order History"
            android:layout_gravity="center"
            android:id="@+id/toolbar_title"
            android:textSize="17sp"
            android:textStyle="bold"
            android:textColor="@color/colorWhite"
            />

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

And you can change title/label , in Activity, write a below codes:

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

TextView mTitle = (TextView) toolbarTop.findViewById(R.id.toolbar_title); mTitle.setText("@string/....");


A
A Sharma

You can use like the following

 <android.support.v7.widget.Toolbar
    android:id="@+id/top_actionbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppThemeToolbar">

    <TextView
        android:id="@+id/pageTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        />
</android.support.v7.widget.Toolbar>

if I set setDisplayHomeAsUpEnabled(true) and setDisplayShowHomeEnabled(true); to enalbe back arrow. Then title is not coming center. I have tried like setting actionBar.setTitle(""); and setDisplayShowTitleEnabled(false). But still not able to solve the issue
d
ductran

Update from @MrEngineer13's answer: to align title center in any cases, including Hamburger icon, option menus, you can add a FrameLayout in toolbar like this:

   <android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_top"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="@color/action_bar_bkgnd"
    app:theme="@style/ToolBarTheme" >

         <FrameLayout android:layout_width="match_parent"
                    android:layout_height="match_parent">

              <TextView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="Toolbar Title"
               android:layout_gravity="center"
               style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
               android:id="@+id/toolbar_title" />

        </FrameLayout>

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

D
Deepak G M

Even though adding a text view to the toolbar can solve the problem of the restriction of title styling, there is an issue with it. Since we are not adding it to a layout, we do not have too much control over its width. We can either use wrap_content or match_parent.

Now consider a scenario where we have a searchView as a button on the right edge of the toolbar. If the title contents are more, it will go on top of the button obscuring it. There is no way of controlling this short of setting a width to the label and is something you don't want to do if you want to have a responsive design.

So, here is a solution that worked for me which is slightly different from adding a textview to the toolbar. Instead of that, add the toolbar and text view to a relative layout and ensure that the text view is on top of the toolbar. Then we can use appropriate margins and make sure the text view shows up where we want it to show up.

Make sure you set the toolbar to not show the title.

Here is the XML for this solution:

<RelativeLayout
                    android:orientation="horizontal"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="?attr/colorPrimary">

                    <android.support.v7.widget.Toolbar
                        android:theme="@style/ThemeOverlay.AppCompat.Dark"
                        android:id="@+id/activity_toolbar"
                        android:layout_width="match_parent"
                        android:layout_height="?attr/actionBarSize"
                        android:background="?attr/colorPrimary"
                        android:titleTextAppearance="@style/AppTheme.TitleTextView"
                        android:layout_marginRight="40dp"
                        android:layoutMode="clipBounds">

                        <android.support.v7.widget.SearchView
                            android:id="@+id/search_view"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="right"
                            android:layout_centerVertical="true"
                            android:layout_alignParentRight="true"
                            android:foregroundTint="@color/white" />
                        </android.support.v7.widget.Toolbar>

                    <TextView
                        android:id="@+id/toolbar_title"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginRight="90dp"
                        android:text="@string/app_name"
                        android:textSize="@dimen/title_text_size"
                        android:textColor="@color/white"
                        android:lines="1"
                        android:layout_marginLeft="72dp"
                        android:layout_centerVertical="true" />

                </RelativeLayout>

Solves the issue @ankur-chaudhary mentioned above.


R
Rainmaker

Since android.support.v7.appcompat 24.2 Toolbar has method setTitleTextAppearance and you can set its font without external textview.

create new style in styles.xml

<style name="RobotoBoldTextAppearance">
        <item name="android:fontFamily">@font/roboto_condensed_bold</item>
</style>

and use it

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

V
Valery Boretsky

I spent several days searching for a universal solution. My toolbar working with android menu and nav icon.

At first, you need create custom toolbar class. This class must have calculate title centered positions (paddings):

    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<TextView>(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)

}

Secondly, you need create layout toolbar:

<CenteredToolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar">

    <TextView
        android:id="@+id/centerTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</CenteredToolbar>

That's all


D
Diya Bhat

Try taking Toolbar and tittle in a separate view. Take a view on right end and given them weight equal to the toolbar weight. In this way your tittle will come in center.

<android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay"
    android:background="@color/white_color">
  <LinearLayout
   android:id="@+id/toolbar_layout"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@color/white_color">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/white_color"
        app:popupTheme="@style/AppTheme.PopupOverlay"
        app:contentInsetLeft="0dp"
        app:contentInsetStart="0dp"
        android:layout_weight="0.2"

        app:contentInsetStartWithNavigation="0dp"
        app:navigationIcon="@color/greyTextColor">
       </android.support.v7.widget.Toolbar>


        <com.an.customfontview.CustomTextView
            android:id="@+id/headingText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.6"
            android:gravity="center"
            android:text="Heading"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:textColor="@color/colorPrimary"
            android:textSize="@dimen/keyboard_number"
            android:layout_gravity="center_horizontal|center_vertical"
            app:textFontPath="fonts/regular.ttf" />
            <ImageView
                android:id="@+id/search_icon"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:visibility="visible"
                android:layout_weight="0.2"
                android:layout_gravity="center_horizontal|center_vertical"
                android:src="@drawable/portfolio_icon"/>
        </LinearLayout>

       </android.support.design.widget.AppBarLayout>

U
Uzair Ahmed

You can insert this code in your xml file

 <androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimaryDark"
    android:elevation="4dp"
    android:theme="@style/ThemeOverlay.AppCompat.ActionBar">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Toolbar Title"
        android:textColor="#000000"
        android:textSize="20dp"
        android:id="@+id/toolbar_title" />

</androidx.appcompat.widget.Toolbar>

Hi Uzair. Which xml file? I am using an Android Studio 3.6.3 Project created from an Empty Activity template. Thanks.
A
Anbuselvan Rocky

To use a custom title in your Toolbar you can add a custom title like :

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="5dp"
    app:contentInsetLeft="0dp"
    app:contentInsetStart="0dp"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    app:theme="@style/ThemeOverlay.AppCompat.Dark">


        <LinearLayout
            android:id="@+id/lnrTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/txvHeader"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal|center"
                android:gravity="center"
                android:ellipsize="end"
                android:maxLines="1"
                android:text="Header"
                android:textColor="@color/white"
                android:textSize="18sp" />


        </LinearLayout>


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

Java Code:

Toolbar toolbar = findViewById(R.id.toolbar);

setSupportActionBar(toolbar);

if (getSupportActionBar() == null)
    return;

getSupportActionBar().setTitle("Title");

getSupportActionBar().setDisplayHomeAsUpEnabled(true);


the title bar has a spacing on left & right... what is that effect appeared?
E
Evgenii

Use com.google.android.material.appbar.MaterialToolbar and app:titleCentered="true" tag

<com.google.android.material.appbar.MaterialToolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:titleCentered="true" />

w
wklbeta
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();
                }
            });
        }
    }
}

A
Ali Khaki

for custom font in toolbar you can override textView font in style and then every textView in your app also toolbar title font changed automatically i tested it in android studio 3.1.3

in style do it:

<style name="defaultTextViewStyle" parent="android:Widget.TextView">
        <item name="android:fontFamily">@font/your_custom_font</item>
</style>

and then in your theme use this:

<item name="android:textViewStyle">@style/defaultTextViewStyle</item>

Â
Ângelo Polotto

I found another way to add custom toolbar without any adicional Java/Kotlin code.

First: create a XML with your custom toolbar layout with AppBarLayout as the parent:

Second: Include the toolbar in your layout:


I
Idan Damri

As I see it you have two options:

1) Edit the toolbar XML. When your Toolbar is added in the XML it usually looks like that:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:elevation="4dp"
    app:popupTheme="@style/AppTheme.PopupOverlay"/>

if you want to customize it just remove the '/' in the end and make it like that:

<android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:elevation="4dp"
            app:popupTheme="@style/AppTheme.PopupOverlay">

            <android.support.constraint.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <ImageView
                    android:id="@+id/toolbar_iv"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:src="@mipmap/ic_launcher"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

                <TextView
                    android:id="@+id/toolbar_tv"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="20dp"
                    android:gravity="center"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintLeft_toRightOf="@+id/toolbar_iv"
                    app:layout_constraintTop_toTopOf="parent" />

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

that way you can have a toolbar and customize the textview and the logo.

2) Programrticly change the native textview and icon:

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setIcon(R.drawable.ic_question_mark);
getSupportActionBar().setTitle("Title");

make sure your toolbar is not null before you set anything in it.


G
Gourav

You can have a custom TextView in the toolbar like this:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_top"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="@color/action_bar_bkgnd"
    app:theme="@style/ToolBarTheme" >

     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title"
        android:layout_gravity="center"
        android:id="@+id/toolbar_title" />


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

So, this will center the text. If you want to add custom font to a normal Toolbar, make a <style>:

<style android:name="ToolbarFont">
    <item android:fontFamily = "@font/fontName" />
</style>

And add it to the toolbar:

toolbar.setTitleTextAppearance(this, R.style.ToolbarFont);

For the textview in the toolbar, you can define it with the fontFamily attribute:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_top"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="@color/action_bar_bkgnd"
    app:theme="@style/ToolBarTheme" >

     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title"
        android:layout_gravity="center"
        android:id="@+id/toolbar_title"
        android:fontFamily="@font/fontFamily" />


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