android抽屉式侧滑

来源:互联网 发布:网络金融培训 编辑:程序博客网 时间:2024/06/06 10:06

侧滑效果展示

这里写图片描述

原理

要实现这种侧滑效果,首先自定义一个滑动Layout继承自RelativeLayout,里面有两个View分别是用来存放内容和菜单布局的,然后记录手指一动的距离更改内容View的leftMargin(注意:只有leftMargin的值是负数才能够向左偏移,如果是正数的话那么会向右压缩),在内容View移动的同时,调用菜单的setTranslateX()方法就可以达到菜单移动了

代码

首先上代码:

<cn.karent.slide.UI.SlideLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent">    <!--侧滑菜单-->    <RelativeLayout        android:id="@+id/slide_menu"        android:layout_width="300dp"        android:layout_height="match_parent"        android:layout_alignParentRight="true"        android:layout_marginRight="-150dp"        android:background="@android:color/holo_purple"        android:orientation="vertical">        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="侧滑菜单"/>        <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerInParent="true"            android:text="测试按钮"/>    </RelativeLayout>    <!--内容View-->    <RelativeLayout        android:id="@+id/slide_content"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_alignParentLeft="true"        android:background="@android:color/holo_red_dark">        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="我是内容"/>        <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="button"            android:layout_centerInParent="true"/>    </RelativeLayout></cn.karent.slide.UI.SlideLayout>

注意,我直接让菜单项往右偏移一半,这样就不会有完全滚动的效果,而是菜单的偏移比内容的偏移更慢一点,下面上自定义Layout的代码:

package cn.karent.slide.UI;import android.content.Context;import android.os.AsyncTask;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.RelativeLayout;import cn.karent.slide.R;import cn.karent.slide.util.ScreenUtil;/** * Created by wan on 2016/12/6. * 侧滑菜单,内容会偏移 */public class SlideLayout extends RelativeLayout {    private Context mContext;    private static final int MOTION_VELOCITY = 300;    /*        是否是第一次调用onLayout方法     */    private boolean mLoadOnece = false;    /*        左边内容的布局参数     */    private MarginLayoutParams mLeftParams;    /*        右边菜单的布局参数     */    private MarginLayoutParams mMenuParams;    /*        左边的内容View     */    private View mLeftView;    /*        侧滑菜单View     */    private View mMenuView;    private float mOldX;    private float mOldY;    /*     * 屏幕的宽度     */    private int mScreenWidth;    /**     * 控件能够移动到的左边界,内容View能向左偏移的最大边界     */    private int mLeftEdge ;    public SlideLayout(Context context) {        super(context);        mContext = context;    }    public SlideLayout(Context context, AttributeSet attrs) {        super(context, attrs);        mContext = context;    }    /**     * 布局     */    public void onLayout(boolean change, int l, int t, int r, int b) {        super.onLayout(change, l, t, r, b);        if( change && !mLoadOnece) {            mLeftEdge = ScreenUtil.dp2px(300);            mLeftView = findViewById(R.id.slide_content);            mMenuView = findViewById(R.id.slide_menu);            mLeftParams =  (MarginLayoutParams) mLeftView.getLayoutParams();            mMenuParams = (MarginLayoutParams)mMenuView.getLayoutParams();            DisplayMetrics dm = getResources().getDisplayMetrics();            mScreenWidth = dm.widthPixels;            mLoadOnece = true;        }    }    /**     * 事件拦截     * @param e     * @return     *  true 表示拦截子类的Touch事件     *  false 表示     */    public boolean onInterceptTouchEvent(MotionEvent e) {        int action  = e.getAction();        switch( action ) {            case MotionEvent.ACTION_DOWN:                return false;            case MotionEvent.ACTION_MOVE:                mOldX = e.getRawX();                break;            case MotionEvent.ACTION_UP:                break;        }        return true;    }    public boolean onTouchEvent(MotionEvent e) {        int action = e.getAction();        switch( action ) {            case MotionEvent.ACTION_DOWN:                //e.getX()得到的是相对当前容器的坐标                mOldX = e.getRawX();                mOldY = e.getRawY();                break;            case MotionEvent.ACTION_MOVE:                float x = e.getRawX();                float y = e.getRawY();                if( y - mOldY > 20 || y - mOldY < -20) {                    return false;                }                //获取移动了多少个px                int moveX = (int)(x - mOldX);                mOldX = x;                mOldY = y;                //侧滑                modifyLeftMargin(mLeftParams.leftMargin + moveX);                break;            case MotionEvent.ACTION_UP:                //当手指拿起时,计算是向哪边滑动                int l = mLeftParams.leftMargin > (-mLeftEdge / 2) ? 0 : -mLeftEdge;                new SmoothScrollTack().execute(l, mLeftParams.leftMargin);                break;        }        return true;    }    /**     * 修改View的边距来达到移动的效果     * @param leftMargin     */    private void modifyLeftMargin(int leftMargin) {        //如果左边距大于0代表将要向右变压缩,应该禁止        if( leftMargin > 0 ) {            mLeftParams.leftMargin = 0;            mMenuView.setTranslationX(0);            //控制左边界滑动        } else if( leftMargin < -mLeftEdge) {            mLeftParams.leftMargin = -mLeftEdge;            mMenuView.setTranslationX(-mLeftEdge / 2);        } else {            mLeftParams.leftMargin = leftMargin;            mMenuView.setTranslationX(leftMargin / 2);        }        mLeftParams.width = mScreenWidth;        mLeftView.setLayoutParams(mLeftParams);    }    /**     * 当侧滑停止的时候来处理接下来的滑动     */    private class SmoothScrollTack extends AsyncTask<Integer, Integer, Integer> {        @Override        protected void onProgressUpdate(Integer... values) {            int leftMargin = values[0];            modifyLeftMargin(leftMargin);        }        /**         * 计算下一个leftMargin值         * @param params         * @return         */        @Override        protected Integer doInBackground(Integer... params) {            int targetLeftMargin = params[0];            int currentLeftMargin = params[1];            int leftMargin = currentLeftMargin;            //计算增加的步长            int step = targetLeftMargin == 0 ? 10 : -10;            while(true) {                leftMargin += step;                //判断是否滑动完成                if( leftMargin < -mLeftEdge ) {                    leftMargin = -mLeftEdge;                    break;                }                if( leftMargin > 0 ) {                    leftMargin = 0;                    break;                }                publishProgress(leftMargin);                try {                    Thread.sleep(5);                } catch( InterruptedException e) {                    e.printStackTrace();                }            }            publishProgress(leftMargin);            return leftMargin;        }    }}

ScreenUtil:

package cn.karent.slide.util;import android.util.DisplayMetrics;import android.util.Log;/** * Created by wan on 2016/12/22. * */public class ScreenUtil  {    /**     * 获取屏幕的密度     * @return     */    public static float getDensity() {        DisplayMetrics dm = MyApplication.getContext().getResources().getDisplayMetrics();        float density = dm.density;        Log.d("density", density + "");        return density;    }    public static DisplayMetrics getDislayMetrics() {        return MyApplication.getContext().getResources().getDisplayMetrics();    }    public static int px2dp(float p) {        float density = getDensity();        return (int)(p / density + 0.5f);    }    public static int dp2px(float dip) {        return (int)(dip * getDensity() + 0.5f);    }}

获取全局的Context:

package cn.karent.slide.util;import android.app.Application;import android.content.Context;/** * Created by wan on 2016/12/22. * 获取全局Context对象 */public class MyApplication extends Application {    private static Context mContext;    @Override    public void onCreate() {        mContext = getApplicationContext();        super.onCreate();    }    public static Context getContext() {        return mContext;    }}

androidManifest.xml:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="cn.karent.slide">    <application        android:name=".util.MyApplication"        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@android:style/Theme.NoTitleBar">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

只要在下面使用android:name=”.util.MyApplication”那么我们自己定义的Application就会覆盖系统默认的Application了

0 0
原创粉丝点击