35 votes

Comment définir une police pour le menu Options ?

Lorsque je crée un menu d'options, les éléments semblent utiliser par défaut la police "sans" native. Lorsque je regarde les applications commerciales, elles semblent faire la même chose. Est-il possible de définir la taille de la police, le poids de la couleur ou la police de caractères pour les éléments du menu Options ?

Merci d'avance.

65voto

Android Stack Points 1981

Vous pouvez personnaliser le menu des options, notamment :

  1. Ajouter une police personnalisée

  2. Modifier la taille de la police

  3. Modifier la couleur de la police

  4. Définir l'arrière-plan d'une ressource Drawable (par exemple, une image, une bordure, un dégradé)

Pour changer l'arrière-plan en une bordure ou un dégradé, vous devez créer un dossier de ressources dans le dossier res appelé drawable et, à l'intérieur de celui-ci, créez le XML de bordure ou le XML de dégradé.

Tout cela peut être fait par programme, comme indiqué ci-dessous :

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

N'oubliez pas de créer un dossier appelé menu sur res et dans le dossier menu créez un XML pour votre menu (par ex. cool_menu.xml ) comme celui-ci :

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

Le résultat sera alors quelque chose comme ceci :

enter image description here

10voto

dsg Points 4334

@Android Stack, quand j'ai lu votre réponse j'ai commencé à paniquer en pensant que je devrais utiliser une "factory".

J'ai cherché un peu, et j'ai appris que vous pouvez utiliser des vues personnalisées pour les éléments de menu. Il suffit d'appeler setActionView sur l'élément de menu.

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

 }

Votre mise en œuvre de my_custom_view peut être n'importe quelle vue que vous voulez (bien qu'elle doive avoir une LinearLayout comme élément racine). Par exemple, vous pouvez utiliser la disposition TextView + ImageView que @R4j propose dans sa réponse.

Dans mon cas, je mets simplement Button dans le menu, puis s'est appuyé sur l'outil onButtonClick des boutons pour répondre aux événements, évitant ainsi de devoir les gérer dans l'activité contenant le menu.

(Excellente question, d'ailleurs. Merci !)

4voto

HarikrishnanVH Points 31

Au lieu d'utiliser la ressource XML pour le menu, gonflez-le à partir du code en utilisant menu.add et utilisez new SpannableString() pour attribuer une police personnalisée.

Voici un exemple fonctionnant sur 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;
}

Le site setTitleCondensed(...) est nécessaire pour contourner un bogue de l'API Android : lorsqu'un élément de menu est sélectionné, l'événement est enregistré et utilise l'attribut titleCondensed pour écrire le journal. Si le titleCondensed n'est pas définie, elle utilise l'option title et le EventLog.writeEvent se plante à chaque fois que la chaîne à enregistrer est formatée.

Ainsi, le passage d'un CharSequence non formaté dans la fonction consendedTitle contourner le bogue.

1voto

R4j Points 2884

Je pense qu'Android ne supporte pas la personnalisation du menu option. Mais vous pouvez essayer un autre moyen : http://www.codeproject.com/Articles/173121/Android-Menus-My-Way
De cette façon, l'élément de menu est à la fois une vue de texte et une vue d'image, de sorte que vous pouvez facilement changer la police, la couleur...

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

0voto

Javier Roberto Points 159

La seule solution que j'ai trouvée est de créer une boîte de dialogue personnalisée qui apparaît lorsque vous appuyez sur le bouton de menu. La mise en page serait la suivante :

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

Ensuite, dans la classe Activity, dans la méthode 'OnOptionsItemSelected', j'écris le code suivant :

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

    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X