5

TextView の特定の単語の上に単色のブロックを配置したい TextView があります。次に例を示します。

「これはテキスト文字列です。この WORD の上に四角形を配置したいです」 - つまり、「WORD」は単色の四角形になります。

これを行うには、テキストの上にブロックを描画するために、onDraw(Canvas canvas) メソッドをオーバーライドすることを考えています。私の唯一の問題は、特定の単語または文字の絶対位置を取得する効率的な方法を見つけることです。

基本的に、 getOffsetForPosition(float x, float y) メソッドの正反対のことをするものを探しています

4

4 に答える 4

10

この投稿に基づく: TextView 内の ClickableSpan の座標を取得するにはどうすればよいですか? 、テキストの上に長方形を配置するために、このコードを使用することができました:

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);
 }
于 2012-11-15T15:38:03.200 に答える
4

そのためにスパンを使用できます。まず、次のように、テキストのスパン可能を作成します。

Spannable span = new SpannableString(text);

次に、次のように強調表示する単語をスパンで囲みます。

span.setSpan(new UnderlineSpan(), start, end, 
                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

残念ながら、単語を境界線で囲む既存のスパンについては知りません。UnderlineSpan とBackgroundColorSpanを見つけました。おそらくこれらも役に立ちます。または、コードを見て、それらのいずれかに基づいて BorderSpan を作成できるかどうかを確認できます。

于 2013-05-18T20:09:59.850 に答える
0

WORD の上に四角形を描画する代わりに、その文字を U+25AE (▮ 黒い垂直の四角形) のような適切な Unicode 記号に置き換えることができます。

だからあなたは得るだろう

「これはテキスト文字列です。これに長方形を置きたい ▮▮▮▮」

それで十分なら。Unicode シンボルの廃棄リストについては、たとえばウィキペディアを参照してください。

実際にそのブラック ボックスをペイントする必要がある場合は、テキストが 1 行である限り、次の操作を実行できます。

ボックスの左端を見つけるには、ここで説明するように「WORD」の前のテキスト部分の幅を計算し、同じ方法を使用して「WORD」の幅を計算してボックスの幅を見つけます。

複数行のテキストの場合、説明された方法も機能する可能性がありますが、ここでかなり多くの作業を行う必要があると思います.

于 2012-11-14T19:32:37.010 に答える