編輯:關於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!
側滑菜單實例
對現有的控件進行拓展,以TextView為例
1.自定義控件有一個方法是在原生控件的基礎上進行的拓展,增加新的功能,修改顯示的UI等,一般我們可以子啊onDraw()方法中隊原生的控件進行的拓展。2.下面以為text
通過webView與javascript交互來研究webView的特點
1、前言webView是android中用於展示簡單的網頁或者加載一些html格式的很好的選擇,它提供了很多的操作上的封裝但同時又不失去靈活性,因為他提供了webView
android應用啟動頁面顯示
像QQ,微博,360等手機應用大部分的應用啟動的一個頁面都是顯示自己產品的logo,不但可以打下廣告還可以掩飾後台加載的行為,今天在自己的應用加上了這個功能,簡單的記錄總
滴滴巴士怎麼用 滴滴巴士乘車指南
滴滴巴士是滴滴快車繼滴滴順風車、滴滴快車服務之後推出的又一便民出行服務,特別廣大上班族來說無疑是極好的,再也不用去擠公交、擠地鐵了。下面下載吧小編就給大家講