PullScrollView详解(六)——延伸拓展(listview中getScrollY()一直等于0、ScrollView中的overScrollBy)
来源:互联网 发布:电脑钢琴软件哪个好 编辑:程序博客网 时间:2024/04/28 15:01
延伸一:为什么PullScrollView中getScrollY()有值而ListView中的getScrollY()却一直为零
通过查源码,你会发现getScrollY()是View的一个方法。那ScrollView为什么getScrollY()有值呢?让我们仔细分析一下源码:
(1)、先看派生
ScrollView->FrameLayout->ViewGroup->View
ListView->AbsListView->AdapterView->ViewGroup->View
从上面的派生中都可以看出,全部都是派生自View,而且全部都没有对getScrollY()方法重写。那就奇怪了,大家都没有对它进行重写。那肯定是设置的问题了。
(2)、设置scrollY的区别
在View.java中,有两个函数能对ScrollY进行设置:
- public void setScrollY(int value) {
- scrollTo(mScrollX, value);
- }
- public void scrollTo(int x, int y) {
- if (mScrollX != x || mScrollY != y) {
- int oldX = mScrollX;
- int oldY = mScrollY;
- mScrollX = x;
- mScrollY = y;
- invalidateParentCaches();
- onScrollChanged(mScrollX, mScrollY, oldX, oldY);
- if (!awakenScrollBars()) {
- invalidate(true);
- }
- }
- }
(3)、ScrollVIew中的ScrollY的设置
由于ScrollView直接派生自FrameLayout,所以我们直接看ScrollView.java中做了什么就可以了。
首先,看setScrollY(int value)的用处,木有地方调。
好吧,那我们再来看看ScrollTo(int x,int y)用到的地方。
在OnTouchEvent()中,最关键的一句应该在这里:
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- mIsLayoutDirty = false;
- // Give a child focus if it needs it
- if (mChildToScrollTo != null && isViewDescendantOf(mChildToScrollTo, this)) {
- scrollToChild(mChildToScrollTo);
- }
- mChildToScrollTo = null;
- // Calling this with the present values causes it to re-clam them
- scrollTo(mScrollX, mScrollY);
- }
在每一次重绘时,都会调用scrollTo()重新设置mScrollY的值,所以,当我们在获取时,是可以获取到的。
那再来看看Listview中,是如何做的:
木有setScrollY(int value)和ScrollTo(int x,int y)的调用。貌似理解了为什么getScrollY()没值的原因了。
但为什么在上篇中重写OverScrollBy()时scrollY是有值的呢?那我们再找找overScrollBy()的整个调用流程:
首先在OnTouchEvent()的ACTION_MOVE中:(在AbsListView.java中)
- case MotionEvent.ACTION_MOVE: {
- …………
- final int y = (int) ev.getY(pointerIndex);
- switch (mTouchMode) {
- case TOUCH_MODE_DOWN:
- case TOUCH_MODE_TAP:
- case TOUCH_MODE_DONE_WAITING:
- // Check if we have moved far enough that it looks more like a
- // scroll than a tap
- startScrollIfNeeded(y);
- break;
- case TOUCH_MODE_SCROLL:
- case TOUCH_MODE_OVERSCROLL:
- scrollIfNeeded(y);
- break;
- }
- break;
- }
- private void scrollIfNeeded(int y) {
- final int rawDeltaY = y - mMotionY;
- final int deltaY = rawDeltaY - mMotionCorrection;
- int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
- if (mTouchMode == TOUCH_MODE_SCROLL) {
- if (y != mLastY) {
- ………………
- if (motionView != null) {
- // Check if the top of the motion view is where it is
- // supposed to be
- final int motionViewRealTop = motionView.getTop();
- if (atEdge) {
- // Apply overscroll
- int overscroll = -incrementalDeltaY -
- (motionViewRealTop - motionViewPrevTop);
- overScrollBy(0, overscroll, 0, mScrollY, 0, 0,
- 0, mOverscrollDistance, true);
- …………
- }
- mMotionY = y;
- invalidate();
- }
- mLastY = y;
- }
- } else if (mTouchMode == TOUCH_MODE_OVERSCROLL) {
- if (y != mLastY) {
- …………
- if (overScrollDistance != 0) {
- overScrollBy(0, overScrollDistance, 0, mScrollY, 0, 0,
- 0, mOverscrollDistance, true);
- …………
- }
- }
- …………
- }
- }
- }
在View.java中:
- /**
- * Scroll the view with standard behavior for scrolling beyond the normal
- * content boundaries. Views that call this method should override
- * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
- * results of an over-scroll operation.
- */
- protected boolean overScrollBy(int deltaX, int deltaY,
- int scrollX, int scrollY,
- int scrollRangeX, int scrollRangeY,
- int maxOverScrollX, int maxOverScrollY,
- boolean isTouchEvent) {
- …………
- int newScrollX = scrollX + deltaX;
- // Clamp values if at the limits and record
- final int left = -maxOverScrollX;
- final int right = maxOverScrollX + scrollRangeX;
- final int top = -maxOverScrollY;
- final int bottom = maxOverScrollY + scrollRangeY;
- boolean clampedX = false;
- if (newScrollX > right) {
- newScrollX = right;
- clampedX = true;
- } else if (newScrollX < left) {
- newScrollX = left;
- clampedX = true;
- }
- boolean clampedY = false;
- if (newScrollY > bottom) {
- newScrollY = bottom;
- clampedY = true;
- } else if (newScrollY < top) {
- newScrollY = top;
- clampedY = true;
- }
- onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
- return clampedX || clampedY;
- }
而View.java中的onOverScrolled()是一个空方法。从overScrollBy()方法上面的那一坨注释我们也不难看到,需要自己重写onOverScrolled()方法来实现overScorll的滚动。
- protected void onOverScrolled(int scrollX, int scrollY,
- boolean clampedX, boolean clampedY) {
- // Intentionally empty.
- }
- @Override
- protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
- if (mScrollY != scrollY) {
- onScrollChanged(mScrollX, scrollY, mScrollX, mScrollY);
- mScrollY = scrollY;
- invalidateParentIfNeeded();
- awakenScrollBars();
- }
- }
延伸二:ScrollView中重写overScrollBy()实现上、下拉滑动
就在上面对比源码的时候,偶然发现ScrollView竟然也重写onOverScrolled(),源码如下:(ScrollView.java中)- @Override
- protected void onOverScrolled(int scrollX, int scrollY,
- boolean clampedX, boolean clampedY) {
- // Treat animating scrolls differently; see #computeScroll() for why.
- if (!mScroller.isFinished()) {
- mScrollX = scrollX;
- mScrollY = scrollY;
- invalidateParentIfNeeded();
- if (clampedY) {
- mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange());
- }
- } else {
- super.scrollTo(scrollX, scrollY);
- }
- awakenScrollBars();
- }
下面就举个栗子来看下ScrollView中实现overScrollBy()的方法吧。
先看看效果图:
效果很明显,也没什么好说的,跟《PullScrollView详解(四)——完全使用listview实现下拉回弹(方法一)》 效果一样,其实实现方法也完全一样。下面就看看代码吧
1、重写ScrollView
代码如下,就是重写overScrollBy()方法,设置里面的maxOverScrollY的值。- public class OverScrollView extends ScrollView {
- //定义最大滚动高度
- int mContentMaxMoveHeight = 250;
- public OverScrollView(Context context) {
- super(context);
- }
- public OverScrollView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public OverScrollView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
- @Override
- protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
- return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mContentMaxMoveHeight, isTouchEvent);
- }
- }<span style="color:#660000;">
- </span>
2、主布局(main.xml)
布局很容易理解,就是在OverScrollView里,放一个TableLayout来填充数据- <?xml version="1.0" encoding="utf-8"?>
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <com.harvic.OverScrollView.OverScrollView
- android:id="@+id/scrollview"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <TableLayout
- android:id="@+id/table_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- </com.harvic.OverScrollView.OverScrollView>
- </FrameLayout><span style="color:#660000;">
- </span>
3、MainActivity.java数据填充
最后就是在MainActivity中对TableLayout进行数据填充,在第二篇和第三篇博客中都有填充的部分,代码都一样,就不再细讲了。- public class MainActivity extends Activity {
- private TableLayout mMainLayout;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- mMainLayout = (TableLayout) findViewById(R.id.table_layout);
- showTable();
- }
- public void showTable() {
- TableRow.LayoutParams layoutParams = new TableRow.LayoutParams(
- TableRow.LayoutParams.MATCH_PARENT,
- TableRow.LayoutParams.WRAP_CONTENT);
- layoutParams.gravity = Gravity.CENTER;
- layoutParams.leftMargin = 30;
- layoutParams.bottomMargin = 10;
- layoutParams.topMargin = 10;
- for (int i = 0; i < 30; i++) {
- TableRow tableRow = new TableRow(this);
- TextView textView = new TextView(this);
- textView.setText("Test pull down scroll view " + i);
- textView.setTextSize(20);
- textView.setPadding(15, 15, 15, 15);
- tableRow.addView(textView, layoutParams);
- if (i % 2 != 0) {
- tableRow.setBackgroundColor(Color.LTGRAY);
- } else {
- tableRow.setBackgroundColor(Color.WHITE);
- }
- final int n = i;
- tableRow.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Toast.makeText(getApplicationContext(), "Click item " + n, Toast.LENGTH_SHORT).show();
- }
- });
- mMainLayout.addView(tableRow);
- }
- }
- }
0 0
- PullScrollView详解(六)——延伸拓展(listview中getScrollY()一直等于0、ScrollView中的overScrollBy)
- PullScrollView详解(六)——延伸拓展(listview中getScrollY()一直等于0、ScrollView中的overScrollBy)
- PullScrollView详解(六)——延伸拓展(listview中getScrollY()一直等于0、ScrollView中的overScrollBy)
- PullScrollView详解(六)——延伸拓展(listview中getScrollY()一直等于0、ScrollView中的overScrollBy)
- PullScrollView详解(三)——PullScrollView实现
- PullScrollView详解(三)——PullScrollView实现
- PullScrollView详解(三)——PullScrollView实现
- PullScrollView详解(四)——完全使用listview实现下拉回弹(方法一)
- PullScrollView详解(五)——完全使用listview实现下拉回弹(方法二)
- PullScrollView详解(四)——完全使用listview实现下拉回弹(方法一)
- PullScrollView详解(五)——完全使用listview实现下拉回弹(方法二)
- PullScrollView详解(四)——完全使用listview实现下拉回弹(方法一)
- PullScrollView详解(五)——完全使用listview实现下拉回弹(方法二)
- PullScrollView详解(一)——自定义控件属性
- PullScrollView详解(一)——自定义控件属性
- PullScrollView详解(一)——自定义控件属性
- Android ListView滑动回弹——overScrollBy
- PullScrollView详解(二)——Animation、Layout与下拉回弹
- 1. PSR-1 --- 基本代码规范
- ios 获取音乐库音乐相关
- PullScrollView详解(五)——完全使用listview实现下拉回弹(方法二)
- SQL当天日期的信息
- 蓝桥杯 2015校内选拔试题 第五题:位平方和
- PullScrollView详解(六)——延伸拓展(listview中getScrollY()一直等于0、ScrollView中的overScrollBy)
- 设置ToggleButton、Switch、CheckBox和RadioButton的区别
- linux lsof命令详解
- Loader(异步加载数据)
- C# 对轻量级(IoC Container)依赖注入Unity的使用
- Qt之QTableView添加复选框(QAbstractTableModel)
- Game Design: Art and Concepts
- Django个人博客部署在SAE
- ssh服务器