Obtener posición absoluta para un desplazamiento dado en TextView (Android)
Tengo un TextView en el que quiero colocar un bloque de color sólido sobre determinadas palabras de TextView, por ejemplo:
"Esta es una cadena de texto, quiero poner un rectángulo sobre esta palabra" – por lo tanto, "WORD" tendría un rectángulo con un color sólido sobre ella.
- Android ¿Cómo enviar texto e imágenes o cualquier objeto con intención?
- ¿Hay una manera de agregar la sombra interna a un TextView en Android?
- ¿Cómo crear un efecto de marquesina para un texto de menor longitud que no exceda el tamaño de la pantalla en Android?
- Hacer texto flotante-derecha en Android
- Alineación de 2 columnas en una vista de texto
Para hacer esto, estoy pensando en reemplazar el método onDraw (Canvas canvas), para dibujar un bloque sobre el texto. Mi único problema es encontrar una forma eficiente de obtener la posición absoluta de una determinada palabra o carácter.
Básicamente, estoy buscando algo que hace exactamente lo contrario del método getOffsetForPosition (float x, float y)
- El texto de Android se recorta en algunos dispositivos
- No se puede establecer la sombra de TextView mediante programación
- Texto transparente de Android
- Cómo establecer la sombra alrededor de TextView
- Android: cómo crear un botón con imagen y texto que están centrados
- TextView en la Galería
- Android recibe archivos compartidos pero no comparte contenido de texto
- Cómo crear alineado verticalmente superíndice y subíndice en TextView
Basado en este post: ¿Cómo obtener coordenadas de un ClickableSpan dentro de un TextView? , He logrado utilizar este código para poner un rectángulo encima del texto:
protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.WHITE); // Initialize global value TextView parentTextView = this; Rect parentTextViewRect = new Rect(); // Find where the WORD is String targetWord = "WORD"; int startOffsetOfClickedText = this.getText().toString().indexOf(targetWord); int endOffsetOfClickedText = startOffsetOfClickedText + targetWord.length(); // Initialize values for the computing of clickedText position Layout textViewLayout = parentTextView.getLayout(); double startXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal((int)startOffsetOfClickedText); double endXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal((int)endOffsetOfClickedText); // Get the rectangle of the clicked text int currentLineStartOffset = textViewLayout.getLineForOffset((int)startOffsetOfClickedText); int currentLineEndOffset = textViewLayout.getLineForOffset((int)endOffsetOfClickedText); boolean keywordIsInMultiLine = currentLineStartOffset != currentLineEndOffset; textViewLayout.getLineBounds(currentLineStartOffset, parentTextViewRect); // Update the rectangle position to his real position on screen int[] parentTextViewLocation = {0,0}; parentTextView.getLocationOnScreen(parentTextViewLocation); double parentTextViewTopAndBottomOffset = ( //parentTextViewLocation[1] - parentTextView.getScrollY() + parentTextView.getCompoundPaddingTop() ); parentTextViewRect.top += parentTextViewTopAndBottomOffset; parentTextViewRect.bottom += parentTextViewTopAndBottomOffset; // In the case of multi line text, we have to choose what rectangle take if (keywordIsInMultiLine){ WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); int screenHeight = display.getHeight(); int dyTop = parentTextViewRect.top; int dyBottom = screenHeight - parentTextViewRect.bottom; boolean onTop = dyTop > dyBottom; if (onTop){ endXCoordinatesOfClickedText = textViewLayout.getLineRight(currentLineStartOffset); } else{ parentTextViewRect = new Rect(); textViewLayout.getLineBounds(currentLineEndOffset, parentTextViewRect); parentTextViewRect.top += parentTextViewTopAndBottomOffset; parentTextViewRect.bottom += parentTextViewTopAndBottomOffset; startXCoordinatesOfClickedText = textViewLayout.getLineLeft(currentLineEndOffset); } } parentTextViewRect.left += ( parentTextViewLocation[0] + startXCoordinatesOfClickedText + parentTextView.getCompoundPaddingLeft() - parentTextView.getScrollX() ); parentTextViewRect.right = (int) ( parentTextViewRect.left + endXCoordinatesOfClickedText - startXCoordinatesOfClickedText ); canvas.drawRect(parentTextViewRect, paint); }
Puedes usar espacios para eso. Primero crear un spannable para su texto, como este:
Spannable span = new SpannableString(text);
A continuación, poner un espacio alrededor de la palabra que desea resaltar, algo así:
span.setSpan(new UnderlineSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Desafortunadamente no sé de una extensión existente que ponga una frontera alrededor de una palabra. He encontrado UnderlineSpan, y también BackgroundColorSpan , tal vez estos también son útiles para usted, o puede echar un vistazo al código y ver si puede crear un BorderSpan basado en uno de ellos.
En vez de dibujar un rectángulo sobre la PALABRA, usted podría substituir simplemente sus caracteres por un símbolo unicode apropiado como U + 25AE (▮ rectángulo vertical negro).
Así que tendrías
"Esta es una cadena de texto, quiero poner un rectángulo sobre este ▮▮▮▮"
Si eso es suficiente. Vea por ejemplo Wikipedia para una lista de wast de símbolos de unicode.
Si realmente necesita pintar ese cuadro negro puede hacer lo siguiente siempre y cuando su texto está en una sola línea:
Calcular el ancho de la parte de texto antes de 'WORD' como se explica aquí para encontrar el borde izquierdo de la caja y calcuate el ancho de 'WORD' utilizando el mismo método para encontrar el ancho de la caja.
Para un texto multilínea el método explicado también podría funcionar, pero creo que tendrás que hacer mucho trabajo aquí.
- ¿Es posible esperar hasta que un brindis haya terminado de reanudar el método?
- Android ksoap2 a través de https