編輯:關於Android編程
側滑菜單應用現在非常多,而且實現方式也多種多樣。通過在網上的多方查找,我找到郭霖少俠的這篇文章:http://blog.csdn.net/guolin_blog/article/details/8744400,研究之後收獲頗多。同時記得以前看過一篇講Scroller實現滑屏的文章:http://www.cnblogs.com/wanqieddy/archive/2012/05/05/2484534.html。
那為何不用scroller來實現以下側滑菜單?閒的蛋疼,那就試試吧,在這裡先感謝以上兩篇博文給我的啟發。
原理:通過scrollBy和scrollTo來移動右側的content布局,實際上整個過程中,左側的menu布局未發生滾動,這樣出來的效果是右側content布局覆蓋住左側menu布局。當然scroll的方式也可以實現menu和content同時平移的效果,這個只需要在布局文件上動動手腳就行了,在此先按下不表。
下面是本文的實現效果
activity_main.xml文件:
首先放入menu布局,因為是RelativeLayout布局因此先放入的會被覆蓋,然後是滑動布局,在滑動布局中加入content布局,因為content布局會隨滑動布局一起移動。
menu.xml和conent_diary.xml這兩個布局文件就不用講了,大家跟著感覺走,想放什麼放什麼吧。
SlideLayout.java文件:大部分代碼都很簡單,看注釋就能懂。這裡只說幾個要點,我也是調試過之後才明白的:
1. getScrollX()得到的是當前View的最左邊所在的X坐標。程序初始化後此值為0,View向右滑動後,相當於屏幕坐標系向負方向移動了一段,因此此時此值為負數;反之則相反。
2. Scroller實際上只是保存和提供自動滑動時所需的數值,真正完成滑動的還是scrollTo和scrollBy兩個函數。
3. 我寫的SlideLayout繼承自RelativeLayout,其實也可以繼承自ViewGroup,但是就需要自己重寫onMeasure和onLayout函數,來布局子控件。這個實現中沒有特殊的布局要求,所以用RelatiLayout就可以啦。
package com.noter.layout; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.widget.RelativeLayout; import android.widget.Scroller; public class SlideLayout extends RelativeLayout { private static String TAG = "SlideMenuLayout"; private Context mContext; private Scroller mScroller; //Android 提供的滑動輔助類 private int mTouchSlop = 0 ; //在被判定為滾動之前用戶手指可以移動的最大值 private VelocityTracker mVelocityTracker; //用於計算手指滑動的速度 public static final int SNAP_VELOCITY = 200; //滾動顯示和隱藏左側布局時,手指滑動需要達到的速度:每秒200個像素點 private int mMaxScrollX = 0; //最大滾動距離,等於menu的寬度 public void setMaxScrollX(int maxScrollX) { this.mMaxScrollX = maxScrollX; } private float mDownX; //一次按下抬起的動作中,按下時的X坐標,用於和抬起時的X比較,判斷移動距離。少於mTouchSlop則判定為原地點擊 private float mLastX; //記錄滑動過程中的X坐標 private boolean isMenuOpen = false; //菜單界面是否被打開,只有完全打開才為true public boolean isMenuOpen() { return isMenuOpen; } private View mContent; public SlideLayout(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; init(); } private void init() { Log.v(TAG, "init start"); mScroller = new Scroller(mContext); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if(changed){ mContent = getChildAt(0); } } @Override public boolean onTouchEvent(MotionEvent event) { createVelocityTracker(event); int curScrollX = getScrollX(); // 檢查觸摸點是否在滑動布局(內容content)中,如果不是則返回false,即本View不處理該事件 if (mContent != null) { Rect rect = new Rect(); mContent.getHitRect(rect); if (!rect.contains((int)event.getX() + curScrollX, (int)event.getY())) { return false; } } float x = event.getX(); //取得本次event的X坐標 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mDownX = x; mLastX = x; break; case MotionEvent.ACTION_MOVE: int deltaX = (int)(mLastX - x); if((curScrollX + deltaX) < -mMaxScrollX) { deltaX = -mMaxScrollX - curScrollX; } if((curScrollX + deltaX) > 0){ deltaX = -curScrollX; } if (deltaX != 0) { scrollBy(deltaX, 0); } mLastX = x; break; case MotionEvent.ACTION_UP: int velocityX = getScrollVelocity(); int offsetX = (int) (x - mDownX); //成立表明移動距離已經達到被判斷為滑動的最低標准 //不成立表明不被判斷為滑動,則認為是單一的點擊,則關閉menu if(Math.abs(offsetX) >= mTouchSlop) { //成立表明手指移動速度達標,則進行自動滑動; //不成立表明速度不達標,但仍然需要判斷當前SlideLayout的位置 //如果已經超過一半,則繼續自動完成剩下的滑動,如果沒有超過一半,則反向滑動 if(Math.abs(velocityX) >= SNAP_VELOCITY) { if(velocityX > 0){ openMenu(); } else if(velocityX < 0) { closeMenu(); } } else { if (curScrollX >= -mMaxScrollX / 2) { closeMenu(); } else { openMenu(); } } } else { closeMenu(); } recycleVelocityTracker(); break; } return true; } private void createVelocityTracker(MotionEvent event) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); } //獲取手指在View上的滑動速度,以每秒鐘移動了多少像素值為單位 private int getScrollVelocity() { mVelocityTracker.computeCurrentVelocity(1000); return (int) mVelocityTracker.getXVelocity(); } private void recycleVelocityTracker() { mVelocityTracker.recycle(); mVelocityTracker = null; } //打開Menu布局 public void openMenu() { int curScrollX = getScrollX(); scrollToDestination(-mMaxScrollX - curScrollX); isMenuOpen = true; } //關閉Menu布局 public void closeMenu() { int curScrollX = getScrollX(); scrollToDestination(-curScrollX); isMenuOpen = false; } private void scrollToDestination(int x) { if (x == 0) return; mScroller.startScroll(getScrollX(), 0, x, 0, Math.abs(x)); invalidate(); } }
最後是代碼下載,Enjoy it!
側滑菜單實例
1.自定義控件有一個方法是在原生控件的基礎上進行的拓展,增加新的功能,修改顯示的UI等,一般我們可以子啊onDraw()方法中隊原生的控件進行的拓展。2.下面以為text
1、前言webView是android中用於展示簡單的網頁或者加載一些html格式的很好的選擇,它提供了很多的操作上的封裝但同時又不失去靈活性,因為他提供了webView
像QQ,微博,360等手機應用大部分的應用啟動的一個頁面都是顯示自己產品的logo,不但可以打下廣告還可以掩飾後台加載的行為,今天在自己的應用加上了這個功能,簡單的記錄總
滴滴巴士是滴滴快車繼滴滴順風車、滴滴快車服務之後推出的又一便民出行服務,特別廣大上班族來說無疑是極好的,再也不用去擠公交、擠地鐵了。下面下載吧小編就給大家講