Texto con degradado en Android
¿Cómo puedo extender TextView
para permitir el dibujo de texto con un efecto de degradado?
- ¿Cómo puedo hacer un diamante ShapeDrawable?
- Cómo configurar windowDrawsSystemBarBackgrounds de forma programática?
- Espresso - Juego SeekBar
- ¿Cómo desarrollar una aplicación android para diferentes pantallas?
- Cómo deshacerse completamente de la GUI de una actividad (evitar una pantalla en negro)
- Creación de una biblioteca de interfaz de usuario de Android con un extremo frontal personalizable
- Mejor equivalente de Android para iOS Tab Bar Controller
- Acceso al controlador de subprocesos de interfaz de usuario desde un servicio
- Cómo ocultar el botón en la barra de acciones
- Android: ¿Cómo configurar el diálogo de forma programática?
- ¿Cómo obtengo el siguiente resultado utilizando RelativeLayout?
- HorizontalScrollView: desplazamiento automático para finalizar cuando se agregan nuevas vistas?
- Anular los colores del menú contextual en Android
TextView secondTextView = new TextView(this); Shader textShader=new LinearGradient(0, 0, 0, 20, new int[]{Color.GREEN,Color.BLUE}, new float[]{0, 1}, TileMode.CLAMP); secondTextView.getPaint().setShader(textShader);
No parece posible ampliar TextView para dibujar texto con un degradado. Sin embargo, es posible lograr este efecto creando un lienzo y dibujándolo. Primero tenemos que declarar nuestro elemento de interfaz de usuario personalizado . En la iniciación necesitamos crear una subclase de Layout . En este caso, usaremos BoringLayout que solo admite texto con una sola línea.
Shader textShader=new LinearGradient(0, 0, 0, 20, new int[]{bottom,top}, new float[]{0, 1}, TileMode.CLAMP);//Assumes bottom and top are colors defined above textPaint.setTextSize(textSize); textPaint.setShader(textShader); BoringLayout.Metrics boringMetrics=BoringLayout.isBoring(text, textPaint); boringLayout=new BoringLayout(text, textPaint, 0, Layout.Alignment.ALIGN_CENTER, 0.0f, 0.0f, boringMetrics, false);
Entonces onMeasure
y onDraw
:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ setMeasuredDimension((int) textPaint.measureText(text), (int) textPaint.getFontSpacing()); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); boringLayout.draw(canvas); }
Nuestra implementación de onDraw
es en este punto bastante perezoso (ignora completamente las especificaciones de medición !, pero siempre y cuando usted garantiza que la vista se da espacio suficiente, debería funcionar bien.
Alternativamente, sería posible heredar de un Canvas
y anular el método onPaint
. Si esto se hace, entonces lamentablemente el ancla para el texto que se dibuja siempre estará en la parte inferior, por lo que tenemos que añadir -textPaint.getFontMetricsInt().ascent()
a nuestra coordenada y.
He enrollado una biblioteca que abarca ambos métodos. Puede crear GradientTextView en XML o simplemente utilizar GradientTextView.setGradient (TextView textView …) para hacerlo en un objeto TextView regular.
Una solución simple pero algo limitada sería utilizar estos atributos:
android:fadingEdge="horizontal" android:scrollHorizontally="true"
Lo he usado en campos de texto donde quiero que se desvanezcan si llegan demasiado tiempo.
Aquí está con el soporte multilínea como un solo revestimiento. Esto debería funcionar para los botones también.
textView.getPaint().setShader(new LinearGradient(0,0,0,textView.getLineHeight(), startColor, endColor, Shader.TileMode.REPEAT));
Esta es una buena manera de hacerlo:
/** * sets a vertical gradient on the textView's paint, so that on its onDraw method, it will use it. * * @param viewAlreadyHasSize * set to true only if the textView already has a size */ public static void setVerticalGradientOnTextView(final TextView tv, final int positionsAndColorsResId, final boolean viewAlreadyHasSize) { final String[] positionsAndColors = tv.getContext().getResources().getStringArray(positionsAndColorsResId); final int[] colors = new int[positionsAndColors.length]; float[] positions = new float[positionsAndColors.length]; for (int i = 0; i < positionsAndColors.length; ++i) { final String positionAndColors = positionsAndColors[i]; final int delimeterPos = positionAndColors.lastIndexOf(':'); if (delimeterPos == -1 || positions == null) { positions = null; colors[i] = Color.parseColor(positionAndColors); } else { positions[i] = Float.parseFloat(positionAndColors.substring(0, delimeterPos)); String colorStr = positionAndColors.substring(delimeterPos + 1); if (colorStr.startsWith("0x")) colorStr = '#' + colorStr.substring(2); else if (!colorStr.startsWith("#")) colorStr = '#' + colorStr; colors[i] = Color.parseColor(colorStr); } } setVerticalGradientOnTextView(tv, colors, positions, viewAlreadyHasSize); } /** * sets a vertical gradient on the textView's paint, so that on its onDraw method, it will use it. <br/> * * @param colors * the colors to use. at least one should exist. * @param tv * the textView to set the gradient on it * @param positions * where to put each color (fraction, max is 1). if null, colors are spread evenly . * @param viewAlreadyHasSize * set to true only if the textView already has a size */ public static void setVerticalGradientOnTextView(final TextView tv, final int[] colors, final float[] positions, final boolean viewAlreadyHasSize) { final Runnable runnable = new Runnable() { @Override public void run() { final TileMode tile_mode = TileMode.CLAMP; final int height = tv.getHeight(); final LinearGradient lin_grad = new LinearGradient(0, 0, 0, height, colors, positions, tile_mode); final Shader shader_gradient = lin_grad; tv.getPaint().setShader(shader_gradient); } }; if (viewAlreadyHasSize) runnable.run(); else runJustBeforeBeingDrawn(tv, runnable); } public static void runJustBeforeBeingDrawn(final View view, final Runnable runnable) { final OnPreDrawListener preDrawListener = new OnPreDrawListener() { @Override public boolean onPreDraw() { view.getViewTreeObserver().removeOnPreDrawListener(this); runnable.run(); return true; } }; view.getViewTreeObserver().addOnPreDrawListener(preDrawListener); }
Además, si desea utilizar un mapa de bits del degradado, en lugar de uno real, utilice:
/** * sets an image for the textView <br/> * NOTE: this function must be called after you have the view have its height figured out <br/> */ public static void setBitmapOnTextView(final TextView tv, final Bitmap bitmap) { final TileMode tile_mode = TileMode.CLAMP; final int height = tv.getHeight(); final int width = tv.getWidth(); final Bitmap temp = Bitmap.createScaledBitmap(bitmap, width, height, true); final BitmapShader bitmapShader = new BitmapShader(temp, tile_mode, tile_mode); tv.getPaint().setShader(bitmapShader); }
Aquí está un ejemplo para linearlayout, usted puede utilizar este ejemplo para textview también, y en el código fuente no será la codificación del gradiente, usted consigue el código de fuente y agrega el código de ese sitio sí mismo – http: // android-codes-examples .blogspot.com / 2011/07 / design-linearlayout-or-textview-and-any.html
- Media Player Looping: Android
- Posición de retención en ListView después de llamar a notifyDataSetChanged