其实要让TextView能够滚动,可以使用ScrollView/HorizontalScrollView或者设置ScrollingMovementMethod来实现。
点击查看:android实现TextView垂直或水平滚动

下面自定义垂直滚动的TextView,主要是用来学习Scroller的使用。关于ScrollTextView的实现,可以看下面的介绍和源码。

package com.orgcent.demo.view;

import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.ViewConfiguration;import android.view.animation.DecelerateInterpolator;import android.widget.Scroller;import android.widget.TextView;/** * 配置android:scrollbars="vertical",启用垂直滚动条 *  * 实现水平滚动就是修改mScrollX,可参考HorizontalScrollView * * 滚动原理: 在绘制前对画布进行偏移操作 *  * 下面是View的绘制机制: * |- view.computeScroll()  --用来对mScrollX/Y进行修改。由于在绘制前调用,可调用invalite()来触发 * |- canvas.translate(-mScrollX,-mScrollY)  --偏移画布 * |- view.draw()  --绘制 *   * 上述内容可以在View.buildDrawingCache()或ViewGroup.dispatchDraw()->drawChild()中找到.直接查看方法名即可 *  * 滚动帮助类: * Scroller --用来计算滚动后的偏移值.具体请参考ScrollView和HorizontalScrollView * VelocityTracker --速度计算类。根据fling时的按下、抬起动作,计算滚动初速度 *  * ScrollTextView--流程解析: * 1、onTouchEvent() --使用Scroller来计算滚动偏移值 * 2、重写computeScroll() --对View的mScrollY进行修改, 此处控制滚动范围 * * 滚动范围: * 最小值:0 * 最大值:所有文本高度+内边距-View高度。也就是超出屏幕的文本高度*/public class ScrollTextView extends TextView {private Scroller mScroller;private int mTouchSlop;private int mMinimumVelocity;private int mMaximumVelocity;

private float mLastMotionY;private boolean mIsBeingDragged;private VelocityTracker mVelocityTracker;private int mActivePointerId = INVALID_POINTER;

private static final int INVALID_POINTER = -1;

public ScrollTextView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);    initView();    }

public ScrollTextView(Context context, AttributeSet attrs) {super(context, attrs);    initView();    }

public ScrollTextView(Context context) {super(context);    initView();    }

private void initView() {final Context cx = getContext(); //设置滚动减速器,在fling中会用到    mScroller = new Scroller(cx,new DecelerateInterpolator(0.5f));final ViewConfiguration configuration = ViewConfiguration.get(cx);        mTouchSlop = configuration.getScaledTouchSlop();        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();

    }

/**     * 此方法为最后机会来修改mScrollX,mScrollY.     * 这方法后将根据mScrollX,mScrollY来偏移Canvas已实现内容滚动*/    @Overridepublic void computeScroll() { super.computeScroll();

final Scroller scroller = mScroller;if(scroller.computeScrollOffset()) { //正在滚动,让view滚动到当前位置        int scrollY = scroller.getCurrY();final int maxY = (getLineCount() * getLineHeight() + getPaddingTop() + getPaddingBottom()) - getHeight();boolean toEdge = scrollY < 0 || scrollY > maxY;if(scrollY < 0)             scrollY = 0;else if(scrollY > maxY)            scrollY = maxY;

/*         *下面等同于:         * mScrollY = scrollY;         * awakenScrollBars(); //显示滚动条,必须在xml中配置。          * postInvalidate(); */        scrollTo(0, scrollY);if(toEdge) //移到两端,由于位置没有发生变化,导致滚动条不显示            awakenScrollBars();        }    }

public void fling(int velocityY) {final int maxY = (getLineCount() * getLineHeight() + getPaddingTop() + getPaddingBottom()) - getHeight();

        mScroller.fling(getScrollX(), getScrollY(), 0, velocityY, 0, 0, 0,                 Math.max(0, maxY));

//刷新,让父控件调用computeScroll()        invalidate();    }

    @Overridepublic boolean onTouchEvent(MotionEvent ev) {/*     * 事件处理方式:先自己处理后交给父类处理。     * PS:方式不同,可能导致效果不同。请根据需求自行修改。*/boolean handled = false;final int contentHeight = getLineCount() * getLineHeight();if(contentHeight > getHeight()) {        handled = processScroll(ev);      }

return handled | super.onTouchEvent(ev);    }

private boolean processScroll(MotionEvent ev) {boolean handled = false;if (mVelocityTracker == null) {            mVelocityTracker = VelocityTracker.obtain();        }        mVelocityTracker.addMovement(ev); //帮助类,用来在fling时计算移动初速度

final int action = ev.getAction();

switch (action) {case MotionEvent.ACTION_DOWN: {if(!mScroller.isFinished()) {        mScroller.forceFinished(true);        }

        mLastMotionY = ev.getY();            mActivePointerId = ev.getPointerId(0);            mIsBeingDragged = true;            handled = true;break;    }case MotionEvent.ACTION_MOVE: {final int pointerId = mActivePointerId;if(mIsBeingDragged && INVALID_POINTER != pointerId) {final int pointerIndex = ev.findPointerIndex(pointerId);final float y = ev.getY(pointerIndex);int deltaY = (int) (mLastMotionY - y);

if(Math.abs(deltaY) > mTouchSlop) { //移动距离(正负代表方向)必须大于ViewConfiguration设置的默认值            mLastMotionY = y;

/*             * 默认滚动时间为250ms,建议立即滚动,否则滚动效果不明显             * 或者直接使用scrollBy(0, deltaY);*/            mScroller.startScroll(getScrollX(), getScrollY(), 0, deltaY, 0);             invalidate();             handled = true;        }        }break;    }case MotionEvent.ACTION_UP: {final int pointerId = mActivePointerId;if(mIsBeingDragged && INVALID_POINTER != pointerId) {final VelocityTracker velocityTracker = mVelocityTracker;        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);int initialVelocity = (int) velocityTracker.getYVelocity(pointerId);

if(Math.abs(initialVelocity) > mMinimumVelocity) {            fling(-initialVelocity);        }

        mActivePointerId = INVALID_POINTER;                mIsBeingDragged = false;

if (mVelocityTracker != null) {                    mVelocityTracker.recycle();                    mVelocityTracker = null;                }

                handled = true;       }break;    }    }return handled;   }    }

测试DEMO: 点击查看

转: http://orgcent.com/android-custom-vertical-scroll-textview/

转载于:https://www.cnblogs.com/shanzei/archive/2012/03/28/2421179.html

android自定义View-垂直滚动的TextView相关推荐

  1. Android自定义view,圆形的TextView,并通过xml设置属性,AttributeSet中取值

    Android自定义view设置xml属性 一个圆形的自定义TextView,通过xml来设置背景颜色的属性 values/attrs <declare-styleable name=" ...

  2. Android自定义View精品(LimitScrollerView-仿天猫广告栏上下滚动效果)

    版权声明:本文为openXu原创文章[openXu的博客],未经博主允许不得以任何形式转载 文章目录 1.分析 2.定义组合控件布局 3.继承最外层控件 4.自定义属性 5.重写onMeasure 6 ...

  3. [Android]自定义View带效果的滚动数字

    [Android]自定义View带效果的滚动数字 @Author GQ 2016年07月29日 一个可以让数字滚动的View,可以自定义参数,是想要的那种效果! 原文github地址 效果图 Andr ...

  4. Android 自定义View(四)实现股票自选列表滑动效果

    一.前言 Android 开发过程中自定义 View 真的是无处不在,随随便便一个 UI 效果,都会用到自定义 View.前面三篇文章已经讲过自定义 View 的一些案例效果,相关类和 API,还有事 ...

  5. 【朝花夕拾】Android自定义View之(一)手把手教你看懂View绘制流程——向源码要答案

    前言 原文:Android自定义View之(一)手把手教你看懂View绘制流程--向源码要答案 View作为整个app的颜值担当,在Android体系中占有重要的地位.深入理解Android View ...

  6. Android 自定义View合集

    http://blog.csdn.net/u011507982/article/details/51199644 自定义控件学习  https://github.com/GcsSloop/Androi ...

  7. Android自定义View绘制流程

    Android视图层次结构简介 在介绍View绘制流程之前,咱们先简单介绍一下Android视图层次结构以及DecorView,因为View的绘制流程的入口和DecorView有着密切的联系. 我们平 ...

  8. Android自定义view之基础知识

    Android自定义view之基础知识 虽然Android已经自带了很多实用的view和layout,加以调教能实现很美观的界面,但是有一些情况下,需要实现特殊的界面效果,比如我们比较熟悉的各种播放器 ...

  9. Android 自定义View

    [Android 自定义View] Android 自定义View 自定义View基础 自定义TextView 继承View重写onDraw方法 View的构造方法 自定义属性 创建attrsxml文 ...

最新文章

  1. hdu1042 java_N! hdu1042 | 学步园
  2. oracle loder nextval,ORA-07445: 出现异常错误: 核心转储
  3. Missing artifact log4j:log4j:bundle:1.2.17
  4. 【渝粤题库】陕西师范大学201981教育统计与测量 作业 (专升本、高起本)
  5. “约见”面试官系列之常见面试题第七篇说说Vue的生命周期(建议收藏)
  6. [C++] 哈希计数
  7. java 多线程同步 通过实现Runnable的示例
  8. 11-6渐变的用途和设定技巧
  9. zipkin使用_我的Spring Cloud(十):Zipkin 服务跟踪
  10. MyBatis3源码解析(3)查询语句执行
  11. python怎么使用-Python中__all__作用何在以及如何使用?
  12. MP算法和OMP算法及其思想与实现
  13. 科睿唯安官网更新SCI期刊列表,慎投2月已被剔除期刊
  14. 【墙裂推荐】二维码生成器哪个好?
  15. 微信小游戏保存自定义分享图到相册实例
  16. 使用旋转动画实现刻度表
  17. MySQL数据库灵魂拷问
  18. linux电脑访问android手机存储
  19. 基于STM32设计的智能家居控制系统设计_语音+环境检测(OneNet)_2022
  20. 【十万个BUG】npx mrm lint-staged报错

热门文章

  1. PDF文档怎么提取其中一页
  2. Silence - 专注于阅读的博客园主题
  3. 面试题:函数回调机制、异步函数回调机制图例详解 没毛用
  4. 树莓派迅雷远程下载 | 树莓派小无相系列
  5. wap开发中取到真实的手机号码
  6. 【原】自定义UINavigationItem的两种方法以及相应的隐藏方法
  7. 多线程程序 怎样查看每个线程的cpu占用
  8. 腾讯是一只邪恶的小企鹅
  9. JavaScript继承详解(四) 转
  10. iOS开发UI篇—实现UITableview控件数据刷新