这次是滑动特效实现,代码是看的郭霖老师的,但是看了代码有点懵懵懂懂的,所以自己就对代码进行更详细的解读。
步骤:
1.首先我们要初始化几个参数:
menuPadding=100; //完全显示Menu时,留给Content的宽度
screenWidth; //初始化为屏幕宽度
leftEdge; //也就是menu滑到最左边,menu布局leftMargin的最小值,也就是后面滑动只要小于了它,就不能再向左滑动了。
rightEdge; //menu滑到最右边,leftMargin不能再增加了。
2. 重写 onTouch事件,分为:手指按下,手指移动,手指抬起。
按下时:获取按下的x值;移动时:判断滑动的位置,根据 leftEdge最左边 ,rightEdge最右边;
抬起时:判断是否需要显示 Menu或者 Content 。
3. 根据AsyncTask来显示手指在屏幕上滑动的样子。(最后我也不清楚为什么用到AsyncTask)
这是我 activity_main 代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/menu"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@color/yellow"
>
</LinearLayout>
<LinearLayout
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@color/blue">
</LinearLayout>
</LinearLayout>
我的 MainActivity.java :
package com.slidemenudemo;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
public class MainActivity extends Activity implements OnTouchListener {
/**
* 自定义的速度,当用户达到这个速度时,
* 就可以是menu到content的转换,或者content到menu的转换
*/
private static final int SPEED=200;
/**
* 手指按下时X的坐标
*/
private float xDown;
/**
* 手指抬起时X的坐标
*/
private float xUp;
/**
* 手指滑动时X的坐标
*/
private float xMove;
private View menu;
private View content;
/**
* menu菜单的参数,根据它来改变leftMargin
*/
private LinearLayout.LayoutParams menuParams;
private boolean isMenuVisible;
private int screenWidth;
/**
* menu滑动到最左端时的最小值
*/
private int leftEdge;
/**
* menu滑动到最右端时的最大值
*/
private int rightEdge;
/**
* menu显示时,留给content的宽度
*/
private int menuPadding;
/**
* 用于计算手指滑动的速度。
*/
private VelocityTracker mVelocityTracker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
content.setOnTouchListener(this);
}
/**
* 初始化
*/
private void initView(){
WindowManager window=(WindowManager) getSystemService(Context.WINDOW_SERVICE);
screenWidth=window.getDefaultDisplay().getWidth();
menu=findViewById(R.id.menu);
content=findViewById(R.id.content);
menuParams=(LinearLayout.LayoutParams)menu.getLayoutParams();
menuPadding=100;
menuParams.width=screenWidth-menuPadding;
leftEdge=-menuParams.width;
rightEdge=0;
menuParams.leftMargin=leftEdge;
content.getLayoutParams().width=screenWidth;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
createVelocityTracker(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
xDown=event.getRawX();
break;
case MotionEvent.ACTION_MOVE:
// 手指移动时,对比按下时的横坐标,计算出移动的距离,来调整menu的leftMargin值,从而显示和隐藏menu
xMove=event.getRawX();
int distanceX=(int) (xMove-xDown);
if(isMenuVisible){
menuParams.leftMargin=distanceX;
}else {
menuParams.leftMargin=distanceX+leftEdge;
}if(menuParams.leftMargin<leftEdge){
menuParams.leftMargin=leftEdge;
}else if(menuParams.leftMargin>rightEdge){
menuParams.leftMargin=rightEdge;
}
menu.setLayoutParams(menuParams);
break;
case MotionEvent.ACTION_UP:
// 手指抬起时,进行判断当前手势的意图,从而决定是滚动到menu界面,还是滚动到content界面
xUp=event.getRawX();
if(wantToShowMenu()){
if(shouldShowMenu()){
ScollToMenu();
}else {
ScollToContent();
}
}
else if(wantToShowContent()){
if(shouldShowContent()){
ScollToContent();
}else {
ScollToMenu();
}
}
break;
}
recycleVelocityTracker();
return true;
}
private boolean wantToShowMenu(){
return xUp-xDown > 0 && !isMenuVisible;
}
private boolean wantToShowContent(){
return xUp-xDown < 0 && isMenuVisible;
}
private boolean shouldShowMenu(){
return xUp-xDown > screenWidth/2 || getScrollVelocity() > SPEED;
}
private boolean shouldShowContent(){
return xDown-xUp + menuPadding >screenWidth/2 || getScrollVelocity() > SPEED ;
}
private void ScollToMenu(){
new ScrollTask().execute(30);
}
private void ScollToContent(){
new ScrollTask().execute(-30);
}
/**
* 创建VelocityTracker对象,并将触摸content界面的滑动事件加入到VelocityTracker当中。
*
* @param event
* content界面的滑动事件
*/
private void createVelocityTracker(MotionEvent event){
if(mVelocityTracker==null){
mVelocityTracker=VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
private void recycleVelocityTracker(){
mVelocityTracker.recycle();
mVelocityTracker=null;
}
/**
* 获取手指在content界面滑动的速度。
*
* @return 滑动速度,以每秒钟移动了多少像素值为单位。
*/
private int getScrollVelocity(){
mVelocityTracker.computeCurrentVelocity(1000);
int velocity=(int) mVelocityTracker.getXVelocity();
return Math.abs(velocity);
}
class ScrollTask extends AsyncTask<Integer, Integer, Integer>{
@Override
protected Integer doInBackground(Integer... speed) {
int leftMargin=menuParams.leftMargin;
// 根据传入的速度来滚动界面,当滚动到达左边界或右边界时,跳出循环。
while(true){
leftMargin=leftMargin+speed[0];
if(leftMargin>rightEdge){
leftMargin=rightEdge;
break;
}
if(leftMargin<leftEdge){
leftMargin=leftEdge;
break;
}
publishProgress(leftMargin);
//为了产生滑动效果,而睡眠20毫秒
sleep(20);
}
if (speed[0] > 0) {
isMenuVisible = true;
} else {
isMenuVisible = false;
}
return leftMargin;
}
@Override
protected void onProgressUpdate(Integer... leftMargin) {
menuParams.leftMargin=leftMargin[0];
menu.setLayoutParams(menuParams);
}
@Override
protected void onPostExecute(Integer leftMargin) {
menuParams.leftMargin=leftMargin;
menu.setLayoutParams(menuParams);
}
}
private void sleep(long mills){
try {
Thread.sleep(mills);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}