2010-11-09 3 views
32

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

Заранее благодарен.

+0

Пытаюсь что-то подобное. Но никакого успеха. Но вот некоторая ссылка на чтение. http://developer.android.com/guide/topics/ui/menus.html#options-menu. Рекомендуется не беспокоить данные по умолчанию. Но можно создать представление для настройки. –

ответ

1

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

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

63

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

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

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

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

  4. Набор фон с растяжимой ресурса (например, изображение, граница, градиент)

Для изменения фона на границе или градиент вы должны создать папку ресурсов в 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> 

Тогда выход будет что-то вроде этого:

+0

Привет, возможно ли изменить шрифт динамически? Я имею в виду, вместо того, чтобы устанавливать шрифт в OnCreateOptionsMenu(), я хотел бы установить его в OnPrepareOptionsMenu(), так что в разное время в моем меню будут разные шрифты. Является ли это возможным? –

+0

Или, если задать разные шрифты для разных пунктов меню, тогда я могу установить шрифт в OnCreateOptionsMenu(), и в меню OnPrepareOptionsMenu() появятся необходимые меню, видимые и ненужные. Является ли это возможным? –

+2

Привет, когда я запускаю код выше (слегка измененный, см. Следующий комментарий), внешний вид элементов меню изменяется только при первом открытии меню параметров. Если я выйду из меню опций (выбрав опцию, нажав кнопку «Назад» или нажав кнопку меню), а затем снова откройте ее, внешний вид будет восстановлен по умолчанию. Как я могу сделать изменения постоянными? Я разрабатываю API уровня 8. –

4

Вместо использования 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: при выборе пункта меню события регистрируется и использовать titleCondensed для напишите журнал. Если titleCondensed не определен, используется title, а EventLog.writeEvent сбой при форматировании строки в журнал.

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

+0

Это не работает, когда меню хранится как showAsAction = "always". Может ли кто-нибудь решить проблему с этим кодом? –

0

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

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

После этого из класса активности, в «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); 

    } 
} 
8

@Android стеку, когда я прочитал Ваш ответ Я начал паниковать, думая, что мне придется использовать «фабрику».

Я немного искал, и я узнал, что вы можете использовать пользовательские представления для пунктов меню. Просто позвоните по номеру 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 для реагирования на события - эффективно отшатывая необходимость обрабатывать их в активности, содержащей меню.

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

+4

Я хотел бы добавить к этому ответу, что, когда мы меняем представление в меню, обратный вызов onOptionsItemSelected не будет вызываться, когда пользователь нажимает на элемент меню, поэтому нам нужно будет добавить onClickListener в наш customView. – Sherekan

2

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

@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); 
} 

класс пользовательского диапазона

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); 
    } 
} 
+0

Он работает в Android 6.Thanks – sahulab

+0

Он работает для меню переполнения, но не для меню действий. Я что-то упускаю? – DalveerSinghDaiya

2

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

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; 
    } 
Смежные вопросы