模拟android桌面的滑动翻页效果

今天没事,把以前感兴趣的一个android滑动翻页效果整理一下发在这里,欢迎大家指教。这个主要是通过学习android Launcher2的源码和网上的一些帖子总结出来的,帖子的地址就不一一列举了。简单起见我也用imageview展示了,如果换成其他的view道理一样。

首先奉上效果图。

 

[img4]                                

第一页和第二页中间,能看到第一页的后半部分和第二页的前半部分,中间是黑色的分割线。          第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上,等有链接以后就把链接发到评论里面。欢迎大家送分。谢谢。

 

若水飞天


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值