下面列出了android.text.Layout#getLineBottom ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private BetterLinkMovementExtended.ClickableSpanWithText findClickableSpanUnderTouch(TextView textView, Spannable text, MotionEvent event) {
int touchX = (int) event.getX();
int touchY = (int) event.getY();
touchX -= textView.getTotalPaddingLeft();
touchY -= textView.getTotalPaddingTop();
touchX += textView.getScrollX();
touchY += textView.getScrollY();
Layout layout = textView.getLayout();
int touchedLine = layout.getLineForVertical(touchY);
int touchOffset = layout.getOffsetForHorizontal(touchedLine, (float) touchX);
this.touchedLineBounds.left = layout.getLineLeft(touchedLine);
this.touchedLineBounds.top = (float) layout.getLineTop(touchedLine);
this.touchedLineBounds.right = layout.getLineWidth(touchedLine) + this.touchedLineBounds.left;
this.touchedLineBounds.bottom = (float) layout.getLineBottom(touchedLine);
if (this.touchedLineBounds.contains((float) touchX, (float) touchY)) {
Object[] spans = text.getSpans(touchOffset, touchOffset, SPAN_CLASS);
for (Object span : spans) {
if (span instanceof ClickableSpan) {
return ClickableSpanWithText.ofSpan(textView, (ClickableSpan) span);
}
}
return null;
} else {
return null;
}
}
@Override
protected void onDraw(Canvas canvas) {
int height = getHeight();
Layout layout = getLayout();
int maxHeight = 0;
for (int i = 0; i < layout.getLineCount(); i++) {
int bottom = layout.getLineBottom(i);
if (bottom > height) {
maxHeight = layout.getLineTop(i);
break;
}
}
if (maxHeight > 0) {
canvas.save();
canvas.clipRect(0, 0, getWidth(), maxHeight);
}
super.onDraw(canvas);
OverlineSpan.draw(this, canvas);
if (maxHeight > 0) {
canvas.restore();
}
}
/**
* Gets the span that was touched.
* @param tv {@link TextView}
* @param span {@link Spannable}
* @param e {@link MotionEvent}
* @return {@link TouchableSpan}
*/
private TouchableSpan getTouchedSpan(TextView tv, Spannable span, MotionEvent e) {
// Find the location in which the touch was made
int x = (int)e.getX();
int y = (int)e.getY();
// Ignore padding
x -= tv.getTotalPaddingLeft();
y -= tv.getTotalPaddingTop();
// Account for scrollable text
x += tv.getScrollX();
y += tv.getScrollY();
final Layout layout = tv.getLayout();
final int touchedLine = layout.getLineForVertical(y);
final int touchOffset = layout.getOffsetForHorizontal(touchedLine, x);
// Set bounds of the touched line
touchBounds.left = layout.getLineLeft(touchedLine);
touchBounds.top = layout.getLineTop(touchedLine);
touchBounds.right = layout.getLineRight(touchedLine);
touchBounds.bottom = layout.getLineBottom(touchedLine);
// Ensure the span falls within the bounds of the touch
TouchableSpan touchSpan = null;
if (touchBounds.contains(x, y)) {
// Find clickable spans that lie under the touched area
TouchableSpan[] spans = span.getSpans(touchOffset, touchOffset, TouchableSpan.class);
touchSpan = (spans.length > 0) ? spans[0] : null;
}
return touchSpan;
}
private static float getLineBottomWithoutSpacing(@NonNull Layout layout, int line) {
final float value = layout.getLineBottom(line);
final boolean isLastLineSpacingNotAdded = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
final boolean isLastLine = line == (layout.getLineCount() - 1);
final float lineBottomWithoutSpacing;
final float lineSpacingExtra = layout.getSpacingAdd();
final float lineSpacingMultiplier = layout.getSpacingMultiplier();
final boolean hasLineSpacing = Float.compare(lineSpacingExtra, .0F) != 0
|| Float.compare(lineSpacingMultiplier, 1F) != 0;
if (!hasLineSpacing || isLastLine && isLastLineSpacingNotAdded) {
lineBottomWithoutSpacing = value;
} else {
final float extra;
if (Float.compare(lineSpacingMultiplier, 1F) != 0) {
final float lineHeight = getLineHeight(layout, line);
extra = lineHeight - (lineHeight - lineSpacingExtra) / lineSpacingMultiplier;
} else {
extra = lineSpacingExtra;
}
lineBottomWithoutSpacing = value - extra;
}
return lineBottomWithoutSpacing;
}
@Override
public void onDraw(@NonNull Canvas canvas) {
if (!isInEditMode()) {
int top;
Layout layout = getLayout();
if (layout != null && codeEditor != null && mHighlightCurrentLine) {
int currentLineStart = codeEditor.getLineForIndex(getSelectionStart());
if (currentLineStart == codeEditor.getLineForIndex(getSelectionEnd())) {
int selectedLineStartIndex = codeEditor.getIndexForStartOfLine(currentLineStart);
int selectedLineEndIndex = codeEditor.getIndexForEndOfLine(currentLineStart);
int topVisualLine = layout.getLineForOffset(selectedLineStartIndex);
int bottomVisualLine = layout.getLineForOffset(selectedLineEndIndex);
int left = mGutterWidth;
if (!mShowLineNumbers)
left = 0; //убираем отступ для Paint'а если номера строк выключены
top = layout.getLineTop(topVisualLine) + getPaddingTop();
int right = (layout.getWidth() + getPaddingLeft()) + getPaddingRight();
int bottom = layout.getLineBottom(bottomVisualLine) + getPaddingTop();
canvas.drawRect(left, top, right, bottom, mSelectedLinePaint);
}
}
super.onDraw(canvas);
if (layout != null && mShowLineNumbers) {
int prevLineNumber = -1;
canvas.drawRect(getScrollX(), getScrollY(),
mGutterWidth + getScrollX(),
getScrollY() + getHeight(), mGutterBackgroundPaint);
int paddingTop = getPaddingTop();
int max = mLineUtils.getBottomVisibleLine(this);
int textRight = (mGutterWidth - mIdealMargin / 2) + getScrollX();
if (codeEditor != null) {
int i = mLineUtils.getTopVisibleLine(this);
if (i >= 2) {
i -= 2;
} else {
i = 0;
}
while (i <= max) {
int number = codeEditor.getLineForIndex(getLayout().getLineStart(i));
if (number != prevLineNumber) {
canvas.drawText(Integer.toString(number + 1), textRight,
layout.getLineBaseline(i) + paddingTop, mLineNumberPaint);
}
prevLineNumber = number;
i++;
}
top = getScrollY();
canvas.drawLine(mGutterWidth + getScrollX(), top,
mGutterWidth + getScrollX(), top + getHeight(), mLinePaint);
}
}
}
}
public static int getLineBottomWithoutPaddingAndSpacing(
@NonNull Layout layout,
int line
) {
final int bottom = layout.getLineBottom(line);
final boolean lastLineSpacingNotAdded = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
final boolean isSpanLastLine = line == (layout.getLineCount() - 1);
final int lineBottom;
final float lineSpacingExtra = layout.getSpacingAdd();
final float lineSpacingMultiplier = layout.getSpacingMultiplier();
// simplified check
final boolean hasLineSpacing = lineSpacingExtra != DEFAULT_EXTRA
|| lineSpacingMultiplier != DEFAULT_MULTIPLIER;
if (!hasLineSpacing
|| (isSpanLastLine && lastLineSpacingNotAdded)) {
lineBottom = bottom;
} else {
final float extra;
if (Float.compare(DEFAULT_MULTIPLIER, lineSpacingMultiplier) != 0) {
final int lineHeight = getLineHeight(layout, line);
extra = lineHeight -
((lineHeight - lineSpacingExtra) / lineSpacingMultiplier);
} else {
extra = lineSpacingExtra;
}
lineBottom = (int) (bottom - extra + .5F);
}
// check if it is the last line that span is occupying **and** that this line is the last
// one in TextView
if (isSpanLastLine
&& (line == layout.getLineCount() - 1)) {
return lineBottom - layout.getBottomPadding();
}
return lineBottom;
}