工具栏图像居中

70

使用最后一个android.support.v7.widget.Toolbar,我想将图像居中在工具栏中,但它始终停留在左侧。

对我来说,最好的方法是使用toolbar.setLogo()方法,并将logo居中,但我没有找到任何方法来实现它。

我为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>

有没有可能在工具栏上添加一张图像(标志)并将其居中?可以通过编程或布局实现吗?


你可以这样做,但是你应该阅读指南。 Android不使用在工具栏中心对齐的标志。 - Gabriele Mariotti
https://dev59.com/6VwX5IYBdhLWcg3w2igu - Aditya Vyas-Lakhan
8个回答

142

工具栏只是一个ViewGroup,您可以根据需要自定义它。

尝试这个:

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

这应该将您的imageView置于工具栏中心。


如何通过编程方式更改设置图标?请帮忙。 - Anand Savjani
@AnandSavjani 我所做的是在ImageView上设置了一个ID,然后在我的Activity中将一个ImageView变量分配给它。然后简单地说,toolbarID.SetImageResource(Resource.Drawable.logo); - MikeOscarEcho
15
据我所见,工具栏(Toolbar)继承自ViewGroup类,因此android:layout_gravity属性无效。也许是我做错了什么,但它不起作用。 - Goltsev Eugene
1
我已经将 layout_width="match_parent" 属性添加到 ImageView 中,它可以正常工作。 - Wojtek

35

如果您有任何看法,但无法使标志居中,那是因为居中是基于剩余空间而不是整个工具栏的。

为了保证标志居中,请尝试使用layer-list作为工具栏的背景,而不是尝试将图像用作视图。

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>

工具栏背景

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

这将确保标志居中,并具有特定的背景颜色。


2
这是一个更好的答案。 - Rony Tesler
7
你如何使用drawable调整大小? - Lion789
我注意到你在另一个问题上留了评论,所以我猜你还没有找到答案。如果你找不到其他解决方案,也许重新创建一个特定大小的图像是最好的选择。 - Blueberry
1
有没有办法调整位图的大小?因为当我这样做时,它会使我尝试使用的图像非常巨大且无法在工具栏中使用... - Sakiboy

9
这不是最佳解决方案,但这是一种权宜之计,即使您有向上按钮或菜单项也可以使用。
尝试
<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>

不错的答案 - 易于理解。我已经在我的答案中更新了一些增强功能,以适应2018年的需求(https://dev59.com/zF4c5IYBdhLWcg3wyMwB#53373773)- 如果您想将这些更改复制到您的答案中,我很乐意删除我的答案,因为它不再添加任何有用的内容。 - Richard Le Mesurier

6
我喜欢Ruben Yoo的回答方式,因为它简单易懂。这种方法明确易懂,易于跟踪,并将所有代码更改保持在一起。
以下是一些小改进后的更新版本:
<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>

变更:

  1. 引入了 AppBarLayout 父布局
  2. 为框架和工具栏提供了明确的尺寸 ?attr/actionBarSize
  3. ImageView 的宽度和高度与父容器相匹配
  4. 将标志调整为 centerInside

2
我遇到了类似的问题。我尝试使用Blueberry建议的layer-list方法,但是一旦我放入一个高分辨率的标志性资产,解决方案就不再起作用了。在layer-list中,位图存在一个错误:它会将较小的图像放大以适应空间,但不会缩小较大的图像。因此,只要您愿意使用看起来有颗粒感/像素化的微小图像,当它们被放大时,layer-list就可以正常工作。
为了解决这个问题并获得一个居中的高分辨率标志,我完全从Toolbar中删除了android:background属性,将android:background="?attr/colorPrimary"添加到我的AppBarLayout父级中,然后将这个可怕的代码扔进了我的Activity的onCreate方法中:
    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);
                }
            }
        });
    }

它的工作原理是创建一个与工具栏大小相同的画布和一个按比例缩放的标志版本,在画布中心绘制新调整大小的标志,最后将正在绘制的位图设置为操作栏的背景。优点是该方法允许您完全控制位置、大小等,而不仅限于 XML 中能做的内容。但是它会被频繁调用,这意味着存在性能影响。如果设计团队要求你使用背景标志并浪费五个小时寻找上述解决方案,那就没有关于性能的问题了-你只是想让它工作。上面的代码有很强的不确定性气息。我会让比我更擅长Android开发的人指出“我做错了”的地方,并修复上述代码中存在的任何性能问题/错误。这并不改变层列表位图损坏的事实,这是一种应该不存在的 hack(也不应该存在)来解决 Android 中愚蠢的 bug。

在我看来,最好的方法是采用XML方法,并使用多个图像尺寸进行缩放。这是一种相当标准的Android方法。不确定是否遇到了相同的问题? - Blueberry
设备形状和大小各不相同,因此,除非您愿意为一个标志而传递200MB的二进制文件,否则没有办法处理每个设备。 - maddog
我认为你需要担心的只是密度问题,其中只有六个你需要处理。请参阅此处以获取有关如何支持多个密度的更多信息。https://developer.android.com/guide/practices/screens_support.html#overview - Blueberry
或者我可以使用单个资源和上面的代码,因为图层列表位图应该足够智能,可以将高分辨率图像缩小,并注意图像比例。抱歉,但我不会回去重新审查这个。本机移动应用程序开发应该更容易。这是我时间的无意义浪费。 - maddog
好的,没问题。只是让您知道最佳实践,当然每个项目都不同。 - Blueberry
适用于我。是否有更好的方法来为图像添加一些边距或填充。我现在所做的是:Bitmap bmp3 = Bitmap.createScaledBitmap(bmp,(bmp.getWidth() * toolbar.getHeight() / bmp.getHeight()) - 10,toolbar.getHeight() - 10,true);(如果我想要一个10...)但不确定这是否是一个好方法。 - OWADVL

1
如果用户设置了以下内容: activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); activity.getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_iconmenu); 然后进行一些操作:
<Toolbar ... >
   <ImageView ...>
   </ImageView>
</Toolbar>

如果主页按钮占用了一些布局空间,那么工具栏内的图像也不会居中。图像的水平中心将偏移主页图标的宽度。因此,最好的解决方案是:
1.从原始图像创建9-patch png。
2.使用layer-list作为示例,通过xml创建可绘制的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>

然后将toolbar_background资源设置为Toolbar元素的背景:
<Toolbar android:background="toolbar_background" ...>
</Toolbar>

这是所有内容。

0

你可以使用这段代码:

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


0
如果您需要在工具栏中居中一个比图像更复杂的布局,这是我放置在Activity的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);
                    }
                }
            }
    );

当调用onLayoutChange时,您的布局宽度已经确定,因此您只需将其推向中心。

注意:仅在工具栏未居中时(请参见if条件)才居中工具栏,否则此回调将在无限循环中重新调用。

XML文件将如下所示:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接