2012-08-10 63 views
12

我有一個TextView許多ClickableSpan如何在TextView中獲取ClickableSpan的座標?

點擊一個ClickableSpan,我必須得到它的屏幕座標(在他的位置顯示一個自定義的View)。

問題是,我不知道如何做到這一點。 ClickableSpanonClick()方法給我參數a View,TextView其中包含ClickableSpan

我已經使用以下來獲取TextView中的字符位置,但我不知道如何將它轉換爲文本屏幕上的x/y位置。

@Override 
public void onClick(View v){ 

    SpannableString completeText = (SpannableString)((TextView) v).getText(); 
    Log.v("characters position", completeText.getSpanStart(this) + "/" + completeText.getSpanEnd(this)); 

} 

在此先感謝您的幫助!

編輯:我想獲得ClickableSpan的整個座標及其大小,目的是在文本的底部中心顯示我的自定義視圖。 onTouch方法會給我手指位置,而不是整個文本座標。所以,用這種方法,我不會有文字的中間。

+0

重寫onTouch()並使用event.getX(),event.getY()? – 2012-08-10 16:19:18

+1

感謝您的回答!不幸的是,我發現這個方法非常...醜!我希望有一個更好的解決方案。此外,我忘記了另一個精度:我想獲取ClickableSpan的整個座標及其大小,目的是在文本底部的中心顯示我的自定義視圖。 onTouch方法會給我手指位置,而不是整個文本座標。所以,用這種方法,我不會有文字的中間。任何其他想法? – 2012-08-10 16:27:07

回答

25

我發現了一個解決方案:-) 在這裏,這可能會幫助其他人與我有同樣的問題!

// Initialize global value 
this.parentTextViewRect = new Rect(); 


// Initialize values for the computing of clickedText position 
SpannableString completeText = (SpannableString)(parentTextView).getText(); 
Layout textViewLayout = parentTextView.getLayout(); 

double startOffsetOfClickedText = completeText.getSpanStart(clickedText); 
double endOffsetOfClickedText = completeText.getSpanEnd(clickedText); 
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, this.parentTextViewRect); 


// Update the rectangle position to his real position on screen 
int[] parentTextViewLocation = {0,0}; 
parentTextView.getLocationOnScreen(parentTextViewLocation); 

double parentTextViewTopAndBottomOffset = (
    parentTextViewLocation[1] - 
    parentTextView.getScrollY() + 
    this.parentTextView.getCompoundPaddingTop() 
); 
this.parentTextViewRect.top += parentTextViewTopAndBottomOffset; 
this.parentTextViewRect.bottom += parentTextViewTopAndBottomOffset; 

// In the case of multi line text, we have to choose what rectangle take 
if (keywordIsInMultiLine){ 

    int screenHeight = this.mWindowManager.getDefaultDisplay().getHeight(); 
    int dyTop = this.parentTextViewRect.top; 
    int dyBottom = screenHeight - this.parentTextViewRect.bottom; 
    boolean onTop = dyTop > dyBottom; 

    if (onTop){ 
     endXCoordinatesOfClickedText = textViewLayout.getLineRight(currentLineStartOffset); 
    } 
    else{ 
     this.parentTextViewRect = new Rect(); 
     textViewLayout.getLineBounds(currentLineEndOffset, this.parentTextViewRect); 
     this.parentTextViewRect.top += parentTextViewTopAndBottomOffset; 
     this.parentTextViewRect.bottom += parentTextViewTopAndBottomOffset; 
     startXCoordinatesOfClickedText = textViewLayout.getLineLeft(currentLineEndOffset); 
    } 

} 

this.parentTextViewRect.left += (
    parentTextViewLocation[0] + 
    startXCoordinatesOfClickedText + 
    this.parentTextView.getCompoundPaddingLeft() - 
    parentTextView.getScrollX() 
); 
this.parentTextViewRect.right = (int) (
    this.parentTextViewRect.left + 
    endXCoordinatesOfClickedText - 
    startXCoordinatesOfClickedText 
);