仿ViewPager实现页面切换的动画效果
(1)自定义类继承ViewGroup,并实现一个构造方法和onLayout方法
public class MyScrollPager extends ViewGroup{
private Context ctx;
public MyScrollPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
//定义页面的布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
(2)在xml(activity_mian.xml)布局中添加自定义view
<com.bxf.myviewpager.MyScrollPager
android:id="@+id/mypager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
(3)在MainActivity中找到此view比添加几个子view
public class MainActivity extends Activity{
private int[] ids = {R.drawable.a1,R.drawable.a2,R.drawable.a3,R.drawable.a4,R.drawable.a5,R.drawable.a6};
private MyScrollPager scrollPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollPager = (MyScrollPager) findViewById(R.id.mypager);
for (int i = 0; i < ids.length; i++) {
ImageView image = new ImageView(this);
image.setBackgroundResource(ids[i]);
scrollPager.addView(image);//将imageview 添加到view中
}
}
}
(4)在MyScrollPager中找到新添加的子view,并指定其位置
//定义页面的布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//定义每一个view的布局
int count = getChildCount();
for (int i = 0; i < count; i++) {
View view = getChildAt(i);
view.layout(i*getWidth(), 0, getWidth() + i*getWidth(), getHeight());
}
}
(5)添加滑动监听事件,并实现滑动切换
GestureDetector gestureDetector = new GestureDetector(ctx, new OnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
scrollBy((int) distanceX, 0);//在屏幕上滑动
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
});//手势识别器
private float firstX = 0;//初始位置
private float offsetX = 0;//初始位置
private int currId = 0;//当前屏幕显示的图片ID
//设置滑动监听
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
gestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
firstX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
offsetX = event.getX() - firstX;
updateCurrId(offsetX);
//瞬间移动
scrollTo(currId * getWidth(), 0);
break;
}
return true;
}
//更新当前显示的图片ID
private void updateCurrId(float endX2) {
if(offsetX > getWidth()/2){
currId --;//上一张图片
}else if(offsetX < -getWidth()/2){
currId ++;//下一张图片
}
currId = (currId>0)?currId:0;
currId = (currId>=getChildCount()-1)?getChildCount()-1:currId;
}
(6)实现缓慢滚动效果
创建滚动类,Scroller管理滚动的位置
public class Scroller {
private int duration = 500;//需要滚动的时间
private float currX;//滚动到的当前位置
private float startX;
private float startY;
private float disX;
private float disY;
private long startTime;
private boolean isFinish;//是否结束了滚动--true->是
public void startScroll(float startX, float startY, float disX, float disY) {
this.startX = startX;
this.startY = startY;
this.disX = disX;
this.disY = disY;
this.startTime = SystemClock.uptimeMillis();
this.isFinish = false;
}
public boolean computeScrollOffset(){
if(isFinish){//滚动已经结束
return false;
}
long currTime = SystemClock.uptimeMillis();
long scrollTime = currTime - startTime;
//计算滚动到的当前位置
if(scrollTime < duration){
//正在滚动
currX = startX + disX*scrollTime/duration;
}else{
//滚动完成
currX = startX + disX;
isFinish = true;
}
return true;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public float getCurrX() {
return currX;
}
public void setCurrX(float currX) {
this.currX = currX;
}
}
(7)最后MianActivity中的代码如下
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
public class MyScrollPager extends ViewGroup{
private Context ctx;
private Scroller scroller;
public MyScrollPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.ctx = context;
init();
}
//定义页面的布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//定义每一个view的布局
int count = getChildCount();
for (int i = 0; i < count; i++) {
View view = getChildAt(i);
view.layout(i*getWidth(), 0, getWidth() + i*getWidth(), getHeight());
}
}
GestureDetector gestureDetector;//手势识别器
private float firstX = 0;//初始位置
private float offsetX = 0;//初始位置
private int currId = 0;//当前屏幕显示的图片ID
//设置滑动监听
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
gestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
firstX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
offsetX = event.getX() - firstX;
updateCurrId(offsetX);
//瞬间移动
scrollTo(currId * getWidth(), 0);
//缓慢移动
getScrollX();//代表左边缘总共滑动的距离距起始点的距离
scroller.startScroll(getScrollX(), 0,currId * getWidth() - getScrollX(),0);
break;
}
invalidate();//刷新界面,这个方法会导致computeScroll方法的执行
return true;
}
@Override
public void computeScroll() {
if(scroller.computeScrollOffset()){
float currX = scroller.getCurrX();
scrollTo((int) currX, 0);
invalidate();//刷新界面
}
}
//更新当前显示的图片ID
private void updateCurrId(float endX2) {
if(offsetX > getWidth()/2){
currId --;//上一张图片
}else if(offsetX < -getWidth()/2){
currId ++;//下一张图片
}
currId = (currId>0)?currId:0;
currId = (currId>=getChildCount()-1)?getChildCount()-1:currId;
}
private void init() {
scroller = new Scroller();
gestureDetector = new GestureDetector(ctx, new OnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
scrollBy((int) distanceX, 0);//在屏幕上滑动
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
});
}
}