源码下载 , 效果图如下:

1. 自定义视图继承自ViewGroup,覆写onMeasure,onLayout,之前文章介绍过覆写这两个方法。
2. 提供两个方法供两个button使用,向左向右移动。调用startScroll (int startX, int startY, int dx, int dy)方法, 以提供的起始点和将要滑动的距离开始滚动。滚动会使用缺省值250ms作为持续时间。
3. 设置滚动的便宜量childView.offsetLeftAndRight(leftAndRightOffset);
4. 调用invalidate()进行重绘
5. 延迟短暂时间,返回执行3,4步骤
public class CustomViewGroup extends ViewGroup {
// ===========================================================
// Constants
// ===========================================================
private static final int DELAY_MILLIS = 1000 / 60;
// ===========================================================
// Fields
// ===========================================================
// 记录上次滚动的位置,用于计算滚动偏移量
private int mOffsetX = 0;
private Scroller mScroller = new Scroller(getContext());
private Handler mHandler = new Handler();
private Runnable mScrollerRunnable = new ScrollerRunnable();
// 每次滚动的距离
private int mScrollWidth = 300;
// ===========================================================
// Constructors
// ===========================================================
public CustomViewGroup(Context context) {
super(context);
}
public CustomViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
// ===========================================================
// Getter & Setter
// ===========================================================
/**
* 向右滚动
*/
public void scrollToRight() {
scroll(true);
}
/**
* 向左滚动
*/
public void scrollToLeft() {
scroll(false);
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
int measuredWidth = childView.getMeasuredWidth();
int measuredHeight = childView.getMeasuredHeight();
childView.layout(mOffsetX, 0, mOffsetX + measuredWidth, measuredHeight);
}
}
// ===========================================================
// Methods
// ===========================================================
private void scroll(boolean scrollToRight) {
// 向右滚动举例是正值,反之负值
int scrollWidth = scrollToRight ? mScrollWidth: -mScrollWidth;
// 此次滚动的X轴终点位置
int scrollFinalX = mOffsetX + scrollWidth;
// 不能移出边界
if (scrollFinalX > 300 || scrollFinalX < 0) {
return;
}
// 清除
mHandler.removeCallbacks(mScrollerRunnable);
// 触发开始滚动
mScroller.startScroll(mOffsetX, 0, scrollWidth, 0);
// 子线程中间隔段时间重绘视图
mHandler.post(mScrollerRunnable);
}
/**
* 设置view滚动后的x坐标的位置
*
* @param offsetX
*/
private void setOffsetX(int offsetX) {
if (offsetX == mOffsetX) {
return;
}
final int leftAndRightOffset = offsetX - mOffsetX;
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
childView.offsetLeftAndRight(leftAndRightOffset);
}
mOffsetX = offsetX;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
private class ScrollerRunnable implements Runnable {
@Override
public void run() {
final Scroller scroller = mScroller;
if (scroller.computeScrollOffset()) {
setOffsetX(scroller.getCurrX());
// 位置发生偏移,重绘
invalidate();
// 每过间隔时间,再次执行当前子线程
mHandler.postDelayed(this, DELAY_MILLIS);
}
}
}
}
扩展:
学习下Scroller原理
原文地址:http://blog.csdn.net/love_world_/article/details/8126234
本文介绍了如何在Android中使用Scroller实现视图的自动滚动。通过自定义视图继承ViewGroup,并覆写onMeasure和onLayout方法。然后提供向左、向右移动的方法,利用Scroller的startScroll方法设定滚动参数,并在重绘后延迟执行滚动偏移和更新。此外,文章还提到了学习Scroller的工作原理。

1256

被折叠的 条评论
为什么被折叠?



