I have a TextView
with many ClickableSpan
.
On click on a ClickableSpan
, I have to get the coordinate on screen of it (to show a custom View
at his position).
The problem is that I have no idea of how I can do this. The onClick()
method of the ClickableSpan
gives me in parameter a View
, the TextView
which contains the ClickableSpan
.
I have used the following to get characters position in the TextView
, but I don't know how I can convert it to get x/y position on screen of the text.
@Override
public void onClick(View v){
SpannableString completeText = (SpannableString)((TextView) v).getText();
Log.v("characters position", completeText.getSpanStart(this) + " / " + completeText.getSpanEnd(this));
}
Thanks in advance for your help!
EDIT : I want to get the entire coordinate of the ClickableSpan and its size, the aim is to show my custom view at the bottom center of the text. The onTouch method will give me the finger position, not the entire text coordinates. So, with this method, I will not have the middle of the text.
This example demonstrates how do I set the part of the Android textView as clickable. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.
Just like Buttons and ImageViews we can add onClickListeners to TextViews by simply adding the attribute android:onClick="myMethod" to your TextView XML tag. The other way, TextView tv = (TextView) this.
I have found a solution :-) Here it is, may be this will help others with the same problem like me !
// 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
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With