Android 左右滑屏效果

View Code
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:orientation="vertical" >



    <com.login.setup.SwitchLayout

        android:id="@+id/switchLayoutID"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent" >



        <LinearLayout

            android:layout_width="fill_parent"

            android:layout_height="fill_parent"

            android:background="@drawable/yindao_image_01" />



        <LinearLayout

            android:layout_width="fill_parent"

            android:layout_height="fill_parent"

            android:background="@drawable/yindao_image_02" />



        <LinearLayout

            android:layout_width="fill_parent"

            android:layout_height="fill_parent"

            android:background="@drawable/yindao_image_03" />

    </com.login.setup.SwitchLayout>



    <LinearLayout

        android:id="@+id/linerLayoutID"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentBottom="true"

        android:layout_centerHorizontal="true"

        android:layout_marginBottom="24dip"

        android:orientation="horizontal" >



        <TextView

            android:layout_width="18sp"

            android:layout_height="18sp"

            android:layout_gravity="center_vertical"

            android:background="@drawable/guide_round"

            android:clickable="true"

            android:gravity="center"

            android:textSize="15sp" />



        <TextView

            android:layout_width="18sp"

            android:layout_height="18sp"

            android:layout_gravity="center_vertical"

            android:background="@drawable/guide_round"

            android:clickable="true"

            android:gravity="center"

            android:textSize="15sp" />



        <TextView

            android:layout_width="18sp"

            android:layout_height="18sp"

            android:layout_gravity="center_vertical"

            android:background="@drawable/guide_round"

            android:clickable="true"

            android:gravity="center"

            android:textSize="15sp" />

    </LinearLayout>



</RelativeLayout>

以上xml文件中引用的guide_round.xml   (页面滑动下面的实心圈和空心圈)

View Code
<?xml version="1.0" encoding="utf-8"?>



<selector xmlns:android="http://schemas.android.com/apk/res/android">

   <item android:state_enabled="true" android:drawable="@drawable/guide_dot_black" />

   <item android:state_enabled="false" android:drawable="@drawable/guide_dot_white" />

</selector>


自定义组件 SwitchLayout

View Code
public class SwitchLayout extends ViewGroup {



    private int mCurScreen;

    // 瞬间速度

    private static final int SNAP_VELOCITY = 600;

    // 改变imageView

    private OnViewChangeListener onViewChangeListener;

    // 拖动手势的速率跟踪器

    private VelocityTracker tracker;

    // 滚动控制器

    private Scroller scroller;

    private float mLastMotionX;

    private Context context;



    public SwitchLayout(Context context) {

        super(context);

        this.context = context;

        init(context);

    }



    public SwitchLayout(Context context, AttributeSet attrs) {

        super(context, attrs);

        this.context = context;

        init(context);

    }



    public SwitchLayout(Context context, AttributeSet attrs, int defStyle) {

        super(context, attrs, defStyle);

        this.context = context;

        init(context);

    }



    /** 初始化控件 */ 

    private void init(Context context) {

        mCurScreen = 0;

        scroller = new Scroller(context);

    }



    @Override /** 必须要调用的方法 目的:当前的view在给自己的子控件指派大小和位置必须要调用的方法 */

    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        if (changed) {

            int childLeft = 0;

            int childCount = getChildCount();

            for (int i = 0; i < childCount; i++) {

                View childView = getChildAt(i);

                if (childView.getVisibility() != View.GONE) {

                    int childWidth = childView.getMeasuredWidth();

                    // 子控件被填充在父控件中(第二个阶段,第一个阶段为onMeasure,即计算)

                    childView.layout(childLeft, 0, childLeft + childWidth,

                            childView.getMeasuredHeight());

                    // 改变左边的起始位置

                    childLeft += childWidth;

                }

            }

        }

    }



    @Override  /** 计算控件的宽和高 */

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = MeasureSpec.getSize(widthMeasureSpec);

        int count = getChildCount();

        for (int i = 0; i < count; i++) {

            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);

        }

        // 滚到到哪一屏,通过width来控制

        scrollTo(mCurScreen * width, 0);

    }



    public void setOnViewChangeListener(OnViewChangeListener changeListener) {

        this.onViewChangeListener = changeListener;

    }



    /**

     * 设置自定义控件中的哪个子控件展示在当前屏幕中

     * @param pos

     */

    public void snapToScreen(int pos) {

        //System.out.println("当前的位置:" + pos);

        if (getScrollX() != (pos * getWidth())) {

            int destina = pos * getWidth() - getScrollX();// 要移动的距离

            // 开始滚动,从起始地开始,后两个参数为滚动的距离。用坐标来表示

            scroller.startScroll(getScrollX(), 0, destina, 0);

            mCurScreen = pos;

            // 在主线程中调用这个方法来重绘view,必须在主线程中调用

            invalidate();

            // 改变imageView的显示(根据guide_round.xml可以看出,当状态enabled的

            // 的时候,用黑点表示,也就是不是当前选中。)

            //System.out.println("ImageView改变监听" + onViewChangeListener);

            if (onViewChangeListener != null) {

                onViewChangeListener.onViewChange(pos);

            }

        }



    }



    @Override

    public void computeScroll() {

        if (scroller.computeScrollOffset()) {

            scrollTo(scroller.getCurrX(), scroller.getCurrY());

            postInvalidate();

        }

    }



    @Override

    public boolean onTouchEvent(MotionEvent event) {

        // Return the kind of action being performed --

        // one of either ACTION_DOWN, ACTION_MOVE, ACTION_UP, or ACTION_CANCEL.

        int action = event.getAction();

        /**

         * 屏幕上的每一次触摸都会被onTouchEvent捕获到,可以从event得到其x,y的值。

         * 特别注意:并且得到的是你当前的触点的x,y坐标的值,也就是说,往左划动的话, 你的x的值是变小的。

         */

        float x = event.getX();

        //System.out.println("onTouchEvent--" + x);

        switch (action) {

        // 按下

        case MotionEvent.ACTION_DOWN:

            if (tracker == null) {

                tracker = VelocityTracker.obtain();

                tracker.addMovement(event);

            }

            if (!scroller.isFinished())

                // 防止scroller滚动到最终的x和y的位置

                scroller.abortAnimation();

            mLastMotionX = x;

            //System.out.println("mLastMotionX--" + mLastMotionX);

            break;

        // 移动

        case MotionEvent.ACTION_MOVE:

            // 开始位置的触点与当前位置的差值

            int deltalX = (int) (mLastMotionX - x);

            if (canMove(deltalX)) {

                if (tracker != null) {

                    tracker.addMovement(event);

                }

                mLastMotionX = x;

                // 控件滚动的位置

                scrollBy(deltalX, 0);

            }

            break;

        

        // 松手

        case MotionEvent.ACTION_UP:  

            /** 往左滑动,因为x是在减小,所以横向速率是负值。 往右滑动,因为x是在增大,所以横向速率是正值。 */

            int velocityX = 0;

            if (tracker != null) {

                tracker.addMovement(event);

                tracker.computeCurrentVelocity(1000);// 计算1s滚动的速度

                //System.out.println("tracker -- " + tracker);

                velocityX = (int) tracker.getXVelocity();// 得到最终的横向速率

                //System.out.println("横向速率--" + velocityX);

                //System.out.println("mCurScreen--" + mCurScreen);

            }

            // 不是第一屏,且是往右滑动

            if (velocityX > SNAP_VELOCITY && mCurScreen > 0)

                snapToScreen(mCurScreen - 1);

            // 往左滑动,且不是最后一个

            else if (velocityX < -SNAP_VELOCITY

                    && mCurScreen < (getChildCount() - 1)) {

                snapToScreen(mCurScreen + 1);

            }

            // 往左滑动,且是最后一个,这里直接finish掉activity

            else if (velocityX == 0 && mCurScreen == (getChildCount() - 1)) {

                //System.out.println("-----------");

                Activity activity = (Activity) context;

                Intent intent = new Intent();

                intent.setClass(context, LandingTwoActivity.class);

                context.startActivity(intent);

                activity.finish();

            }

            else { // 速率不够快是,另一种跳转方式

                snapToDestination();

            }

            if (tracker != null) {

                tracker.recycle();

                tracker = null;

            }

            break;

        }

        return true;

    }



    /** 滑动到下一屏 */ 

    private void snapToDestination() {

        int screenWidth = getWidth();

        // 最终滑动的位置超过1\2时,才滚动,否则,destScreen得到将是当前屏的值。

        int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;

        snapToScreen(destScreen);

    }



    /** 可滚动的条件 */ 

    private boolean canMove(int deltalX) {

        // getScrollX(),得到触点view在左边的x轴的坐标,它的值是从第一张图到最后一张图算的,

        // 也就是说:getScrollX()得到的值是 将整个图展开,然后相对的那个x坐标。

        // 显示的是第一张图,并且是往右划

        if (getScrollX() <= 0 && deltalX < 0) {

            return false;

        }

        // 显示的是最后一张图并且是往左划

        if (getScrollX() >= (getChildCount() - 1) * getWidth() && deltalX > 0) {

            return false;

        }

        return true;

    }



}

SetupPageActivity加载显示效果

View Code
public class SetupPageActivity extends Activity {



    private static String TAG = "SetupPageActivity1";

    private SwitchLayout switchLayout;

    private LinearLayout linearLayout;

    private TextView bottom_img[]; // 底部的ImageView

    private int viewCount; // 自定义控件中子控件的个数

    private int viewSel; // 当前选中的ImageView



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        // TODO Auto-generated method stub

        super.onCreate(savedInstanceState);



        requestWindowFeature(Window.FEATURE_NO_TITLE);



        super.setContentView(R.layout.setup_page1);



        init();

    }



    private void init() {

        switchLayout = (SwitchLayout) findViewById(R.id.switchLayoutID);

        linearLayout = (LinearLayout) findViewById(R.id.linerLayoutID);



        // 得到子控件的个数

        viewCount = switchLayout.getChildCount();

        bottom_img = new TextView[viewCount];



        // 设置imageView

        for (int i = 0; i < viewCount; i++) {

            // 得到LinearLayout中的子控件(底部)

            bottom_img[i] = (TextView) linearLayout.getChildAt(i);

            bottom_img[i].setEnabled(true); // 控件激活

            bottom_img[i].setTag(i);

            bottom_img[i].setOnClickListener(new MOnClickListener());

            bottom_img[i].getPaint().setFakeBoldText(true);

        }



        // 设置第一个imageView不被激活

        viewSel = -1;

        int initCurScreen = 0;

        setCurPoint(initCurScreen);

        switchLayout.snapToScreen(initCurScreen);

        // bottom_img[viewSel].setEnabled(false);

        switchLayout.setOnViewChangeListener(new MOnViewChangeListener());

    }



    /** bottom_img点击事件的监听器 */

    private class MOnClickListener implements OnClickListener {

        @Override

        public void onClick(View v) {

            int pos = (Integer) v.getTag();

            // 设置当前显示的ImageView

            setCurPoint(pos);

            // 设置自定义控件中的哪个子控件展示在当前屏幕中

            switchLayout.snapToScreen(pos);

        }

    }



    /** 设置当前显示的ImageView */

    private void setCurPoint(int pos) {

        if (pos < 0 || pos > viewCount - 1 || viewSel == pos)

            return;



        // 当前的imgaeView将可以被激活

        if (viewSel != -1) {

            bottom_img[viewSel].setEnabled(true);

            bottom_img[viewSel].setText(" ");

        }

        // 将要跳转过去的那个imageView变成不可激活

        bottom_img[pos].setEnabled(false);

        //bottom_img[pos].setText(" " + (pos + 1)+" " );

        viewSel = pos;

    }



    /** 自定义控件中View改变的事件监听 */

    private class MOnViewChangeListener implements OnViewChangeListener {

        @Override

        public void onViewChange(int view) {

            // TODO Auto-generated method stub

            Log.i(TAG, "view:--" + view);

            if (view < 0 || viewSel == view) {

                return;

            } else if (view > viewCount - 1) {

                Log.i(TAG, "finish activity");

                SetupPageActivity.this.finish();

            }

            setCurPoint(view);

        }

    }



}


以上Activity使用到的接口

View Code
public interface OnViewChangeListener {

   public void onViewChange(int view);

}

 

 

你可能感兴趣的:(android)