/// <summary> /// Move the selection end to the buffer offset physically below /// the current selection end. /// </summary> /// <remarks> /// Move the selection end to the buffer offset physically below /// the current selection end. /// </remarks> public static bool extendDown(android.text.Spannable text, android.text.Layout layout ) { int end = getSelectionEnd(text); int line = layout.getLineForOffset(end); if (line < layout.getLineCount() - 1) { int move; if (layout.getParagraphDirection(line) == layout.getParagraphDirection(line + 1)) { float h = layout.getPrimaryHorizontal(end); move = layout.getOffsetForHorizontal(line + 1, h); } else { move = layout.getLineStart(line + 1); } extendSelection(text, move); return(true); } else { if (end != text.Length) { extendSelection(text, text.Length); return(true); } } return(true); }
private static int chooseHorizontal(android.text.Layout layout, int direction, int off1, int off2) { int line1 = layout.getLineForOffset(off1); int line2 = layout.getLineForOffset(off2); if (line1 == line2) { // same line, so it goes by pure physical direction float h1 = layout.getPrimaryHorizontal(off1); float h2 = layout.getPrimaryHorizontal(off2); if (direction < 0) { // to left if (h1 < h2) { return(off1); } else { return(off2); } } else { // to right if (h1 > h2) { return(off1); } else { return(off2); } } } else { // different line, so which line is "left" and which is "right" // depends upon the directionality of the text // This only checks at one end, but it's not clear what the // right thing to do is if the ends don't agree. Even if it // is wrong it should still not be too bad. int line = layout.getLineForOffset(off1); int textdir = layout.getParagraphDirection(line); if (textdir == direction) { return(System.Math.Max(off1, off2)); } else { return(System.Math.Min(off1, off2)); } } }
/// <summary> /// Scrolls the specified widget to the specified coordinates, except /// constrains the X scrolling position to the horizontal regions of /// the text that will be visible after scrolling to the specified /// Y position. /// </summary> /// <remarks> /// Scrolls the specified widget to the specified coordinates, except /// constrains the X scrolling position to the horizontal regions of /// the text that will be visible after scrolling to the specified /// Y position. /// </remarks> public static void scrollTo(android.widget.TextView widget, android.text.Layout layout , int x, int y) { int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom( ); int top = layout.getLineForVertical(y); int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding); int left = int.MaxValue; int right = 0; android.text.Layout.Alignment?a = layout.getParagraphAlignment(top); bool ltr = layout.getParagraphDirection(top) > 0; { for (int i = top; i <= bottom; i++) { left = (int)System.Math.Min(left, layout.getLineLeft(i)); right = (int)System.Math.Max(right, layout.getLineRight(i)); } } int hoizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight (); int availableWidth = widget.getWidth() - hoizontalPadding; int actualWidth = right - left; if (actualWidth < availableWidth) { if (a == android.text.Layout.Alignment.ALIGN_CENTER) { x = left - ((availableWidth - actualWidth) / 2); } else { if ((ltr && (a == android.text.Layout.Alignment.ALIGN_OPPOSITE)) || (a == android.text.Layout.Alignment .ALIGN_RIGHT)) { // align_opposite does NOT mean align_right, we need the paragraph // direction to resolve it to left or right x = left - (availableWidth - actualWidth); } else { x = left; } } } else { x = System.Math.Min(x, right - availableWidth); x = System.Math.Max(x, left); } widget.scrollTo(x, y); }
/// <summary> /// Move the cursor to the buffer offset physically below the current /// offset, or return false if the cursor is already on the bottom line. /// </summary> /// <remarks> /// Move the cursor to the buffer offset physically below the current /// offset, or return false if the cursor is already on the bottom line. /// </remarks> public static bool moveDown(android.text.Spannable text, android.text.Layout layout ) { int start = getSelectionStart(text); int end = getSelectionEnd(text); if (start != end) { int min = System.Math.Min(start, end); int max = System.Math.Max(start, end); setSelection(text, max); if (min == 0 && max == text.Length) { return(false); } return(true); } else { int line = layout.getLineForOffset(end); if (line < layout.getLineCount() - 1) { int move; if (layout.getParagraphDirection(line) == layout.getParagraphDirection(line + 1)) { float h = layout.getPrimaryHorizontal(end); move = layout.getOffsetForHorizontal(line + 1, h); } else { move = layout.getLineStart(line + 1); } setSelection(text, move); return(true); } } return(false); }
private static int findEdge(android.text.Spannable text, android.text.Layout layout , int dir) { int pt = getSelectionEnd(text); int line = layout.getLineForOffset(pt); int pdir = layout.getParagraphDirection(line); if (dir * pdir < 0) { return(layout.getLineStart(line)); } else { int end = layout.getLineEnd(line); if (line == layout.getLineCount() - 1) { return(end); } else { return(end - 1); } } }