Название центра панели инструментов Android и собственный шрифт
Я пытаюсь найти правильный способ использования специального шрифта для заголовка панели инструментов и сосредоточить его на панели инструментов (требование клиента).
На данный момент я использую старый добрый ActionBar, и я устанавливал заголовок для пустого значения, а с помощью setCustomView
помещал свой собственный шрифт TextView и setCustomView
его с помощью ActionBar.LayoutParams.
Есть ли лучший способ сделать это? Использование новой панели инструментов в качестве моего ActionBar.
- Изменение цвета строки состояния с помощью AppCompat ActionBarActivity
- Как сделать панель инструментов прозрачной?
- Удалите большое дополнение после значка гамбургера (меню) на панели инструментов Android?
- Управление навигационной панелью и обратной кнопкой панели инструментов из fragmentа в андроиде
- Android Lollipop, добавить всплывающее меню из заголовка на панели инструментов
- Панель инструментов lollipop для Android: как скрыть / показать панель инструментов при прокрутке?
- Как использовать SearchView в панели инструментов Android
- Прокладка панели инструментов Android API 21
- Создание кнопки в панели инструментов Android
- Добавить представления ниже панели инструментов в CoordinatorLayout
- Добавить высоту / тень на панели инструментов для устройств с предварительным леоптипом
- Эта активность уже имеет панель действий, предоставляемую декором windows
- Изменить цвет панели инструментов в Appcompat 21
Чтобы использовать пользовательский заголовок на Toolbar
все, что вам нужно сделать, это помнить, что Toolbar
– просто причудливая ViewGroup, поэтому вы можете добавить собственный заголовок так:
Это означает, что вы можете TextView
но вы хотите, потому что это обычный TextView
. Поэтому в вашей деятельности вы можете получить доступ к названию так:
Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar_top); TextView mTitle = (TextView) toolbarTop.findViewById(R.id.toolbar_title);
Заголовок ToolBar является стильным. Любая настройка, которую вы делаете, должна быть сделана в теме. Я приведу вам пример.
Расположение панели:
Стили:
у нас нет прямого доступа к заголовку ToolBar TextView, поэтому мы используем reflection для доступа к нему.
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; }
Это просто, чтобы помочь присоединиться ко всем частям, используя @ MrEngineer13 ответ с комментариями @Jonik и @Rick Sanchez с правильным приказанием, чтобы помочь достичь цели по центру!
Макет с TextAppearance.AppCompat.Widget.ActionBar.Title
:
Способ достижения правильного порядка:
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);
Пожалуйста, не забудьте прочесть @ MrEngineer13 ответ !!!
Вот пример проекта ToolbarCenterTitleSample
Надеюсь помочь кому-то еще;)
Ниже приведен подход, основанный на заголовке текста, для поиска экземпляра TextView
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; }
Никто не упомянул об этом, но для Toolbar
есть некоторые атрибуты:
app:titleTextColor
для установки цвета текста заголовка
app:titleTextAppearance
для установки внешнего вида заголовка
app:titleMargin
для установки поля
И есть другие специфические поля, такие как marginStart
и т. Д.
Определите следующий 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; } }
… а затем просто используйте его вместо обычной Toolbar
следующим образом:
Вам все еще нужны эти 2 строки кода в вашей Activity
(как со стандартной 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);
Это оно! Вам не нужно скрывать стандартный выровненный по левому краю заголовок, не нужно дублировать один и тот же код XML много раз и т. Д., Просто используйте CenteredToolbar
как если бы это была Toolbar
умолчанию. Вы также можете настроить свой собственный шрифт программно, так как теперь у вас есть прямой доступ к TextView
. Надеюсь это поможет.
Я использую это решение:
static void centerToolbarTitle(@NonNull final Toolbar toolbar) { final CharSequence title = toolbar.getTitle(); final ArrayList 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); } }
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); } }
Без панели инструментов TextView мы можем настроить шрифт, используя приведенный ниже код
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); }
Планировка:
Код:
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);
Вы можете использовать следующее:
Я не знаю, было ли что-то изменено в библиотеке appcompat, но это довольно тривиально, не нужно размышлять.
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; } }
Решение, которое я использовал для этой проблемы:
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; } } } }
Для центра тяжести я думаю, что было бы необходимо изменить параметры макета на match_parent по горизонтали, а затем:
tv.setGravity(Gravity.CENTER);
Я решил это решение, и это следующие коды:
И вы можете изменить название / метку в Activity, напишите нижеприведенные коды:
Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar_top);
TextView mTitle = (TextView) toolbarTop.findViewById (R.id.toolbar_title); mTitle.setText ( “@ строка / ….”);
Так как Toolbar
android.support.v7.appcompat 24.2
имеет метод setTitleTextAppearance
и вы можете установить его шрифт без внешнего textview
.
создать новый стиль в styles.xml
и использовать его
mToolbar.setTitleTextAppearance(this, R.style.RobotoBoldTextAppearance);
Очень быстрый и простой способ установки пользовательского шрифта – использовать пользовательское titleTextAppearance
с fontFamily
:
Добавить в стили.xml :
В папке res создайте папку шрифтов (Ex: varela_round_regular.ttf )
Прочтите официальное руководство, чтобы узнать больше https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html
Несмотря на то, что добавление текстового представления на панель инструментов может решить проблему ограничения стиля заголовка, есть проблема с ним. Поскольку мы не добавляем его в макет, у нас нет слишком большого контроля над его шириной. Мы можем либо использовать wrap_content, либо match_parent.
Теперь рассмотрим сценарий, в котором у нас есть searchView как кнопка на правом краю панели инструментов. Если содержание заголовка больше, оно будет отображаться поверх кнопки, скрывающей его. Нет способа контролировать это, не устанавливая ширину метки, и это то, что вы не хотите делать, если хотите иметь отзывчивый дизайн.
Итак, вот решение, которое сработало для меня, которое немного отличается от добавления текстового представления на панель инструментов. Вместо этого добавьте панель инструментов и текстовое представление в относительный макет и убедитесь, что текстовое представление находится поверх панели инструментов. Затем мы можем использовать соответствующие поля и убедиться, что текстовое представление отображается там, где мы хотим, чтобы оно отображалось.
Убедитесь, что панель инструментов не отображает заголовок.
Вот XML для этого решения:
Решает проблему @ ankur-chaudhary, упомянутую выше.
Пытаться
@Override public void onBackPressed() { if(getTitle().equals(getResources().getString(R.string.app_name))) { super.onBackPressed();} else { //set visiblity } }
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(); } }); } } }
Настройка android:gravity="center"
работал для меня
Ничего не устраивает. Панель инструментов – это, в основном, ViewGroup
все, что вам нужно сделать, – это установить гравитацию элементов в ней.
Я провел несколько дней в поисках универсального решения. Моя панель инструментов работает с меню Android и значком навигации.
Сначала вам нужно создать собственный class панели инструментов. Этот class должен вычислять позиции по центру (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(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) }
Во-вторых, вам нужно создать панель инструментов макета:
Это все
Обновление из ответа @ MrEngineer13: для выравнивания центра заголовка в любом случае, включая значок гамбургера, меню опций, вы можете добавить FrameLayout
на панели инструментов, как это:
Ни один из вышеперечисленных решений не работал для меня. Я обнаружил, что только переопределив поведение по умолчанию в Actionbar, я могу реализовать свое пользовательское представление.
Попробуйте этот код:
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); getSupportActionBar().setCustomView(R.layout.toolbar_home);
Typeface face= Typeface.createFromAsset(getAssets(), "font/font.ttf"); // your custom font Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTypeface(face); setSupportActionBar(toolbar);
Другой учебник:
- Пример панели инструментов Android
- Использование пользовательского шрифта в Android
- Учебное пособие по ActionBar с примером