No he encontrado una manera de hacer esto. Es posible?

InformationsquelleAutor notme | 2011-01-27

5 Comentarios

  1. 146

    Bueno, no podía entender cómo hacer con las clases para que se amplié la TypefaceSpan en mi propio ahora trabaja para mí. Aquí es lo que yo hice:

    package de.myproject.text.style;
    
    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);
        }
    }
    • De alguna manera esto no funciona en los botones. Alguna idea de por qué?
    • ¿qué debería pasar a la variable de cadena de la familia en este constructor CustomTypefaceSpan(Cadena de familia de tipo de Letra, tipo) {} ???
  2. 97

    Mientras notme tiene esencialmente la idea de derecho, la solución dada es un poco chapucero como «la familia» se vuelve redundante. También es ligeramente incorrecta porque TypefaceSpan es uno de los especiales que abarca Android conoce y espera de ciertos comportamientos con respecto a la ParcelableSpan interfaz (que notme la subclase no lo hace correctamente, ni es posible, implementar).

    De una forma más simple y más exacta de la solución sería:

    public class CustomTypefaceSpan extends MetricAffectingSpan
    {
        private final Typeface typeface;
    
        public CustomTypefaceSpan(final Typeface typeface)
        {
            this.typeface = typeface;
        }
    
        @Override
        public void updateDrawState(final TextPaint drawState)
        {
            apply(drawState);
        }
    
        @Override
        public void updateMeasureState(final TextPaint paint)
        {
            apply(paint);
        }
    
        private void apply(final Paint paint)
        {
            final Typeface oldTypeface = paint.getTypeface();
            final int oldStyle = oldTypeface != null ? oldTypeface.getStyle() : 0;
            final int fakeStyle = oldStyle & ~typeface.getStyle();
    
            if ((fakeStyle & Typeface.BOLD) != 0)
            {
                paint.setFakeBoldText(true);
            }
    
            if ((fakeStyle & Typeface.ITALIC) != 0)
            {
                paint.setTextSkewX(-0.25f);
            }
    
            paint.setTypeface(typeface);
        }
    }
    • +1 Gracias! Y aquí es un buen ejemplo de uso.
    • y @Benjamin …. Benjamin dice que no puede usar TypefaceSpan pero luego Marco, se muestra un ejemplo de trabajo, utilizando sólo eso. Cual es el correcto? Benjamín lo hicieron la prueba de su ejemplo?
    • Creo que @MarcoW comentado en la respuesta equivocada. Supongo que él quería comentar @notme la respuesta, como es de su clase que él utiliza. Para ser claro, no estoy diciendo que tú no sub-clase TypefaceSpan. Yo estoy muy sugiriendo fuertemente que no. Haciendo así que rompe Liscov principal de sustitución y es muy mala práctica. Usted ha subclasificado una clase que especifica la fuente a través de un family nombre de y es parcelable; has totalmente sobrescrito que el comportamiento y la family parámetro confuso y sin sentido, y la Span es también no parcelable.
    • Yo realmente no sé nada sobre este tema @BenjaminDobell … tratando de averiguar lo que está pasando en esta otra pregunta que básicamente portado las respuestas aquí para Kotlin y no hay manera de hacerlo funcionar. El Kotlin diferencia no es relevante porque es el mismo concepto, y sería el mismo código de bytes de Java, algo debe estar mal con: stackoverflow.com/questions/35039686/…
    • Bien teniendo en cuenta que esta respuesta ya tiene 42 hasta los votos, preguntando si he probado mi ejemplo es un poco peculiar. Sin embargo, sí que he probado este código. Este es el exacto el código que he utilizado en numerosas publicado las aplicaciones de Android.
    • Es posible realizar subraya a este CustomTypefaceSpan?
    • Android Typeface clase no proporciona soporte para subraya. Sin embargo, tanto la oficial TypefaceSpan y mi clase CustomTypefaceSpan utilizar un TextPaint detrás de las escenas para asistir con la representación, el único problema es que no se expone de una manera sencilla. Para subrayar toda una TextView que usted puede hacer textView.setPaintFlags(Paint.UNDERLINE_TEXT_FLAG);. De lo contrario, agregue un valor booleano underlined, y un nuevo método de setUnderlined(boolean) a mi clase. A continuación, en apply(Paint), agregar paint.setUnderlineText(underlined);
    • podría usted explicar cuál es el propósito de fakeStyle es y cuáles son esas operaciones a nivel de bit están haciendo? Estoy un poco confundida.
    • Por lo general, cuando usted hace una fuente en negrita en el equipo, hay una audaz versión de la fuente en cuestión, y que se utiliza en lugar de la fuente normal. Sin embargo, para que funcione tienes que saber si la fuente que está utilizando ya está en negrita y lo que las correspondientes fuentes. Como un trabajo en torno a Android proporciona «falso» en negrita y cursiva modos, que sólo se aplica a algunos se transforma en fuente regular con el fin de hacer que aparezca en negrita o en cursiva (de modo que usted no necesita cargar varios tipos de letra).
    • Sí, aunque debo añadir que no es «técnicamente» de Android que hace la representación de la fuente. Es Skia (skia.org), un nativo de la biblioteca desarrollado por Google. Si usted mira en SKPaint.cpp usted puede ver exactamente lo que está pasando.

  3. 4

    En Android P es posible, mediante el mismo TypefaceSpan clase que usted sepa, como se muestra aquí.

    Pero en versiones anteriores, usted puede usar lo que han mostrado más adelante en el video, que he escrito sobre aquí.

  4. 0

    Si alguien estaría interesado aquí C# Xamarin versión de Benjamin código:

    using System;
    using Android.Graphics;
    using Android.Text;
    using Android.Text.Style;
    
    namespace Utils
    {
        //https://stackoverflow.com/a/17961854/1996780
        ///<summary>A text span which applies <see cref="Android.Graphics.Typeface"/> on text</summary>
        internal class CustomFontSpan : MetricAffectingSpan
        {
            ///<summary>The typeface to apply</summary>
            public Typeface Typeface { get; }
    
            ///<summary>CTor - creates a new instance of the <see cref="CustomFontSpan"/> class</summary>
            ///<param name="typeface">Typeface to apply</param>
            ///<exception cref="ArgumentNullException"><paramref name="typeface"/> is null</exception>
            public CustomFontSpan(Typeface typeface) =>
                Typeface = typeface ?? throw new ArgumentNullException(nameof(typeface));
    
    
            public override void UpdateDrawState(TextPaint drawState) => Apply(drawState);
    
            public override void UpdateMeasureState(TextPaint paint) => Apply(paint);
    
            ///<summary>Applies <see cref="Typeface"/></summary>
            ///<param name="paint"><see cref="Paint"/> to apply <see cref="Typeface"/> on</param>
            private void Apply(Paint paint)
            {
                Typeface oldTypeface = paint.Typeface;
                var oldStyle = oldTypeface != null ? oldTypeface.Style : 0;
                var fakeStyle = oldStyle & Typeface.Style;
    
                if (fakeStyle.HasFlag(TypefaceStyle.Bold))
                    paint.FakeBoldText = true;
    
                if (fakeStyle.HasFlag(TypefaceStyle.Italic))
                    paint.TextSkewX = -0.25f;
    
                paint.SetTypeface(Typeface);
            }
        }
    }

    Y uso: (en el OnCreate de la actividad)

    var txwLogo = FindViewById<TextView>(Resource.Id.logo);
    var font = Resources.GetFont(Resource.Font.myFont);
    
    var wordtoSpan = new SpannableString(txwLogo.Text);
    wordtoSpan.SetSpan(new CustomFontSpan(font), 6, 7, SpanTypes.InclusiveInclusive); //One caracter
    txwLogo.TextFormatted = wordtoSpan;  
  5. -2

    He intentado varias soluciones similares, se encontró que Este es simple y viable. Sólo que el elemento, haga clic en se maneja como un clic de botón en lugar de la onOptionsItemSelected. Gracias!

    Aquí está mi código para mi proyecto:

    En mi menu_main.xml:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">
    
    
    <item
        android:id="@+id/action_friends"
        android:orderInCategory="100"
        android:title="@string/hello_world"
        app:actionViewClass="android.widget.Button"
        app:showAsAction="always" />
    
    
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        app:showAsAction="never" />
    
    </menu>

    En Mi MainActivity.java:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //Use custom menu
        MenuInflater inflater = getMenuInflater();
        //Inflate the custom menu
        inflater.inflate(R.menu.menu_main, menu);
        //reference to the item of the menu
        MenuItem i=menu.findItem(R.id.action_friends);
        Button itemuser =(Button) i.getActionView();
    
        if(itemuser!=null){
            //Create Typeface object to use unicode font in assets folder
            Typeface a =  Typeface.createFromAsset(getApplicationContext(), "fontawesome-webfont.ttf");
            //Set unicode font to menu item
            itemuser.setTypeface(a);
            itemuser.setText(getString(R.string.fa_users));
            //Set item text and color
            itemuser.setTextColor(Color.BLACK);
            //Make item background transparent
            itemuser.setBackgroundColor(Color.TRANSPARENT);
    
            itemuser.setOnClickListener(new View.OnClickListener(){
    
                @Override
                public void onClick(View v) {
                    //set action when clicked
                }
            });
        }
        return super.onCreateOptionsMenu(menu);
    }
    • Gracias por recordármelo, editado respuesta
    • Gracias, señor. Siento ser una plaga 😛
    • No es relevante para la publicación de que se trate.

Dejar respuesta

Please enter your comment!
Please enter your name here