在Andoird使用Android自带的那些组件,像SlidingDrawer和DrawerLayout都是抽屉效果的菜单,但是在项目很多要实现的功能都收到Android这些自带组件的限制,导致很难完成项目的需求,自定义的组件,各方面都在自己的控制之下,从而根据需求做出调整。想要实现好的效果,基本上都的基于Android的OnTouch事件自己实现响应的功能。
首先,给大家先看一下整体的效果:


滑动的加速度效果都是有的,具体的体验,只能安装后才能查看。
接下来,看代码:
代码从MainActivity延伸出了2个类:MainController和MainView,MainController来处理控制层、MainView来操作展示层。
主要代码:
MainActivity的代码:

package com.example.wz;import com.example.wz.controller.MainController;import com.example.wz.util.MyLog;import com.example.wz.view.MainView;import android.app.Activity;import android.os.Bundle;import android.view.MotionEvent;public class MainActivity extends Activity {    public MyLog log = new MyLog(this, true);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        log.e("欢迎你加入测试项目.");        link();    }    public MainController mainController;    public MainView mainView;    private void link() {        this.mainController = new MainController(this);        this.mainView = new MainView(this);        this.mainController.thisView = this.mainView;        this.mainView.thisController = this.mainController;        this.mainView.initViews();    }    @Override    public boolean onTouchEvent(MotionEvent event) {        super.onTouchEvent(event);        return mainController.onTouchEvent(event);    }}

MainController的代码:

package com.example.wz.controller;import android.view.GestureDetector;import android.view.GestureDetector.SimpleOnGestureListener;import android.view.MotionEvent;import com.example.wz.MainActivity;import com.example.wz.util.MyLog;import com.example.wz.util.OpenLooper;import com.example.wz.util.OpenLooper.LoopCallback;import com.example.wz.view.MainView;public class MainController {    public MyLog log = new MyLog(this, true);    public MainActivity mainActivity;    public MainController thisController;    public MainView thisView;    public GestureDetector mGesture;    public MainController(MainActivity mainActivity) {        this.mainActivity = mainActivity;        this.thisController = this;        mGesture = new GestureDetector(mainActivity, new GestureListener());        openLooper = new OpenLooper();        openLooper.createOpenLooper();        loopCallback = new ListLoopCallback(openLooper);        openLooper.loopCallback = loopCallback;    }    public class TouchStatus {        public int None = 4, Down = 1, Horizontal = 2, Vertical = 3, Up = 4;// LongPress = 5        public int state = None;    }    public TouchStatus touchStatus = new TouchStatus();    public class BodyStatus {        public int Fixed = 0, Dragging = 1, Homing = 2, FlingHoming = 3, BoundaryHoming = 4;        public int state = Fixed;    }    public BodyStatus bodyStatus = new BodyStatus();    public class DrawStatus {        public int Closed = 0, Open = 1, GoClosing = 2, GoOpening = 3;        public int state = Closed;    }    public DrawStatus drawStatus = new DrawStatus();    public class AreaStatus {        public int A = 0, B = 1;        public int state = A;    }    public AreaStatus areaStatus = new AreaStatus();    public float touch_pre_x;    public float touch_pre_y;    public float currentTranslateX;    public boolean onTouchEvent(MotionEvent event) {        int action = event.getAction();        float x = event.getX();        float y = event.getY();        if (action == MotionEvent.ACTION_DOWN) {            this.touch_pre_x = x;            this.touch_pre_y = y;            if (touchStatus.state == touchStatus.None) {                touchStatus.state = touchStatus.Down;                log.e("Down ");                if (x > thisView.maxTranslateX) {                    areaStatus.state = areaStatus.B;                } else if (x <= thisView.maxTranslateX) {                    areaStatus.state = areaStatus.A;                }            }        } else if (action == MotionEvent.ACTION_MOVE) {            float Δy = (y - touch_pre_y);            float Δx = (x - touch_pre_x);            if (touchStatus.state == touchStatus.Down) {                if (Δx * Δx + Δy * Δy > 400) {                    if (Δx * Δx > Δy * Δy) {                        touchStatus.state = touchStatus.Horizontal;                    } else {                        touchStatus.state = touchStatus.Vertical;                    }                    touch_pre_x = x;                    touch_pre_y = y;                    log.e("ACTION_MOVE ");                }            } else if (touchStatus.state == touchStatus.Horizontal) {                currentTranslateX += Δx;                this.touch_pre_x = x;                this.touch_pre_y = y;                if (currentTranslateX - thisView.maxTranslateX <= 0 && currentTranslateX >= 0) {                    setPosition();                }                log.e("Horizontal");                bodyStatus.state = bodyStatus.Dragging;            } else if (touchStatus.state == touchStatus.Vertical) {                log.e("Vertical");                bodyStatus.state = bodyStatus.Dragging;            }        } else if (action == MotionEvent.ACTION_UP) {            log.e("ACTION_UP");            if (bodyStatus.state == bodyStatus.Dragging) {                if (touchStatus.state == touchStatus.Horizontal) {                    bodyStatus.state = bodyStatus.Homing;                    openLooper.start();                } else if (touchStatus.state == touchStatus.Vertical) {                    if (drawStatus.state == drawStatus.Open && areaStatus.state == areaStatus.B) {                        bodyStatus.state = bodyStatus.Homing;                        drawStatus.state = drawStatus.GoClosing;                        openLooper.start();                    }                }            } else if (touchStatus.state == touchStatus.Down && areaStatus.state == areaStatus.B) {                bodyStatus.state = bodyStatus.Homing;                drawStatus.state = drawStatus.GoClosing;                openLooper.start();            }            touchStatus.state = touchStatus.Up;        }        mGesture.onTouchEvent(event);        return true;    }    class GestureListener extends SimpleOnGestureListener {        @Override        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {            if (velocityX * velocityX + velocityY * velocityY > 250000) {                if (velocityX * velocityX > velocityY * velocityY) {                    log.e("velocityX--" + velocityX);                    if (drawStatus.state == drawStatus.Closed && velocityX < 0) {                    } else if (drawStatus.state == drawStatus.Open && velocityX > 0) {                    } else {                        dxSpeed = velocityX;                        bodyStatus.state = bodyStatus.FlingHoming;                        openLooper.start();                    }                } else {                    log.e("velocityY");                }            }            return true;        }        public void onLongPress(MotionEvent event) {        }        public boolean onDoubleTap(MotionEvent event) {            return false;        }        public boolean onDoubleTapEvent(MotionEvent event) {            return false;        }        public boolean onSingleTapUp(MotionEvent event) {            return false;        }        @Override        public boolean onSingleTapConfirmed(MotionEvent event) {            return false;        }        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {            return false;        }    }    public void setPosition() {        thisView.v1.setTranslationX(currentTranslateX - thisView.maxTranslateX);        thisView.v2.setTranslationX(Math.abs(currentTranslateX));    }    float transleteSpeed = 3f;    OpenLooper openLooper = null;    LoopCallback loopCallback = null;    public class ListLoopCallback extends LoopCallback {        public ListLoopCallback(OpenLooper openLooper) {            openLooper.super();        }        @Override        public void loop(double ellapsedMillis) {            if (bodyStatus.state == bodyStatus.Homing) {                hommingView((float) ellapsedMillis);            } else if (bodyStatus.state == bodyStatus.FlingHoming) {                flingHomingView((float) ellapsedMillis);            }        }    }    public float ratio = 0.0008f;    public void flingHomingView(float ellapsedMillis) {        float distance = (float) ellapsedMillis * transleteSpeed;        boolean isStop = false;        if (drawStatus.state == drawStatus.Closed) {            drawStatus.state = drawStatus.GoOpening;        } else if (drawStatus.state == drawStatus.Open) {            drawStatus.state = drawStatus.GoClosing;        }        if (drawStatus.state == drawStatus.GoClosing) {            this.currentTranslateX -= distance;            if (this.currentTranslateX <= 0) {                this.currentTranslateX = 0;                drawStatus.state = drawStatus.Closed;                isStop = true;                log.e("-------------1");            }        } else if (drawStatus.state == drawStatus.GoOpening) {            this.currentTranslateX += distance;            if (this.currentTranslateX >= thisView.maxTranslateX) {                this.currentTranslateX = thisView.maxTranslateX;                drawStatus.state = drawStatus.Open;                isStop = true;                log.e("-------------2");            }        }        setPosition();        if (isStop) {            openLooper.stop();        }    }    public float dxSpeed;    public void dampenSpeed(long deltaMillis) {        if (this.dxSpeed != 0.0f) {            this.dxSpeed *= (1.0f - 0.002f * deltaMillis);            if (Math.abs(this.dxSpeed) < 50f)                this.dxSpeed = 0.0f;        }    }    public void hommingView(float ellapsedMillis) {        float distance = (float) ellapsedMillis * transleteSpeed;        boolean isStop = false;        if (drawStatus.state == drawStatus.Closed && this.currentTranslateX < thisView.maxTranslateX / 5) {            this.currentTranslateX -= distance;            if (this.currentTranslateX <= 0) {                this.currentTranslateX = 0;                drawStatus.state = drawStatus.Closed;                isStop = true;            }        } else if (drawStatus.state == drawStatus.Closed && this.currentTranslateX >= thisView.maxTranslateX / 5) {            this.currentTranslateX += distance;            if (this.currentTranslateX >= thisView.maxTranslateX) {                this.currentTranslateX = thisView.maxTranslateX;                drawStatus.state = drawStatus.Open;                isStop = true;            }        } else if (drawStatus.state == drawStatus.Open && this.currentTranslateX < thisView.maxTranslateX / 5 * 4) {            this.currentTranslateX -= distance;            if (this.currentTranslateX <= 0) {                this.currentTranslateX = 0;                drawStatus.state = drawStatus.Closed;                isStop = true;            }        } else if (drawStatus.state == drawStatus.Open && this.currentTranslateX >= thisView.maxTranslateX / 5 * 4) {            this.currentTranslateX += distance;            if (this.currentTranslateX >= thisView.maxTranslateX) {                this.currentTranslateX = thisView.maxTranslateX;                drawStatus.state = drawStatus.Open;                isStop = true;            }        } else if (drawStatus.state == drawStatus.GoClosing) {            this.currentTranslateX -= distance;            if (this.currentTranslateX <= 0) {                this.currentTranslateX = 0;                drawStatus.state = drawStatus.Closed;                isStop = true;            }        }        setPosition();        if (isStop) {            openLooper.stop();            log.e("looper stop...");        }    }}

MainView的代码:

package com.example.wz.view;import android.graphics.Color;import android.util.DisplayMetrics;import android.view.ViewGroup.LayoutParams;import android.widget.RelativeLayout;import android.widget.TextView;import com.example.wz.MainActivity;import com.example.wz.R;import com.example.wz.controller.MainController;import com.example.wz.util.MyLog;public class MainView {    public MyLog log = new MyLog(this, true);    public MainActivity mainActivity;    public MainController thisController;    public MainView thisView;    public MainView(MainActivity mainActivity) {        this.mainActivity = mainActivity;        this.thisView = this;    }    public DisplayMetrics displayMetrics;    public float screenWidth;    public float screenHeight;    public float density;    public float maxTranslateX;    public RelativeLayout maxView;    public RelativeLayout v1;    public RelativeLayout v2;    public void initViews() {        this.displayMetrics = new DisplayMetrics();        this.mainActivity.getWindowManager().getDefaultDisplay().getMetrics(this.displayMetrics);        this.screenHeight = this.displayMetrics.heightPixels;        this.screenWidth = this.displayMetrics.widthPixels;        this.density = this.displayMetrics.density;        this.maxTranslateX = this.screenWidth * 0.8f;        this.mainActivity.setContentView(R.layout.activity_main);        this.maxView = (RelativeLayout) this.mainActivity.findViewById(R.id.maxView);        v1 = new RelativeLayout(mainActivity);        v1.setBackgroundColor(Color.RED);        RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams((int) this.maxTranslateX, LayoutParams.MATCH_PARENT);        this.maxView.addView(v1, params1);        TextView t1 = new TextView(mainActivity);        t1.setText("left menu bar");        t1.setTextColor(Color.WHITE);        v1.addView(t1);        v1.setTranslationX(0 - this.maxTranslateX);        v2 = new RelativeLayout(mainActivity);        v2.setBackgroundColor(Color.parseColor("#0099cd"));        RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams((int) this.screenWidth, LayoutParams.MATCH_PARENT);        this.maxView.addView(v2, params2);        v2.setTranslationX(0);        TextView t2 = new TextView(mainActivity);        t2.setText("body content");        t2.setTextColor(Color.WHITE);        v2.addView(t2);    }}

日志管理类MyLog:

package com.example.wz.util;import android.util.Log;public class MyLog {    public static boolean isGlobalTurnOn = true;    public boolean isTurnOn = true;    public String tag = null;    public MyLog(String tag, boolean isTurnOn) {        this.tag = tag;        this.isTurnOn = isTurnOn;    }    public MyLog(Object clazz, boolean isTurnOn) {        this.tag = clazz.getClass().getSimpleName();        this.isTurnOn = isTurnOn;    }    public void v(String message) {        this.v(this.tag, message);    }    public void d(String message) {        this.d(this.tag, message);    }    public void i(String message) {        this.i(this.tag, message);    }    public void w(String message) {        this.w(this.tag, message);    }    public void e(String message) {        this.e(this.tag, message);    }    public void v(String tag, String message) {        if (isTurnOn && isGlobalTurnOn) {            Log.v(tag, message);        }    }    public void d(String tag, String message) {        if (isTurnOn && isGlobalTurnOn) {            Log.d(tag, message);        }    }    public void i(String tag, String message) {        if (isTurnOn && isGlobalTurnOn) {            Log.i(tag, message);        }    }    public void w(String tag, String message) {        if (isTurnOn && isGlobalTurnOn) {            Log.w(tag, message);        }    }    public void e(String tag, String message) {        if (isTurnOn && isGlobalTurnOn) {            Log.e(tag, message);        }    }}

实现动画效果的核心类OpenLooper:

package com.example.wz.util;import android.annotation.TargetApi;import android.os.Build;import android.os.Handler;import android.os.SystemClock;import android.view.Choreographer;public class OpenLooper {    public LegacyAndroidSpringLooper legacyAndroidSpringLooper = null;    public ChoreographerAndroidSpringLooper choreographerAndroidSpringLooper = null;    public LoopCallback loopCallback = null;    public void createOpenLooper() {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {            choreographerAndroidSpringLooper = new ChoreographerAndroidSpringLooper();        } else {            legacyAndroidSpringLooper = new LegacyAndroidSpringLooper();        }    }    public void start() {        if (choreographerAndroidSpringLooper != null) {            choreographerAndroidSpringLooper.start();        } else if (legacyAndroidSpringLooper != null) {            legacyAndroidSpringLooper.start();        }    }    public void stop() {        if (choreographerAndroidSpringLooper != null) {            choreographerAndroidSpringLooper.stop();        } else if (legacyAndroidSpringLooper != null) {            legacyAndroidSpringLooper.stop();        }    }    public class LoopCallback {        public void loop(double ellapsedMillis) {        }    }    public void loop(double ellapsedMillis) {        if (this.loopCallback != null) {            this.loopCallback.loop(ellapsedMillis);        }    }    public class LegacyAndroidSpringLooper {        public Handler mHandler;        public Runnable mLooperRunnable;        public boolean mStarted;        public long mLastTime;        public LegacyAndroidSpringLooper() {            initialize(new Handler());        }        public void initialize(Handler handler) {            mHandler = handler;            mLooperRunnable = new Runnable() {                @Override                public void run() {                    if (!mStarted) {                        return;                    }                    long currentTime = SystemClock.uptimeMillis();                    loop(currentTime - mLastTime);                    mHandler.post(mLooperRunnable);                }            };        }        public void start() {            if (mStarted) {                return;            }            mStarted = true;            mLastTime = SystemClock.uptimeMillis();            mHandler.removeCallbacks(mLooperRunnable);            mHandler.post(mLooperRunnable);        }        public void stop() {            mStarted = false;            mHandler.removeCallbacks(mLooperRunnable);        }    }    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)    public class ChoreographerAndroidSpringLooper {        public Choreographer mChoreographer;        public Choreographer.FrameCallback mFrameCallback;        public boolean mStarted;        public long mLastTime;        public ChoreographerAndroidSpringLooper() {            initialize(Choreographer.getInstance());        }        public void initialize(Choreographer choreographer) {            mChoreographer = choreographer;            mFrameCallback = new Choreographer.FrameCallback() {                @Override                public void doFrame(long frameTimeNanos) {                    if (!mStarted) {                        return;                    }                    long currentTime = SystemClock.uptimeMillis();                    loop(currentTime - mLastTime);                    mLastTime = currentTime;                    mChoreographer.postFrameCallback(mFrameCallback);                }            };        }        public void start() {            if (mStarted) {                return;            }            mStarted = true;            mLastTime = SystemClock.uptimeMillis();            mChoreographer.removeFrameCallback(mFrameCallback);            mChoreographer.postFrameCallback(mFrameCallback);        }        public void stop() {            mStarted = false;            mChoreographer.removeFrameCallback(mFrameCallback);        }    }}

如有转载请著名来自http://blog.csdn.net/qxs965266509
源代码下载链接:http://download.csdn.net/detail/qxs965266509/8621503

更多相关文章

  1. linux和windows平台下,如何下载android sdk的源代码
  2. Android之替换APP字体——Typeface
  3. Android(安卓)二维码开发功能实现(四)------基于Zxing实现编码功
  4. Android(安卓)命名规范 (提高代码可以读性)
  5. android之webview无网络情况下简单处理
  6. Android高手进阶教程(二十五)之---Android(安卓)中的AIDL!!!
  7. Android图像滤镜框架GPUImage从配置到应用
  8. [Android]使用ActivityGroup来切换Activity和Layout
  9. 浅谈Java中Collections.sort对List排序的两种方法

随机推荐

  1. 布局(2、相对布局)
  2. 监听android电话呼叫状态
  3. Android使用Google提供的地图实现定位时L
  4. Android实现自定义对话框(Dialog)
  5. Android 系统音量最大值的定义位置以及默
  6. android .apk 反编译
  7. Android(安卓)串口通信编程及串口协议分
  8. 【Android】Android Studio中gradle scri
  9. Flutter1.12与原生Android交互(kotlin)
  10. android开发 常用技巧