Android-Scroller
/********************SpriteLayout.java**********************************/
package com.example.game;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.View.MeasureSpec;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.Toast;
public class SpriteLayout extends ViewGroup {
private float startX;
private int curL=1;
private int destL;
VelocityTracker velocity=null;
@Override
public void computeScroll() {
super.computeScroll();
if(mScroller.computeScrollOffset()){
scrollTo(mScroller.getCurrX(), 0);
postInvalidate();
}
}
public void startMove(){
//从开(startX,startY)点开始滑动到(startX+deltaX,startY+deltaY)点,如果终点在起点的左边或这下边,便会向左或向下滑动,如果在邮编或者上边便会向右或向上滑动
//起点和终点都是以view的左上角的坐标
mScroller.startScroll((curL-1)*getWidth(), 0, getWidth(), 0,3000);
curL++;
if(curL>=3)
curL=1;
invalidate();
}
private Scroller mScroller;
private float minDist;
private void init(){
mScroller=new Scroller(getContext());
LinearLayout l1=new LinearLayout(getContext());
l1.setBackgroundColor(Color.BLUE);
LinearLayout l2=new LinearLayout(getContext());
l2.setBackgroundColor(Color.CYAN);
LinearLayout l3=new LinearLayout(getContext());
l3.setBackgroundColor(Color.RED);
this.addView(l1);
this.addView(l2);
this.addView(l3);
minDist=ViewConfiguration.get(getContext()).getScaledEdgeSlop();
}
public SpriteLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
public SpriteLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//Toast.makeText(getContext(), "SpriteLayout touchevent"+event.getAction()+"return:"+super.onTouchEvent(event), Toast.LENGTH_SHORT).show();
if(velocity==null){
velocity = VelocityTracker.obtain();
}
velocity.addMovement(event);
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
startX=event.getX();
break;
case MotionEvent.ACTION_MOVE:
int delta=(int)(startX-event.getX());
scrollBy(delta, 0);
startX=event.getX();
break;
case MotionEvent.ACTION_UP:
//如果手指从左向右滑动velocity.getXVelocity()返回正数
//如果手指从右向左滑动velocity.getXVelocity()返回负数
velocity.computeCurrentVelocity(1000);//一秒钟划过多少个像素,原本的基本单位是一毫秒划过多少个像素
//getScrollX()就是viewgroup的左上角对应的视图的X坐标,当滑动的距离超过半屏的距离就当滑到下一屏,否则就是滑到当前屏
int dest=(getScrollX()+getWidth()/2)/getWidth();
//显示第N屏 scrollTo((N-1)*getWidth(),0) startScroll(getScrollX(),0,(N-1)*getWidth()-getScrollX(),0)
if(dest>getChildCount()-1){
dest=getChildCount()-1;//滑到最后一个view 最后显示到viewgroup的左上角的X坐标为 (getChildCount()-1)*getWidth()而不是(getChildCount())*getWidth()
}
mScroller.startScroll(getScrollX(),0,(int) (dest*getWidth()-getScrollX()),0);
invalidate();
curL=dest;
break;
default:
break;
}
return true;
}
public SpriteLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
// measure过程
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 设置该ViewGroup的大小
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
// 设置每个子视图的大小 , 即全屏
child.measure(getWidth(), getHeight());
}
}
// layout过程
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int startLeft = 0; // 每个子视图的起始布局坐标
int startTop = 0; // 间距设置为10px 相当于 android:marginTop= "10px"
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
//即使可见的,才划到屏幕上
if(child.getVisibility() != View.GONE)
//左上角的X,Y 右下角的X,Y
child.layout(startLeft, startTop,
startLeft + getWidth(),
startTop + getHeight() );
startLeft = startLeft + getWidth() ; //校准每个子View的起始布局位置
//三个子视图的在屏幕中的分布如下 [0 , 320] / [320,640] / [640,960]
}
}
}
/********************SpriteB.java**********************************/
package com.example.game;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
import android.widget.Toast;
public class SpriteB extends Button {
@Override
public void computeScroll() {
// TODO Auto-generated method stub
super.computeScroll();
}
public SpriteB(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public SpriteB(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public SpriteB(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
}
/********************SpriteActivity.java**********************************/
package com.example.game;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
public class SpriteActivity extends Activity {
SpriteB sprite;
SpriteLayout layout;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sprite=(SpriteB) findViewById(R.id.btn);
layout=(SpriteLayout) findViewById(R.id.layout);
sprite.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
layout.startMove();
}
});
}
}
/********************main.xml**********************************/
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.game.SpriteB
android:id="@+id/btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="this is a sprite button!"/>
<com.example.game.SpriteLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>