ScrollingMovementMethod.java revision 67b6ab72ae96a9f2be929de2c32c110df5390fdd
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text.method; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.*; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.TextView; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown/** 2567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown * A movement method that interprets movement keys by scrolling the text buffer. 2667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown */ 2767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brownpublic class ScrollingMovementMethod extends BaseMovementMethod implements MovementMethod { 2867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown private int getTopLine(TextView widget) { 2967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return widget.getLayout().getLineForVertical(widget.getScrollY()); 3067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown private int getBottomLine(TextView widget) { 3367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return widget.getLayout().getLineForVertical(widget.getScrollY() + getInnerHeight(widget)); 3467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown private int getInnerWidth(TextView widget) { 3767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return widget.getWidth() - widget.getTotalPaddingLeft() - widget.getTotalPaddingRight(); 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown private int getInnerHeight(TextView widget) { 4167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return widget.getHeight() - widget.getTotalPaddingTop() - widget.getTotalPaddingBottom(); 4267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown private int getCharacterWidth(TextView widget) { 4567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return (int) Math.ceil(widget.getPaint().getFontSpacing()); 4667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown private int getScrollBoundsLeft(TextView widget) { 4967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final Layout layout = widget.getLayout(); 5067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int topLine = getTopLine(widget); 5167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int bottomLine = getBottomLine(widget); 5267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (topLine > bottomLine) { 5367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return 0; 5467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 5567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int left = Integer.MAX_VALUE; 5667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown for (int line = topLine; line <= bottomLine; line++) { 5767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int lineLeft = (int) Math.floor(layout.getLineLeft(line)); 5867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (lineLeft < left) { 5967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown left = lineLeft; 6067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 6167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 6267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return left; 6367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown private int getScrollBoundsRight(TextView widget) { 6667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final Layout layout = widget.getLayout(); 6767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int topLine = getTopLine(widget); 6867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int bottomLine = getBottomLine(widget); 6967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (topLine > bottomLine) { 7067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return 0; 7167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 7267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int right = Integer.MIN_VALUE; 7367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown for (int line = topLine; line <= bottomLine; line++) { 7467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int lineRight = (int) Math.ceil(layout.getLineRight(line)); 7567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (lineRight > right) { 7667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown right = lineRight; 7767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return right; 8067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 8367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean left(TextView widget, Spannable buffer) { 8467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int minScrollX = getScrollBoundsLeft(widget); 8567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int scrollX = widget.getScrollX(); 8667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (scrollX > minScrollX) { 8767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown scrollX = Math.max(scrollX - getCharacterWidth(widget), minScrollX); 8867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown widget.scrollTo(scrollX, widget.getScrollY()); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return false; 9267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 9567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean right(TextView widget, Spannable buffer) { 9667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget); 9767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int scrollX = widget.getScrollX(); 9867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (scrollX < maxScrollX) { 9967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown scrollX = Math.min(scrollX + getCharacterWidth(widget), maxScrollX); 10067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown widget.scrollTo(scrollX, widget.getScrollY()); 10167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return true; 10267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean up(TextView widget, Spannable buffer) { 10867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final Layout layout = widget.getLayout(); 10967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int top = widget.getScrollY(); 11067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int topLine = layout.getLineForVertical(top); 11167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (layout.getLineTop(topLine) == top) { 11267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown // If the top line is partially visible, bring it all the way 11367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown // into view; otherwise, bring the previous line into view. 11467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown topLine -= 1; 11567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 11667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (topLine >= 0) { 11767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine)); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean down(TextView widget, Spannable buffer) { 12567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final Layout layout = widget.getLayout(); 12667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int innerHeight = getInnerHeight(widget); 12767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int bottom = widget.getScrollY() + innerHeight; 12867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int bottomLine = layout.getLineForVertical(bottom); 12967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (layout.getLineTop(bottomLine + 1) < bottom + 1) { 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Less than a pixel of this line is out of view, 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so we must have tried to make it entirely in view 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and now want the next line to be in view instead. 13367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown bottomLine += 1; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (bottomLine <= layout.getLineCount() - 1) { 13667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown Touch.scrollTo(widget, layout, widget.getScrollX(), 13767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown layout.getLineTop(bottomLine + 1) - innerHeight); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 14467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean pageUp(TextView widget, Spannable buffer) { 14567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final Layout layout = widget.getLayout(); 14667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int top = widget.getScrollY() - getInnerHeight(widget); 14767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int topLine = layout.getLineForVertical(top); 14867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (topLine >= 0) { 14967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine)); 15067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return true; 15167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 15267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return false; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 15667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean pageDown(TextView widget, Spannable buffer) { 15767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final Layout layout = widget.getLayout(); 15867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int innerHeight = getInnerHeight(widget); 15967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int bottom = widget.getScrollY() + innerHeight + innerHeight; 16067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int bottomLine = layout.getLineForVertical(bottom); 16167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (bottomLine <= layout.getLineCount() - 1) { 16267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown Touch.scrollTo(widget, layout, widget.getScrollX(), 16367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown layout.getLineTop(bottomLine + 1) - innerHeight); 16467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return true; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return false; 16767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 17067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean top(TextView widget, Spannable buffer) { 17167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final Layout layout = widget.getLayout(); 17267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (getTopLine(widget) >= 0) { 17367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(0)); 17467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return true; 17567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 17667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return false; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 18067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean bottom(TextView widget, Spannable buffer) { 18167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final Layout layout = widget.getLayout(); 18267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int lineCount = layout.getLineCount(); 18367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (getBottomLine(widget) <= lineCount - 1) { 18467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown Touch.scrollTo(widget, layout, widget.getScrollX(), 18567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown layout.getLineTop(lineCount) - getInnerHeight(widget)); 18667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return true; 18767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 19267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean lineStart(TextView widget, Spannable buffer) { 19367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int minScrollX = getScrollBoundsLeft(widget); 19467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int scrollX = widget.getScrollX(); 19567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (scrollX > minScrollX) { 19667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown widget.scrollTo(minScrollX, widget.getScrollY()); 19767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return true; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown 20267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 20367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean lineEnd(TextView widget, Spannable buffer) { 20467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget); 20567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown int scrollX = widget.getScrollX(); 20667b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown if (scrollX < maxScrollX) { 20767b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown widget.scrollTo(maxScrollX, widget.getScrollY()); 20867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return true; 20967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21267b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown 21367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 21467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean home(TextView widget, Spannable buffer) { 21567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return top(widget, buffer); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 21967b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown protected boolean end(TextView widget, Spannable buffer) { 22067b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return bottom(widget, buffer); 22167b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22367b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 22467b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { 22567b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown return Touch.onTouchEvent(widget, buffer, event); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22867b6ab72ae96a9f2be929de2c32c110df5390fddJeff Brown @Override 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onTakeFocus(TextView widget, Spannable text, int dir) { 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Layout layout = widget.getLayout(); 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (layout != null && (dir & View.FOCUS_FORWARD) != 0) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widget.scrollTo(widget.getScrollX(), 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout.getLineTop(0)); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (layout != null && (dir & View.FOCUS_BACKWARD) != 0) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int padding = widget.getTotalPaddingTop() + 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widget.getTotalPaddingBottom(); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = layout.getLineCount() - 1; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widget.scrollTo(widget.getScrollX(), 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout.getLineTop(line+1) - 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (widget.getHeight() - padding)); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static MovementMethod getInstance() { 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sInstance == null) 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sInstance = new ScrollingMovementMethod(); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sInstance; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static ScrollingMovementMethod sInstance; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 256