滑动菜单有很多,网上有很多的实现是借用gitHub上的开源代码,slidingmenu.实现价值很高,但是项目宠大,移植不是那么容易,今天介绍一种简单的侧滑。
主要分为,MainActivity(主体),界面有三人fragment支撑,(LeftFragment,CenterFragmet,RightFragment)
正常显示为CenterFragment,左右需要LeftFragment和RihtFragment.
现在开始代码架构:
MainActivity的布如下
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/bg_1"
tools:context=".MainActivity" >
<FrameLayout
android:id="@+id/left_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</FrameLayout>
<FrameLayout
android:id="@+id/right_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true" >
</FrameLayout>
<FrameLayout
android:id="@+id/center_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent" >
</FrameLayout>
</RelativeLayout>
中间布局是关键因为需要包含一个Slider来支持左右滑动
<com.example.Slider xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/center_slider"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/home_blue"
tools:context=".MainActivity" >
<RelativeLayout>
..........这里自己写你自己的布局
</RelativeLayout>
</com.example.Slider>
LeftFragment的布局主要是正常布局,居左对齐,宽度为home_page_left_menu_width,固定宽度
RightFragment的布局主要是正常布局,居右对齐,宽度为home_page_Right_menu_width,固定宽度
接下来到核心Slider类的书写
public class Slider extends RelativeLayout {
private int mTouchSlop;
private float mLastMotionX, mLastMotionY;
private int mState = 0;
private int mLeftMenuWidth;
private int mRightMenuWidth;
private int mCurrentPosition = 0; // -1(left),0(center),1(right)
public Slider(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
mCurrentPosition = 0;
mLeftMenuWidth = context.getResources().getDimensionPixelSize(
R.dimen.home_page_left_menu_width);
DisplayMetrics metrics = new DisplayMetrics();
((MainActivity)context).getWindowManager().getDefaultDisplay().getMetrics(metrics);
mRightMenuWidth = metrics.widthPixels
mState = ScrollState.DEFAULT;
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
private void calibrateView() {
int currentX = getLeftMargin();
if (currentX < 0) {
((MainActivity)getContext()).showRightView();
} else if (currentX > 0) {
((MainActivity)getContext()).showLeftView();
} else {
((MainActivity)getContext()).showCenterView();
}
}
private boolean checkMoveState(int x, int y) {
int dx = (int)(x - mLastMotionX);
int deltaX = Math.abs(dx);
int deltaY = Math.abs((int)(y - mLastMotionY));
if (mState == ScrollState.DEFAULT) {
if (deltaX > mTouchSlop && deltaX > deltaY) {
if (dx > 0) {
mState = ScrollState.RIGHT;
mLastMotionX = x - mTouchSlop;
} else {
mState = ScrollState.LEFT;
mLastMotionX = x + mTouchSlop;
}
calibrateView();
return true;
}
}
return false;
}
private int getLeftMargin() {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)getLayoutParams();
return params.leftMargin;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
float x = ev.getX();
float y = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
mLastMotionX = x;
mLastMotionY = y;
break;
}
case MotionEvent.ACTION_MOVE: {
return checkMoveState((int)x, (int)y);
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
mState = ScrollState.DEFAULT;
break;
}
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getRawX();
calibrateView();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mLastMotionX = x;
break;
}
case MotionEvent.ACTION_MOVE: {
int dx = (int)(x - mLastMotionX);
if (ScrollState.DEFAULT == mState) {
if (dx > 0) {
mState = ScrollState.RIGHT;
} else if (dx < 0) {
mState = ScrollState.LEFT;
}
return true;
}
mLastMotionX = x;
int scrollX = dx + getLeftMargin();
if (mCurrentPosition == 0) {
// 中间位置上
if (dx > 0) {
if (mState == ScrollState.RIGHT) {
// 不能出界
scrollX = Math.min(mLeftMenuWidth, scrollX);
} else if (mState == ScrollState.LEFT) {
scrollX = getLeftMargin();
mState = ScrollState.DEFAULT;
}
} else if (dx < 0) {
if (mState == ScrollState.RIGHT) {
scrollX = getLeftMargin();
mState = ScrollState.DEFAULT;
} else if (mState == ScrollState.LEFT) {
scrollX = Math.max(-mRightMenuWidth, scrollX);
}
}
} else if (mCurrentPosition == -1) {
// LeftView is shown
if (dx > 0) {
// ---->
if (mState == ScrollState.RIGHT) {
scrollX = mLeftMenuWidth;
} else if (mState == ScrollState.LEFT) {
scrollX = Math.min(scrollX, mLeftMenuWidth);
}
} else if (dx < 0) {
// <----
if (mState == ScrollState.RIGHT) {
scrollX = getLeftMargin();
mState = ScrollState.DEFAULT;
} else if (mState == ScrollState.LEFT) {
scrollX = Math.max(0, scrollX);
}
}
} else if (mCurrentPosition == 1) {
// RightView is shown.
if (dx > 0) {
// ---->
if (mState == ScrollState.RIGHT) {
scrollX = Math.min(0, scrollX);
} else if (mState == ScrollState.LEFT) {
scrollX = getLeftMargin();
mState = ScrollState.DEFAULT;
}
} else if (dx < 0) {
// <-----
if (mState == ScrollState.RIGHT) {
scrollX = Math.max(-mRightMenuWidth, scrollX);
} else if (mState == ScrollState.LEFT) {
scrollX = -mRightMenuWidth;
}
}
}
scrollTo(scrollX);
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
int currentX = getLeftMargin();
final int currentPos = mCurrentPosition;
if (currentPos == 0) {
if (currentX > mTouchSlop) {
smoothScrollBy(mLeftMenuWidth - currentX);
mCurrentPosition = -1;
} else if (currentX < -mTouchSlop) {
smoothScrollBy(-mRightMenuWidth - currentX);
mCurrentPosition = 1;
} else {
smoothScrollBy(-currentX);
mCurrentPosition = 0;
}
} else if (currentPos == 1) {
if (currentX > -mRightMenuWidth + mTouchSlop) {
smoothScrollBy(-currentX);
mCurrentPosition = 0;
} else {
smoothScrollBy(-mRightMenuWidth - currentX);
mCurrentPosition = 1;
}
} else if (currentPos == -1) {
if (currentX < mLeftMenuWidth - mTouchSlop) {
smoothScrollBy(-currentX);
mCurrentPosition = 0;
} else {
smoothScrollBy(mLeftMenuWidth - currentX);
mCurrentPosition = -1;
}
}
mState = ScrollState.DEFAULT;
break;
}
}
return true;
}
public void scrollTo(int x) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)getLayoutParams();
params.leftMargin = x;
params.rightMargin = -x;
params.gravity = Gravity.NO_GRAVITY;
setLayoutParams(params);
invalidate();
}
public void smoothScrollBy(int dx) {
new SmoothMove().execute(dx);
}
public boolean onBackPressed() {
if (mCurrentPosition == 0) {
return false;
}
if (mCurrentPosition == -1) {
smoothScrollBy(-mLeftMenuWidth);
}
if (mCurrentPosition == 1) {
smoothScrollBy(mRightMenuWidth);
}
mCurrentPosition = 0;
return true;
}
public void clickLeftButton() {
if (mCurrentPosition == 0) {
((MainActivity)getContext()).showLeftView();
smoothScrollBy(mLeftMenuWidth);
mCurrentPosition = -1;
} else {
smoothScrollBy(-getLeftMargin());
mCurrentPosition = 0;
}
}
public void clickRightButton() {
if (mCurrentPosition == 0) {
((MainActivity)getContext()).showRightView();
smoothScrollBy(-mRightMenuWidth);
mCurrentPosition = 1;
} else {
smoothScrollBy(-getLeftMargin());
mCurrentPosition = 0;
}
}
private class SmoothMove extends AsyncTask<Integer, Integer, Void> {
private static final long SLEEP_TIME = 5;
private static final int MOVE_SPEED = 30;
@Override
protected Void doInBackground(Integer... params) {
int distance = params[0];
int times = Math.abs(distance) / MOVE_SPEED;
times = Math.max(1, times);
int dis = distance / times;
int total = 0;
for (int i = 0; i < times - 1; i++) {
publishProgress(dis);
total += dis;
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
}
}
// 最后一次自己移动,防止余数
dis = distance - total;
publishProgress(dis);
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
int scrollX = values[0] + getLeftMargin();
scrollTo(scrollX);
}
}
private class ScrollState {
static final int DEFAULT = 0;
static final int RIGHT = 1;
static final int LEFT = -1;
}
}
MainActivity加载这几个Fragment.
FragmentTransaction t = this.getSupportFragmentManager().beginTransaction();
mLeftFragment = new LeftFragment();
t.replace(R.id.left_frame, mLeftFragment);
mRightFragment = new RightFragment();
t.replace(R.id.right_frame, mRightFragment);
mCenterFragment = new CenterFragment();
t.replace(R.id.center_frame, mCenterFragment);
t.commit();
这样一个左右滑动菜单的页面就完成了 另外中间CenterFrament可以增加两个按扭,分别点击可以达到相同的效果
Slider类的如上public void clickLeftButton() {}和public void clickRightButton() {}
大致辞思想就是这样,可以根据自己的实际情作相应修改。