• 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);
    }
  • 相关阅读:
    CSS选择器及优先级
    iframe中跨域页面访问parent的方法
    网页外链用了 target=_blank,结果悲剧了
    CarbonData:大数据融合数仓新一代引擎
    补习系列(14)-springboot redis 整合-数据读写
    python读写配置文件使用总结与避坑指南
    【云速建站】后台配置邮费
    解析:区块链的本质是伴随信息社会产生的一种新型生产关系
    用“黑科技”产放心粮,种地竟然和想象中有点不一样
    【云速建站】按照给定模板从0开始编辑网站页面
  • 原文地址:https://www.cnblogs.com/androidsj/p/3064928.html
Copyright © 2020-2023  润新知