Как установить шрифт для меню "Параметры"?

Когда я создаю меню параметров, элементы по умолчанию по умолчанию имеют собственный шрифт "sans". Когда я смотрю коммерческие приложения, они, похоже, делают то же самое. Можно ли установить размер шрифта, цвет или шрифт для пунктов меню Option?

Спасибо заранее.

Ответ 1

Вы можете настроить меню параметров, в том числе:

  • Добавить пользовательский шрифт

  • Изменить размер шрифта

  • Изменить цвет шрифта

  • Установите фон для ресурса, пригодного для рисования (например, изображение, граница, градиент)

Чтобы изменить фон на границу или градиент, вам нужно создать папку ресурса в res, называемую drawable, и внутри нее создать XML или градиент XML границы.

Все это можно сделать программно, как показано ниже:

public class CustomMenu extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public boolean onCreateOptionsMenu(android.view.Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.cool_menu, menu);
        getLayoutInflater().setFactory(new Factory() {
            public View onCreateView(String name, Context context,
                    AttributeSet attrs) {

                if (name.equalsIgnoreCase(
                        "com.android.internal.view.menu.IconMenuItemView")) {
                    try {
                        LayoutInflater li = LayoutInflater.from(context);
                        final View view = li.createView(name, null, attrs);
                        new Handler().post(new Runnable() {
                            public void run() {
                                // set the background drawable if you want that
                                //or keep it default -- either an image, border
                                //gradient, drawable, etc.
                                view.setBackgroundResource(R.drawable.myimage);
                                ((TextView) view).setTextSize(20); 

                                // set the text color
                                Typeface face = Typeface.createFromAsset(
                                        getAssets(),"OldeEnglish.ttf");     
                                ((TextView) view).setTypeface(face);
                                ((TextView) view).setTextColor(Color.RED);
                            }
                        });
                        return view;
                    } catch (InflateException e) {
                        //Handle any inflation exception here
                    } catch (ClassNotFoundException e) {
                        //Handle any ClassNotFoundException here
                    }
                }
                return null;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.AboutUs:
            Intent i = new Intent("com.test.demo.ABOUT");
            startActivity(i);
            break;
        case R.id.preferences:
            Intent p = new Intent("com.test.demo.PREFS");
            startActivity(p);
            break;
        case R.id.exit:
            finish();
            break;
        }
        return false;
    }
}

Не забудьте создать папку с именем menu в папке res, а внутри папки menu создайте XML для своего меню (например, cool_menu.xml), например:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item  android:title="about"android:id="@+id/AboutUs" /> 
    <item android:title="Prefs" android:id="@+id/preferences" /> 
    <item android:title="Exit" android:id="@+id/exit" /> 
</menu>

Тогда вывод будет примерно таким:

enter image description here

Ответ 2

@Android Stack, когда я прочитал ваш ответ, я начал паниковать, думая, что мне придется использовать "factory".

Я немного искал, и я узнал, что вы можете использовать пользовательские представления для элементов меню. Просто назовите setActionView в пункте меню.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, menu);

    // Get the root inflator. 
    LayoutInflater baseInflater = (LayoutInflater)getBaseContext()
           .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // Inflate your custom view.
    View myCustomView = baseInflater.inflate(R.layout.my_custom_view, null);
    menu.findItem(R.id.my_custom_menu_icon).setActionView(myCustomView);


    // If myCustomView has additional children, you might have to inflate them separately here.
    // In my case, I used buttons in my custom view, and registered onClick listeners at this point.

 }

Ваша реализация my_custom_view может быть любым желаемым видом (хотя, возможно, в качестве корневого элемента должна быть LinearLayout). Например, вы можете использовать макет TextView + ImageView, который предлагает @R4j в своем ответе.

В моем примере использования я просто помещал в него объекты Button, а затем полагался на обработчик onButtonClick кнопок для реагирования на события - эффективно перешагивая необходимость обрабатывать их в активности, содержащей меню.

(Большой вопрос, кстати. Спасибо!!)

Ответ 3

Вместо использования XML-ресурса для меню раздуйте его из кода с помощью menu.add и используйте новый SpannableString() для назначения пользовательского шрифта.

Вот пример работы с Android 4.x:

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    ...
    menu.add(Menu.NONE,1234,1,wrapInSpan(getResources().getString(R.string.item_title)))
        .setTitleCondensed(getResources().getString(R.string.item_title));
    ...
}

private CharSequence wrapInSpan(CharSequence value) {
    SpannableStringBuilder sb = new SpannableStringBuilder(value);
    sb.setSpan(MY_TYPEFACE, 0, value.length(), 0);
    return sb;
}

Требуется setTitleCondensed(...) для обхода ошибки в API android: при выборе пункта меню регистрируется событие и используется titleCondensed для записи журнала. Если titleCondensed не определен, он использует title и EventLog.writeEvent сбой при форматировании строки в журнал.

Итак, передаем неформованную CharSequence в обходной ошибке consendedTitle.

Ответ 4

Протестировано и работает как шарм:)

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_feedback_filter, menu);

    for (int i = 0; i < menu.size(); i++) {
        MenuItem mi = menu.getItem(i);
        //for aapplying a font to subMenu ...
        SubMenu subMenu = mi.getSubMenu();
        if (subMenu != null && subMenu.size() > 0) {
            for (int j = 0; j < subMenu.size(); j++) {
                MenuItem subMenuItem = subMenu.getItem(j);
                applyFontToMenuItem(subMenuItem, typeface);
            }
        }
        //the method we have create in activity
        applyFontToMenuItem(mi, typeface);
    }

    return super.onCreateOptionsMenu(menu);
}



private void applyFontToMenuItem(MenuItem mi, Typeface font) {
    SpannableString mNewTitle = new SpannableString(mi.getTitle());
    mNewTitle.setSpan(new CustomTypefaceSpan("", font), 0, mNewTitle.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
    mi.setTitle(mNewTitle);
}

Пользовательский класс span

import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.style.TypefaceSpan;

public class CustomTypefaceSpan extends TypefaceSpan {

    private final Typeface newType;

    public CustomTypefaceSpan(String family, Typeface type) {
        super(family);
        newType = type;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        applyCustomTypeFace(ds, newType);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        applyCustomTypeFace(paint, newType);
    }

    private static void applyCustomTypeFace(Paint paint, Typeface tf) {
        int oldStyle;
        Typeface old = paint.getTypeface();
        if (old == null) {
            oldStyle = 0;
        } else {
            oldStyle = old.getStyle();
        }

        int fake = oldStyle & ~tf.getStyle();
        if ((fake & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }

        if ((fake & Typeface.ITALIC) != 0) {
            paint.setTextSkewX(-0.25f);
        }

        paint.setTypeface(tf);
    }
}

Ответ 5

Я думаю, что Android не поддерживает настройку для меню опций. Но вы можете попробовать другой способ: http://www.codeproject.com/Articles/173121/Android-Menus-My-Way
Таким образом, на самом деле элемент меню представляет собой текстовое изображение и изображение, поэтому вы можете легко изменить шрифт, цвет...

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:padding="4dip"
android:clickable="true"
android:background="@drawable/custom_menu_selector">
<ImageView
    android:id="@+id/custom_menu_item_icon"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:paddingBottom="2dip"
    android:paddingTop="2dip"/>
<TextView
    android:id="@+id/custom_menu_item_caption"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="#ffffff"
    android:textSize="12sp"
    android:gravity="center"/>

Ответ 6

Ни один из ответов выше не работал у меня. Я достиг этого, выполнив следующее решение:

public boolean onPrepareOptionsMenu(Menu menu)
    {
        MenuItem item = menu.findItem(R.id.menu_name);
        item.setTitle(someTextToDisplayOnMenu);
        SpannableString spanString = new SpannableString(item.getTitle().toString());
        spanString.setSpan(new TextAppearanceSpan(context,android.R.style.TextAppearance_Medium), 0,spanString.length(), 0);
        spanString.setSpan(new ForegroundColorSpan(Color.WHITE), 0, spanString.length(), 0); //fix the color to white
        item.setTitle(spanString);
        return true;
    }

Ответ 7

Единственное решение, которое я нашел, это создать настраиваемый диалог, который появляется при нажатии кнопки меню. Макет будет таким:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Mi cuenta"
        android:id="@+id/buttonMyAccount" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Ayuda"
        android:id="@+id/buttonHelp" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Contacto"
        android:id="@+id/buttonContact" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Acerca de"
        android:id="@+id/buttonAbout" />
</LinearLayout>

После этого из класса Activity в методе OnOptionsItemSelected я напишу следующий код:

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

            case R.id.action_settings:
            Dialog dialog = new Dialog(this);
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(R.layout.options_menu);
            dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));

            dialog.show();


            Button buttonMyAccount = (Button) dialog.findViewById(R.id.buttonMyAccount);
            Typeface font = Typeface.createFromAsset(this.getAssets(), "SamsungIF_Rg.ttf");
            buttonMyAccount.setTypeface(font);
            buttonMyAccount.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent itMyAccount = new Intent(getBaseContext(), AccountActivity.class);
                    startActivity(itMyAccount);
                }
            });


            Button buttonHelp = (Button) dialog.findViewById(R.id.buttonHelp);
            buttonHelp.setTypeface(font);
            buttonHelp.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent itAssistant = new Intent(getBaseContext(), AssistantPagerActivity.class);
                    startActivity(itAssistant);
                }
            });


            Button buttonContact = (Button) dialog.findViewById(R.id.buttonContact);
            buttonContact.setTypeface(font);
            buttonContact.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent itContact = new Intent(getBaseContext(), ContactActivity.class);
                    startActivity(itContact);
                }
            });

            Button buttonAbout = (Button) dialog.findViewById(R.id.buttonAbout);
            buttonAbout.setTypeface(font);
            buttonAbout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent itAbout = new Intent(getBaseContext(), AboutActivity.class);
                    startActivity(itAbout);
                }
            });


            Window window = dialog.getWindow();
            WindowManager.LayoutParams wlp = window.getAttributes();
            wlp.gravity = Gravity.RIGHT | Gravity.TOP;
            wlp.y = getSupportActionBar().getHeight();
            wlp.width = 300;
            wlp.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND;
            window.setAttributes(wlp);


            return true;

        default:
            return super.onOptionsItemSelected(item);

    }
}