详细内容请看代码,注释很详细很详细:
1:先看xml文件,就是简单的两个线性布局,一个作为当前界面,一个作为隐藏的侧滑界面。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:context="com.example.actionbar.SlideMenActivity" > <LinearLayout android:id="@+id/menu" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ff00ff00" android:orientation="vertical" > </LinearLayout> <LinearLayout android:id="@+id/content" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffff0000" android:orientation="vertical"> </LinearLayout> </LinearLayout>
2:activity的主要代码:
public class SlideMenActivity extends Activity implements View.OnTouchListener { /** * 手指每单位时间滑动200个像素 */ private static final int SPPED = 200; /** * 屏幕宽度 */ private int mScreenSidth; /** * menu的layout */ private LinearLayout mMenuLayout; /** * content的layout */ private LinearLayout mContentLayout; /** * menu的layout的Paramters */ private LinearLayout.LayoutParams mMenuParams; /** * menu完全显示的时候给content的宽度值 */ private int mMenuPadding = 80; /** * menu最多滑到左边缘,值由menu布局的宽度决定,marginLeft到达此值之后,不能在减少 */ private int mLeftEdge; /** * 测速度的对象 */ private VelocityTracker mVelocityTracker; /** * 手指按下的X坐标 */ private float mXDown; /** * 手指移动时候的X坐标 */ private float mXMove; /** * 手指抬起的X坐标 */ private float mXUp; /** * menu是否再显示 */ private boolean mIsMenuVisible = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_slide_men); initViewsAndValues(); mContentLayout.setOnTouchListener(this); } /** * 初始化menu和content并且设置他们的位置 */ @SuppressLint("ServiceCast") private void initViewsAndValues(){ //得到屏幕的宽 mScreenSidth = getResources().getDisplayMetrics().widthPixels; //找到控件 mMenuLayout = (LinearLayout) findViewById(R.id.menu); mContentLayout = (LinearLayout) findViewById(R.id.content); //得到menu的parameter mMenuParams = (LinearLayout.LayoutParams) mMenuLayout.getLayoutParams(); //将menu的宽度设置为屏幕宽度减去mMenuPading mMenuParams.width = mScreenSidth - mMenuPadding; //左边缘的值复制为menu宽度的负数,这样的话就可以将menu隐藏 mLeftEdge = -mMenuParams.width; //将margin设置为mLeftEdge mMenuParams.leftMargin = mLeftEdge; //将content显示再屏幕上 mContentLayout.getLayoutParams().width = mScreenSidth; } @Override public boolean onTouch(View v, MotionEvent event) { createVelocityTracker(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //记录按下的x坐标 mXDown = event.getRawX(); break; case MotionEvent.ACTION_MOVE: mXMove = event.getRawX(); int distanceX = (int)(mXMove - mXDown); if(mIsMenuVisible){ mMenuParams.leftMargin = distanceX; }else{ mMenuParams.leftMargin = distanceX + mLeftEdge; } if(mMenuParams.leftMargin < mLeftEdge){ //因为leftEdge是负数,就是menu已经隐藏完毕了,不能再往左隐藏了 mMenuParams.leftMargin = mLeftEdge; }else if(mMenuParams.leftMargin > 0){ //menu显示完全了,不能再往右移动了 mMenuParams.leftMargin = 0; } mMenuLayout.setLayoutParams(mMenuParams); break; case MotionEvent.ACTION_UP: mXUp = event.getRawX(); if(wantToShowMenu()){ if(shouldScrollToMenu()){ scrollToMenu(); }else{ //条件不满足,吧menu隐藏 scrollToContent(); } }else if(wantToShowContent()){ if(shouldScrollToContent()){ scrollToContent(); }else{ scrollToMenu(); } } break; default: break; } recycleVelocityTrancker(); return true; } /** * 创建VelocityTracker对象,针对于content的界面的滑动事件 * * @param event */ private void createVelocityTracker(MotionEvent event){ if( null == mVelocityTracker){ mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); } /** * 判断手势是不是想要显示Content && menu处于显示状态 * * @return */ private boolean wantToShowContent(){ return mXUp - mXDown < 0 && mIsMenuVisible; } /** * 是不是要显示menu && menu处于隐藏状态 * * @return */ private boolean wantToShowMenu(){ return mXUp - mXDown > 0 && !mIsMenuVisible; } /** * 是否应该滑动出menu * * @return */ private boolean shouldScrollToMenu(){ return mXUp - mXDown > mScreenSidth/2 || getScrollVelocity() > SPPED; } /** * 是否应该让content全部显示出来 * * @return */ private boolean shouldScrollToContent(){ return mXUp - mXDown < mScreenSidth/2 || getScrollVelocity() > SPPED; } /** * 得到手指滑动速度,每秒移动多少单位像素 * * @return */ private int getScrollVelocity(){ mVelocityTracker.computeCurrentVelocity(1000); int velocity = (int) mVelocityTracker.getXVelocity(); return Math.abs(velocity); } /** * 显示出menu */ private void scrollToMenu(){ new ScrollAsyncTask().execute(30); } /** * 隐藏掉menu */ private void scrollToContent(){ new ScrollAsyncTask().execute(-30); } /** * 回收VelocityTracker对象。 */ private void recycleVelocityTrancker(){ mVelocityTracker.recycle(); mVelocityTracker = null; } private class ScrollAsyncTask extends AsyncTask<Integer, Integer, Integer>{ @Override protected Integer doInBackground(Integer... params) { //得到当前的margin int leftMargin = mMenuParams.leftMargin; //不断更改margin的值 while(true){ leftMargin = leftMargin + params[0]; if(leftMargin > 0){ leftMargin = 0; break; } if(leftMargin < mLeftEdge){ leftMargin = mLeftEdge; break; } publishProgress(leftMargin); sleep(); } if(params[0] > 0){ mIsMenuVisible = true; }else{ mIsMenuVisible = false; } return leftMargin; } @Override protected void onPostExecute(Integer result) { mMenuParams.leftMargin = result; mMenuLayout.setLayoutParams(mMenuParams); } @Override protected void onProgressUpdate(Integer... values) { mMenuParams.leftMargin = values[0]; mMenuLayout.setLayoutParams(mMenuParams); } } private void sleep(){ try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } } }
到此全部结束。
代码改变世界!