传承者(Inheritors)打造共同进步生态圈!!!
转载:http://write.blog.youkuaiyun.com/postedit/23692439
三段论:滑动所需要的准备,自定义ViewGoup,布局中使用
自定义ViewGoup
public class VerticalLinearLayout extends ViewGroup {
public class VerticalLinearLayout extends ViewGroup {
/**
* 屏幕的高度
*/
private int mScreenHeight;
/**
* 手指按下时的getScrollY
*/
private int mScrollStart;
/**
* 手指抬起时getScrollY
*/
private int mScrollEnd;
/**
* 记录移动时的Y
*/
private int mLastY;
/**
* 滚动的辅助类
*/
private Scroller mScroller;
/**
* 是否正在滚动
*/
private boolean isScrolling;
/**
* 加速度检测
*
*/
private VelocityTracker mVelocityTracker;
/**
* 记录当前页
*
*/
private int currentPage = 0;
private OnPageChangeListener mOnPageChangeListener;
private int childHeight;
public VerticalLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
/**
* 获得屏幕的高度
*/
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenHeight = outMetrics.heightPixels;
//初始化
mScroller = new Scroller(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i < count; i++) {
View childView = getChildAt(i);
measureChild(childView,widthMeasureSpec,mScreenHeight);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if(changed){
int childCount = getChildCount();
//设置主布局的高度
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
lp.height = mScreenHeight*childCount;
setLayoutParams(lp);
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if(child.getVisibility() != View.GONE){
child.layout(l,i*mScreenHeight,r,(i+1)*mScreenHeight);//调用每个自布局的layout
}
childHeight = getChildAt(0).getMeasuredHeight();
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//如果当前正在滚动,调用父类的onTouchEvent
if (isScrolling) {
return super.onTouchEvent(event);
}
int action =event.getAction();
int y = (int)event.getY();
obtainVelocity(event);
switch (action){
case MotionEvent.ACTION_DOWN:
mScrollStart = getScrollY();
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
if(!mScroller.isFinished()){
mScroller.abortAnimation();
}
int dy = mLastY - y;
//边际值检查
int scrollY = getScrollY();
//已经到达顶端,下拉多少,就往上滚动多少
if(dy<0 && scrollY+dy < 0 ){
dy = -scrollY;
}
//已经达到底部了,上拉多少,留往下滚动多少
if(dy>0 && scrollY+dy > getHeight() - mScreenHeight){
dy = getHeight() - mScreenHeight - scrollY;
}
scrollBy(0,dy);
mLastY = y;
break;
case MotionEvent.ACTION_UP:
mScrollEnd = getScrollY();
int dScrollY = mScrollEnd - mScrollStart;
if(wantScrollToNext()){
//往上滑动
if(shouldScrollToNext()){
mScroller.startScroll(0,getScrollY(),0, mScreenHeight - dScrollY);
}else{
mScroller.startScroll(0,getScrollY(),0,-dScrollY);
}
}
if(wantScrollToPre()){
//往下下滑
if(shouldScrollToPre()){
mScroller.startScroll(0,getScrollY(),0,-mScreenHeight - dScrollY);
}else{
mScroller.startScroll(0,getScrollY(),0 , -dScrollY);
}
}
isScrolling = true;
postInvalidateDelayed(0);
recycleVelocity();
break;
}
return true;
}
/**
* 根据滚动距离判断是否能够滚动到下一页
*/
private boolean shouldScrollToNext() {
return mScrollEnd - mScrollStart > mScreenHeight / 2 || Math.abs(getYVelocity()) > 600;
}
/**
* 根据用户滑动,判断用户的意图是否是滚动到下一页
*
*/
private boolean wantScrollToNext(){
return mScrollEnd> mScrollStart ;
}
/**
* 根据滚动距离判断是否能够滚动到上一页
* @return
*/
private boolean shouldScrollToPre(){
return -mScrollEnd + mScrollStart > mScreenHeight / 2 || Math.abs(getYVelocity())>600;
}
/**
* 根据用户滑动,判断用户意图是否是滚动到上一页
* @return
*/
private boolean wantScrollToPre(){
return mScrollEnd < mScrollStart;
}
@Override
public void computeScroll() {
super.computeScroll();
if(mScroller.computeScrollOffset()){
scrollTo(0,mScroller.getCurrY());
postInvalidate();
}else {
int position = getScrollY() / mScreenHeight;
if(position != currentPage){
if(mOnPageChangeListener!= null){
currentPage = position;
mOnPageChangeListener.onPageChange(currentPage);
}}
isScrolling = false;
}
}
/**
* 初始化加速度检测器
* @param event
*/
private void obtainVelocity(MotionEvent event) {
if(mVelocityTracker == null){
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
/**
* 资源释放
*/
private void recycleVelocity(){
if(mVelocityTracker != null){
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
/**
* 设置回调接口
* @param onPageChangeListener
*/
public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener){
mOnPageChangeListener = onPageChangeListener;
}
public int getYVelocity() {
mVelocityTracker.computeCurrentVelocity(1000);
return (int) mVelocityTracker.getYVelocity();
}
public interface OnPageChangeListener{
void onPageChange(int currentPage);
}
}
布局出来
<com.example.administrator.testapplication.VerticalLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/id_main_ly"
android:background="#fff"
tools:context="com.example.administrator.testapplication.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/shenang"
>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/dragon_boat"
>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/zhagao"
>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/dragon_boat_fes"
>
</RelativeLayout>
</com.example.administrator.testapplication.VerticalLinearLayout>
在Activity中使用
public class MainActivity extends Activity {
private VerticalLinearLayout mMainLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainLayout = (VerticalLinearLayout) findViewById(R.id.id_main_ly);
mMainLayout.setOnPageChangeListener(new VerticalLinearLayout.OnPageChangeListener() {
@Override
public void onPageChange(int currentPage) {
Toast.makeText(MainActivity.this, "第"+(currentPage+1)+"页", Toast.LENGTH_SHORT).show();
}
});
}
}