Toolbar image centered

AndroidAndroid Toolbar

Android Problem Overview


Using the last android.support.v7.widget.Toolbar I want to center an image in the toolbar but it keeps staying on the left.

The best way for me would be to use toolbar.setLogo() method and to center the logo but i don't see any way to do it.

I use a layout for the Toolbar:

  <android.support.v7.widget.Toolbar style="@style/ToolBarStyle"
                                   xmlns:android="http://schemas.android.com/apk/res/android"
                                   android:layout_width="match_parent"
                                   android:layout_height="wrap_content"
                                   android:background="?attr/colorPrimary"
                                   android:minHeight="@dimen/abc_action_bar_default_height_material">

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

Is there any possibility to add an image (logo) to the toolbar and center it? programatically or in the layout?

Android Solutions


Solution 1 - Android

Toolbar is just a ViewGroup, you can customize is as much as you want.

Try this :

<android.support.v7.widget.Toolbar
   style="@style/ToolBarStyle"
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="?attr/colorPrimary"
   android:minHeight="@dimen/abc_action_bar_default_height_material">

    <ImageView
        android:layout_width="wrap_content"
        android:contentDescription="@string/logo"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/ic_launcher"/>

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

This should bring your imageView in center of toolbar.

Solution 2 - Android

If you have any views and can't quite get the logo centered, it will be because the centering is based on remaining space, not the entire toolbar.

To guarantee the logo being centered, try using a layer-list as a background of your toolbar instead of trying to use an image as a view.

toolbar.xml

<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="@drawable/toolbar_background"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    app:layout_scrollFlags="scroll|enterAlways"
    app:layout_collapseMode="pin">
</android.support.v7.widget.Toolbar>

toolbar_background.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <shape android:shape="rectangle">
      <solid android:color="@color/colorPrimary" />
    </shape>
  </item>
  <item>
    <bitmap android:src="@drawable/logo" android:gravity="center" />
  </item>
</layer-list>

That should ensure a centered logo, with a specific background colour.

Solution 3 - Android

This is not the best solution but it's a work around that works even when you have up button or menu item.

try

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

    <android.support.v7.widget.Toolbar
       style="@style/ToolBarStyle"
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:background="?attr/colorPrimary"
       android:minHeight="@dimen/abc_action_bar_default_height_material"/>

    <ImageView
        android:layout_width="wrap_content"
        android:contentDescription="@string/logo"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/ic_launcher"/>

</FrameLayout>

Solution 4 - Android

I like the approach given by Ruben Yoo's answer because of its simplicity. It is explicit, easy to follow, and keeps all the code changes together.

Here's an updated version with some minor improvements:

<android.support.design.widget.AppBarLayout
    android:id="@+id/layout_app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize">
        </android.support.v7.widget.Toolbar>

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="@string/app_name"
            android:scaleType="centerInside"
            android:src="@mipmap/ic_launcher"/>
    </FrameLayout>

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

Changes:

  1. introduced AppBarLayout parent
  2. explicit size ?attr/actionBarSize provided to frame & toolbar
  3. ImageView matches parent dimensions in width & height
  4. logo resized to centerInside

Solution 5 - Android

I had a similar problem. I tried to use the layer-list approach that Blueberry suggested, but once I put in a high-res asset for the logo the solution no longer worked. A bitmap in a layer-list has a bug: It will enlarge smaller images to fit the space but won't shrink larger images. So, as long as you are okay with using tiny images that look grainy/pixelated when they are enlarged, layer-list works fine.

To solve this problem and to have a centered high-res logo, I completely removed the android:background attribute from Toolbar, added android:background="?attr/colorPrimary" to my AppBarLayout parent and then tossed this terrible code into my Activity's onCreate method:

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

	ActionBar ab = getSupportActionBar();
	if (ab != null && toolbar != null)
	{
		// Hide the title text.
		ab.setDisplayShowTitleEnabled(false);

		// Convert and show the logo.
		toolbar.addOnLayoutChangeListener(new View.OnLayoutChangeListener()
		{
			@Override
			public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
			{
				ActionBar ab = getSupportActionBar();
				if (ab != null)
				{
					Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
					Bitmap bmp2 = Bitmap.createBitmap(toolbar.getWidth(), toolbar.getHeight(), bmp.getConfig());
					Bitmap bmp3 = Bitmap.createScaledBitmap(bmp, bmp.getWidth() * toolbar.getHeight() / bmp.getHeight(), toolbar.getHeight(), true);
					Canvas canvas = new Canvas(bmp2);
					canvas.drawBitmap(bmp3, (toolbar.getWidth() / 2) - (bmp3.getWidth() / 2), 0, null);
					BitmapDrawable background = new BitmapDrawable(getResources(), bmp2);
					ab.setBackgroundDrawable(background);
				}
			}
		});
	}

It works by creating a canvas the size of the toolbar and a ratio-scaled version of the logo, drawing the newly resized logo onto the canvas in the center, and finally setting the bitmap being drawn on as the background of the action bar.

On the plus side, this approach gives you total control over placement, sizing, etc. Not limited to whatever you can do in XML. It's terrible because it is called pretty regularly whenever the toolbar layout changes, which means there are performance implications. But, when you are required by your design team (that cares not about the first thing regarding Material Design) to have a background logo and waste five hours looking for the solution above, performance stops mattering - you just want the damn thing to work. The above code reeks pretty badly of desperation.

I'll let someone more capable than me in Android development point out that "I'm doing it wrong" and fix whatever performance issues/bugs there are with the above code. It doesn't change the fact that layer-list bitmap is broken and this is a hack (that should not exist) to fix a stupid bug (that should also not exist) in Android.

Solution 6 - Android

If user set :

activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); activity.getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_iconmenu);

and after do something like

<Toolbar ... >
   <ImageView ...>
   </ImageView>
</Toolbar>

then image inside toolbar will not be centered as well cause home button eat some space from layout.Image's horizontal center will be biased on home icon width.So best solution:
1.Create 9-patch png from your original image .png resource.
2.Create drawable from 9-patch with xml using layer-list as example toolbar_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:drawable="@color/white"/><!-- fill color under image(optional) -->
    <item>
        <nine-patch
        android:src="@drawable/toolbar_image" />
    </item>
</layer-list>


Then set toolbar_background resource as background at Toolbar element:

<Toolbar android:background="toolbar_background" ...>
</Toolbar>


That's all.

Solution 7 - Android

If you need to center a more complicated layout in the Toolbar than just an image, this is what I placed to my Activity's onCreate():

mToolbar.addOnLayoutChangeListener(
            new View.OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
                    // Push layout to the center
                    int toolbarCenterX = (int) (mToolbar.getWidth() / 2.0 - mMiddleToolbarLayout.getWidth() / 2.0));
                    if(mMiddleToolbarLayout.getX() != toolbarCenterX) {
                        mMiddleToolbarLayout.setX(toolbarCenterX);
                    }
                }
            }
    );

When onLayoutChange is called, your layout's width is already determined so you just push it to the center.

NOTE: It is important to only center toolbar (see the if condition) when it is not centered, otherwise this callback would be re-called in an infinite loop.

The XML file will look like this:

<android.support.v7.widget.Toolbar
...
>
    <LinearLayout
        android:id="@+id/middle_toolbar_layout"
        ...
    >
</android.support.v7.widget.Toolbar>

Solution 8 - Android

you can use this code:

     <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">


        <ImageView
            android:layout_width="250dp"
            android:layout_height="match_parent"
            android:src="@drawable/apptitle"/>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNicolas HauzareeView Question on Stackoverflow
Solution 1 - AndroidAbhinav PuriView Answer on Stackoverflow
Solution 2 - AndroidBlueberryView Answer on Stackoverflow
Solution 3 - AndroidRubin YooView Answer on Stackoverflow
Solution 4 - AndroidRichard Le MesurierView Answer on Stackoverflow
Solution 5 - AndroidmaddogView Answer on Stackoverflow
Solution 6 - Androidartyom mamaevView Answer on Stackoverflow
Solution 7 - AndroidjohnnyView Answer on Stackoverflow
Solution 8 - AndroidMatin GdzView Answer on Stackoverflow