【发布时间】:2015-06-09 05:13:08
【问题描述】:
我是第一次在我的项目中使用 ToolBar,所以我不知道如何在 android 中自定义工具栏。我需要将标题居中放在工具栏上,请告诉我该怎么做。
提前致谢。
【问题讨论】:
我是第一次在我的项目中使用 ToolBar,所以我不知道如何在 android 中自定义工具栏。我需要将标题居中放在工具栏上,请告诉我该怎么做。
提前致谢。
【问题讨论】:
在工具栏居中添加一个 TextView 的问题是在工具栏中添加菜单项会偏移居中的文本。
为了解决这个问题,我将文本分层放在工具栏的顶部,而不是在里面。这样无论你添加多少图标,它都不会偏移居中的文本:
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar">
</android.support.v7.widget.Toolbar>
<TextView
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"/>
</RelativeLayout>
</android.support.design.widget.AppBarLayout>
这样就不需要任何额外的逻辑来补偿工具栏上后退按钮/溢出菜单/搜索图标等的偏移间距,因为居中的文本在它上面,而不是在它里面。
【讨论】:
请记住,Toolbar 只是一个 ViewGroup 和其他人一样。所以你可以把Views 塞进去。在您的情况下,您需要在Toolbar 中使用TextView。
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Some Fancy Title"
android:gravity = "center"
android:id="@+id/toolbar_title" />
</android.support.v7.widget.Toolbar>
现在,将Toolbar 设置为您的操作栏,首先检索它,然后使用setSupportActionBar()。
由于TextView 的重力设置为center,因此文本必须居中。
【讨论】:
Toolbar 设置gravity 和layout_gravity。
您可以通过包装标题和级别右填充来强制工具栏居中,该填充具有标题的默认左填充。然后将背景颜色放在工具栏的父级上,这样被包装标题剪掉的部分是相同的颜色(在我的例子中是白色):
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="wrap_content"
android:layout_height="56dp"
android:layout_gravity="center_horizontal"
android:paddingEnd="15dp"
android:paddingRight="15dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:titleTextColor="@color/black"/>
</android.support.design.widget.AppBarLayout>
【讨论】:
ToolBar 是一个视图组。所以要 居中对齐文本使用
app_bar.xml
<?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/in.chabu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:theme="@style/ToolBarTheme"
android:minHeight="?attr/actionBarSize">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_activity_sign_up"
android:layout_gravity="center"
android:id="@+id/toolbar_title"
android:textStyle="bold"
android:textColor="@android:color/white"/>
</android.support.v7.widget.Toolbar>
activity_sign_up
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="in.chabu.activities.SignUpActivity" >
<include
android:id="@+id/tool_bar"
layout="@layout/app_bar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tool_bar"
android:text="@string/hello_world" />
</RelativeLayout>
活力
public class SignUpActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
}
【讨论】:
仅在Toolbar 中放置另一个TextView 不足以使标题相对于屏幕居中,其位置将取决于工具栏中的其他项目(后退按钮、菜单项)。
要使标题居中,您可以手动设置其位置:
扩展android.support.v7.widget.Toolbar 类并进行以下更改:
TextView
onLayout() 并将 TextView 位置设置为居中 (titleView.setX((getWidth() - titleView.getWidth())/2))setTitle() 其中将标题文本设置为新文本视图在布局中你可以像这样使用这个类:
<com.example.CenteredToolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ToolbarTheme"/>
此外,要使新标题文本看起来像标准标题,您应该将titleTextAppearance 样式应用于新的TextView (titleView.setTextAppearance(context, textAppearanceStyleResId))。
【讨论】:
onLayout 方法并在构造函数中自定义titleView TextView。
toolbar.setTitle()。我想在它上面添加另一个文本视图。我的目标是在打开抽屉时在标题之间制作动画。我的抽屉必须在工具栏下,这就是我尝试这样做的原因。顺便说一句,谢谢您的回复。
super.setTitle() 的情况下覆盖了 setTitle() 方法。
super.setTitle(title)这一行,你会一一看到两个相同的TextView。您可以在onLayout() 中将位置设置为新的titleView。 protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); TextView originalTitle = findOriginalTitleView(); if (originalTitle != null) { titleView.setX(originalTitle.getX()); titleView.setY(originalTitle.getY()); } } where findOriginalTitleView() 方法只是遍历所有孩子并尝试找到原始 textView
最终的 UI 如下所示: 对于我的项目,我在左侧有导航图标,在右侧有菜单(超过 1 个),并且想将标题放在中心。
我有setSupportActionBar(toolbar) 和_actionBar.setCustomView(R.layout.actionbar_filter);。
我的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lib_action_bar_filter_view_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center">
<TextView
android:id="@id/lib_action_bar_filter_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:textColor="@android:color/white"
android:textSize="15sp"/>
</RelativeLayout>
我的工具栏扩展了 android.support.v7.widget.Toolbar,然后(某种硬代码)测量 RelativeLayout 的大小,最后将其布置在水平中心。
/**
* Customized the <code>RelativeLayout</code> inside the <code>Toolbar</code>.
* Because by default the custom view in the <code>Toolbar</code> cannot set
* width as our expect value. So this class allows setting the width of the
* <code>RelativeLayout</code> to take up any percentage of the screen width.
*/
public class CenteredToolbar extends Toolbar {
private static final double WIDTH_PERCENTAGE = 0.8;
private TextView titleView;
public CenteredToolbar(Context context) {
this(context, null);
}
public CenteredToolbar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, android.support.v7.appcompat.R.attr.toolbarStyle);
}
public CenteredToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View view = this.getChildAt(i);
if (view instanceof RelativeLayout) {
int width = getMeasuredWidth();
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.width = (int) (width * WIDTH_PERCENTAGE);
view.setLayoutParams(layoutParams);
break;
}
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View view = this.getChildAt(i);
if (view instanceof RelativeLayout) {
forceTitleCenter(view);
break;
}
}
}
/**
* Centering the layout.
*
* @param view The view to be centered
*/
private void forceTitleCenter(View view) {
int toolbarWidth = getMeasuredWidth();
int relativeLayoutWidth = view.getMeasuredWidth();
int newLeft = (int) (toolbarWidth - relativeLayoutWidth) / 2;
int top = view.getTop();
int newRight = newLeft + relativeLayoutWidth;
int bottom = view.getBottom();
view.layout(newLeft, top, newRight, bottom);
}
}
附加我的工具栏布局。也许你不需要这个,我只是在这里粘贴以供参考:
<?xml version="1.0" encoding="utf-8"?>
<com.chinalwb.CenteredToolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/vmosolib_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:contentInsetEnd="0dp"
/>
【讨论】:
当你有 Home 或 Up 按钮和居中的标题,并且标题不再居中并且稍微向右移动一点时,将你的 textview 设置为 width=wrap_content 和 layout_gravity=center
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
【讨论】:
我稍微修改了Toolbar 源以使标题中心对齐。
public class CenterTitleToolbar extends Toolbar {
private AppCompatTextView titleTextView;
public CenterTitleToolbar(Context context) {
super(context);
}
public CenterTitleToolbar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public CenterTitleToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void setTitle(CharSequence title) {
if (!TextUtils.isEmpty(title)) {
if (titleTextView == null) {
final Context context = getContext();
titleTextView = new AppCompatTextView(context);
titleTextView.setSingleLine();
titleTextView.setEllipsize(TextUtils.TruncateAt.END);
titleTextView.setTextAppearance(context, R.style.TextAppearance_MaterialComponents_Headline6);
final LayoutParams lp = generateDefaultLayoutParams();
lp.gravity = Gravity.CENTER;
titleTextView.setLayoutParams(lp);
}
if (titleTextView.getParent() != this) {
addSystemView(titleTextView);
}
} else if (titleTextView != null && titleTextView.getParent() == this) {
removeView(titleTextView);
}
if (titleTextView != null) {
titleTextView.setText(title);
}
}
private void addSystemView(View v) {
final ViewGroup.LayoutParams vlp = v.getLayoutParams();
final LayoutParams lp;
if (vlp == null) {
lp = generateDefaultLayoutParams();
} else if (!checkLayoutParams(vlp)) {
lp = generateLayoutParams(vlp);
} else {
lp = (LayoutParams) vlp;
}
addView(v, lp);
}
}
文本样式TextAppearance_MaterialComponents_Headline6 包含在新的Android Material library 中。
【讨论】:
generateDefaultLayoutParams 返回什么?
protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); } generateDefaultLayoutParams 方法在超类中声明。
基于@LiuWenbin_NO,
我已经创建了一个自定义工具栏,它不需要任何额外的视图来在 textview 中居中标题,
import android.content.Context
import android.util.AttributeSet
import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import android.view.Gravity
class CenteredToolbar(context: Context, attrs: AttributeSet?, defStyleAttr: Int):
Toolbar(context, attrs, defStyleAttr) {
constructor(context: Context) : this(context, null, 0)
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, androidx.appcompat.R.attr.toolbarStyle)
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
val childCount = childCount
for (i in 0 until childCount) {
val view = this.getChildAt(i)
if (view is TextView) {
forceTitleCenter(view,l, r)
break
}
}
}
/**
* Centering the layout.
*
* @param view The view to be centered
*/
private fun forceTitleCenter(view: TextView, l: Int, r: Int) {
val top = view.getTop()
val bottom = view.getBottom()
view.layout(l, top, r, bottom)
navigationIcon?.let{
view.setPadding(it.intrinsicWidth,0,0,0)
}
view.gravity = Gravity.CENTER
}
}
<ui.customView.CenteredToolbar
android:id="@+id/apd_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:navigationIcon="@drawable/ic_search"
app:title="Check Title"
app:elevation="4dp"/>
【讨论】:
你可以使用MaterialToolbar,它在android上支持material:1.4.0-alpha02
implementation 'com.google.android.material:material:1.4.0-alpha02'
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:titleCentered="true" />
【讨论】:
工具栏是一个视图组,因此您可以在其中创建布局。 请按照以下步骤操作
1-在工具栏中创建一个文本视图 2-让你的 textview 重心
<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" >
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/profile_image"
android:layout_width="44dp"
android:layout_height="55dp"
android:src="@drawable/profile"
app:civ_border_color="@color/secondary_text"
app:civ_border_width="2dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title"
android:gravity="center"
style="@style/Base.TextAppearance.AppCompat.Widget.ActionBar.Title"
/>
</android.support.v7.widget.Toolbar>
【讨论】:
我不完全理解你的问题..但我找到了这样的解决方案
要在工具栏中使用自定义标题,您只需记住工具栏只是一个精美的 ViewGroup,因此您可以像这样添加自定义标题:
<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="Toolbar Title"
android:layout_gravity="center"
android:id="@+id/toolbar_title" />
</android.support.v7.widget.Toolbar>
这意味着您可以随意设置 TextView 的样式,因为它只是一个常规的 TextView。因此,在您的活动中,您可以像这样访问标题:
Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar_top);
TextView mTitle = (TextView) toolbarTop.findViewById(R.id.toolbar_title);
【讨论】:
在工具栏内使用自定义标题(带重心)
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:animateLayoutChanges="true"
android:backgroundTint="@color/colorPrimary"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:minHeight="?android:attr/actionBarSize"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:titleTextAppearance="@style/Toolbar.TitleText" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/toolbar_title"
android:text="Title"
android:layout_gravity="center"/>
</android.support.v7.widget.Toolbar>
【讨论】:
最好的解决方案是在ToolBar 中使用嵌套的TextView,然后将layout_width 和layout_height 设置为wrap_content。然后将layout_gravity 设置为center。这样它就不会被toolbar中的其他图标所抵消。
【讨论】:
public void centerTitleAndSubtitle(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);
} 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);
}
}
// Restore title and subtitle
toolbar.setTitle(originalTitle);
toolbar.setSubtitle(originalSubtitle);
}
}
如果您还想要自定义字体,请在此处查看我的其他答案:https://stackoverflow.com/a/35723158/445548
【讨论】:
这完成了我的工作!
Toolbar toolbar = findViewById(R.id.mytoolbar);
TextView titleText = getProperties(new TextView(this));
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
frameLayout.addView(titleText);
toolbar.addView(frameLayout);
setSupportActionBar(toolbar);
设置TextView属性的方法
private TextView getProperties(TextView titleText){
titleText.setText(wallpaperName);
titleText.setTextColor(Color.WHITE);
titleText.setTextSize(18f);
titleText.setShadowLayer(2f,2f,2f,Color.BLACK);
titleText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); // CENTER ALIGNMENT
return titleText;
}
【讨论】:
在 koltin 中,只有一个功能可以帮助您...
private fun centerTitle(toolbar: Toolbar) {
// Save current title
val originalTitle: CharSequence = toolbar.title
// Temporarily modify title
toolbar.title = "title"
for (i in 0 until toolbar.childCount) {
val view: View = toolbar.getChildAt(i)
if (view is TextView) {
if (view.text == "title") {
// Customize title's TextView
val params: Toolbar.LayoutParams = Toolbar.LayoutParams(
Toolbar.LayoutParams.WRAP_CONTENT,
Toolbar.LayoutParams.MATCH_PARENT
)
params.gravity = Gravity.CENTER_HORIZONTAL
view.layoutParams = params
}
}
// Restore title
toolbar.title = originalTitle
}
}
【讨论】:
对于 kotlin 用户 来自@user2137020 的回答:
package com.example.safetyofficer.view
import android.content.Context
import android.util.AttributeSet
import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import com.example.safetyofficer.R
class CustomToolbar @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = R.attr.toolbarStyle
) :
Toolbar(context, attrs, defStyleAttr) {
private val titleView: TextView = TextView(getContext())
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
titleView.x = (width - titleView.width) / 2.toFloat()
}
override fun setTitle(title: CharSequence) {
titleView.text = title
}
init {
val textAppearanceStyleResId: Int
val a = context.theme.obtainStyledAttributes(
attrs,
intArrayOf(R.attr.titleTextAppearance),
defStyleAttr,
0
)
textAppearanceStyleResId = try {
a.getResourceId(0, 0)
} finally {
a.recycle()
}
if (textAppearanceStyleResId > 0) {
titleView.setTextAppearance(textAppearanceStyleResId)
}
addView(titleView, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT))
}
}
【讨论】:
您可以使用 MaterialToolbar 并在 xml 中设置 app:titleCentered="true"。
【讨论】:
您可以将此代码插入到您的代码中
SupportActionBar.Title = "title";
【讨论】: