Android实现多页左右滑动效果,支持子view动态创建和cache
要实现多页滑动效果,主要是需要处理onTouchEvent和onInterceptTouchEvent,要处理好touch事件的子控件和父控件的传递问题。滚动控制可以利用android的Scroller来实现。
对于不清楚android Touch事件的传递过程的,先google一下。
这里提供两种做法:
1、自定义MFlipper控件,从ViewGroup继承,利用Scroller实现滚动,重点是onTouchEvent和onInterceptTouchEvent的重写,要注意什么时候该返回true,什么时候false。否则会导致界面滑动和界面内按钮点击事件相冲突。
由于采用了ViewGroup来管理子view,只适合于页面数较少而且较固定的情况,因为viewgroup需要一开始就调用addView,把所有view都加进去并layout,太多页面会有内存问题。如果是页面很多,而且随时动态增长的话,就需要考虑对view做cache和动态创建,动态layout,具体做法参考下面的方法二;
2、从AdapterView继承,参考Android自带ListView的实现,实现子view动态创建和cache,滑动效果等。源码如下:
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.Scroller;
/**
* 自定义一个横向滚动的AdapterView,类似与全屏的Gallery,但是一次只滚动一屏,而且每一屏支持子view的点击处理
* @author weibinke
*
*/
public class MultiPageSwitcher extends AdapterView<BaseAdapter> {
private BaseAdapter mAdapter = null;
private Scroller mScroller;
private int mTouchSlop;
private float mTouchStartX;
private float mLastMotionX;
private final static String TAG = "MultiPageSwitcher";
private int mLastScrolledOffset = 0;
/** User is not touching the list */
private static final int TOUCH_STATE_RESTING = 0;
/** User is scrolling the list */
private static final int TOUCH_STATE_SCROLL = 2;
private int mTouchState = TOUCH_STATE_RESTING;
private int mHeightMeasureSpec;
private int mWidthMeasureSpec;
private int mSelectedPosition;
private int mFirstPosition; //第一个可见view的position
private int mCurrentSelectedPosition;
private VelocityTracker mVelocityTracker;
private static final int SNAP_VELOCITY = 600;
protected RecycleBin mRecycler = new RecycleBin();
private OnPostionChangeListener mOnPostionChangeListener = null;
public MultiPageSwitcher(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
MLog.d("MultiPageSwitcher.onlayout start");
super.onLayout(changed, left, top, right, bottom);
if (mAdapter == null) {
return ;
}
recycleAllViews();
detachAllViewsFromParent();
mRecycler.clear();
fillAllViews();
MLog.d("MultiPageSwitcher.onlayout end");
}
/**
* 从当前可见的view向左边填充
*/
private void fillToGalleryLeft() {
int itemSpacing = 0;
int galleryLeft = 0;
// Set state for initial iteration
View prevIterationView = getChildAt(0);
int curPosition;
int curRightEdge;
if (prevIterationView != null) {
curPosition = mFirstPosition - 1;
curRightEdge = prevIterationView.getLeft() - itemSpacing;
} else {
// No children available!
curPosition = 0;
curRightEdge = getRight() - getLeft();
}
while (curRightEdge > galleryLeft && curPosition >= 0) {
prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
curRightEdge, false);
// Remember some state
mFirstPosition = curPosition;
// Set state for next iteration
curRightEdge = prevIterationView.getLeft() - itemSpacing;
curPosition--;
}
}
private void fillToGalleryRight() {
int itemSpacing = 0;
int galleryRight = getRight() - getLeft();
int numChildren = getChildCount();
int numItems = mAdapter.getCount();
// Set state for initial iteration
View prevIterationView = getChildAt(numChildren - 1);
int curPosition;
int curLeftEdge;
if (prevIterationView != null) {
curPosition = mFirstPosition + numChildren;
curLeftEdge = prevIterationView.getRight() + itemSpacing;
} else {
mFirstPosition = curPosition = numItems - 1;
curLeftEdge = 0;
}
补充:移动开发 , Android ,