Toolbar image centered
Asked Answered
G

8

70

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?

Gristede answered 17/12, 2014 at 20:32 Comment(2)
You can do it, but you should read the guidelines. Android doesn't use a logo centered in the toolbar.Cherice
#33301478Bibliopole
B
142

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.

Batson answered 17/12, 2014 at 21:1 Comment(4)
How to change set icon grammatically ? please help.Dominion
@AnandSavjani What I did was set an ID on ImageView and then in my Activity I assign an ImageView variable to it. Then simply, toolbarID.SetImageResource(Resource.Drawable.logo);Cornela
As I see, Toolbar is extending ViewGroup, so android:layout_gravity is not valid attribute. Maybe I'm doing something wrong, but it's not working.Elnoraelnore
I have added layout_width="match_parent" attribute to ImageView and it works.Ephraim
M
35

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.

Malacology answered 16/3, 2016 at 23:7 Comment(4)
this is a much better answerNakasuji
How do you adjust size here with the drawable?Guaiacum
I noticed you had a comment on another question, so I assume you haven't found an answer - If you cant find another solution, maybe recreating the image with a particular size is your best bet.Malacology
Is there any way to adjust the size of the bitmap, because when I do this it makes the image i'm trying to use very huge and unusable within the Toolbar...Upheld
E
9

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>
Exciseman answered 22/3, 2017 at 20:22 Comment(1)
Nice answer - simple to follow. I've updated it for 2018 with a few enhancements in my own answer - if you want to copy those changes into yours I'd be happy to remove mine as it would no longer add anything useful.Wadewadell
W
6

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
Wadewadell answered 19/11, 2018 at 11:34 Comment(0)
C
2

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.

Chalaza answered 21/6, 2016 at 18:19 Comment(6)
In my mind the best way would be the XML approach, with several sizes of the image for scaling. It is a fairly standard android approach. Not sure if I have encountered the same issue?Malacology
Devices come in all shapes and sizes so there is no way to handle every device unless you want to deliver a 200MB binary just for a logo.Chalaza
I think all you should worry about is densities, of which there are only six you need to handle. Please see here for further information on how to support multiple densities. developer.android.com/guide/practices/…Malacology
Or I can use a single resource and the above code because layer-list bitmap should be intelligent enough to take a high-res image and scale it smaller, minding the image ratio. Sorry, but I'm not going back to revisit this. Native mobile app development should be easier. This was a pointless waste of my time.Chalaza
Fair enough :). Just letting you know best practice but of course each project is different.Malacology
works for me. is there a better way to add some margin, or padding to the image. What I do now is Bitmap bmp3 = Bitmap.createScaledBitmap(bmp, (bmp.getWidth() * toolbar.getHeight() / bmp.getHeight()) - 10, toolbar.getHeight() - 10, true); (if I want a 10...) but not sure if it's a good aproachFrazier
N
1

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.

Necessitous answered 7/6, 2018 at 22:27 Comment(0)
W
0

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>
Wigwam answered 10/3, 2017 at 19:2 Comment(0)
E
0

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"/>
Epigeous answered 6/3, 2018 at 17:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.