今天没事,把以前感兴趣的一个android滑动翻页效果整理一下发在这里,欢迎大家指教。这个主要是通过学习android Launcher2的源码和网上的一些帖子总结出来的,帖子的地址就不一一列举了。简单起见我也用imageview展示了,如果换成其他的view道理一样。
首先奉上效果图。
第一页和第二页中间,能看到第一页的后半部分和第二页的前半部分,中间是黑色的分割线。 第1页,上面显示的数字是1。 第2页,上面显示的数字是2.
接下来贴上主要代码。
首先是这个FlatWorkSpace,沿用网上一帖子的取名,主要是因为Launcher里面叫WorkSpace. 这个是一个ViewGroup,在创建的时候添加了三个ImageView。然后构造方法的重写就不用说了。主要要重写的方法有dispatchDraw,onMeasure,onLayout,computeScroll,onTouchEvent,他们的作用从源代码中可以看出来。
package com.hhg.test.testscroll;
import com.hhg.test.testscroll.R;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Scroller;
public class FlatWorkSpace extends ViewGroup {
private float mTouchX;
private float mLastMotionX;
private int mActivePointerId = -1;
private Scroller mScroller;
public FlatWorkSpace(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FlatWorkSpace(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public void initScreen() {
Context context = getContext();
mScroller = new Scroller(context);
for (int i = 0; i < 3; i++) {
this.addView(new ImageView(this.getContext()), i);
}
((ImageView)this.getChildAt(0)).setImageResource(R.drawable.view_1);
((ImageView)this.getChildAt(1)).setImageResource(R.drawable.view_2);
((ImageView)this.getChildAt(2)).setImageResource(R.drawable.view_3);
}
@Override
protected void dispatchDraw(Canvas canvas) {
final long drawingTime = getDrawingTime();
final int count = getChildCount();
for (int i = 0; i < count; i++) {
drawChild(canvas, getChildAt(i), drawingTime);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
}
// The children are given the same width and height as the workspace
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childLeft = 0;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
final int childWidth = child.getMeasuredWidth();
child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
childLeft += childWidth;
}
}
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
mTouchX = mScroller.getCurrX();
int scrollY = mScroller.getCurrY();
scrollTo((int)mTouchX, scrollY);
postInvalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mLastMotionX = ev.getX();
mActivePointerId = ev.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
try {
final float x = ev.getX(pointerIndex);
final float deltaX = mLastMotionX - x;
mLastMotionX = x;
if (deltaX > 0) {
scrollBy((int)deltaX, 0);
} else if (deltaX < 0) {
scrollBy((int)deltaX, 0);
} else {
awakenScrollBars();
}
} catch (ArrayIndexOutOfBoundsException e) {
}
break;
case MotionEvent.ACTION_UP:
int screenWidth = getWidth();
int whichView = (getScrollX() + (screenWidth / 2)) / screenWidth;
whichView = Math.max(0, Math.min(whichView, getChildCount() - 1));
int newX = whichView * getWidth();
int delta = newX - getScrollX();
mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);
invalidate();
MainActivity.setLevel(whichView);
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
}
return true;
}
}
然后把这个view添加到activity的布局文件中。用包名加类名的方式。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/indicator_2"
android:visibility="invisible"
android:layout_centerHorizontal="true"
android:text="2"
android:textSize="20dip">
</TextView>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/indicator_1"
android:visibility="visible"
android:layout_toLeftOf="@id/indicator_2"
android:text="1"
android:textSize="20dip">
</TextView>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/indicator_3"
android:visibility="invisible"
android:layout_toRightOf="@id/indicator_2"
android:text="3"
android:textSize="20dip">
</TextView>
</RelativeLayout>
<com.hhg.test.testscroll.FlatWorkSpace
android:layout_height="365dip"
android:layout_width="fill_parent"
android:id="@+id/myid">
</com.hhg.test.testscroll.FlatWorkSpace>
<RelativeLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="3dip">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
android:layout_alignParentLeft="true">
</Button>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
android:layout_centerHorizontal="true">
</Button>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button3"
android:layout_alignParentRight="true">
</Button>
</RelativeLayout>
</LinearLayout>
然后就是在MainActivity中初始化这个viewgroup,在viewgroup滑动完成后修改上面的页数。
package com.hhg.test.testscroll;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
private static TextView sIndicator1;
private static TextView sIndicator2;
private static TextView sIndicator3;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FlatWorkSpace lws = (FlatWorkSpace) findViewById(R.id.myid);
lws.initScreen();
sIndicator1 = (TextView) findViewById(R.id.indicator_1);
sIndicator2 = (TextView) findViewById(R.id.indicator_2);
sIndicator3 = (TextView) findViewById(R.id.indicator_3);
}
public static void setLevel(int level) {
sIndicator1.setVisibility(level == 0 ? View.VISIBLE : View.INVISIBLE);
sIndicator2.setVisibility(level == 1 ? View.VISIBLE : View.INVISIBLE);
sIndicator3.setVisibility(level == 2 ? View.VISIBLE : View.INVISIBLE);
}
}
然后随便找几张图测试就是了,完了我会把源码打包传到csdn上,等有链接以后就把链接发到评论里面。欢迎大家送分。谢谢。
若水飞天