效果:
其实就是利用监听手势。将主页面滑开。将下面一层布局的菜单展露出来。下面是布局文件。
<RelativeLayout 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"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/listMenu"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:background="@drawable/f_1"
android:orientation="vertical" >
</LinearLayout>
<RelativeLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/back"
>
</RelativeLayout>
</RelativeLayout>
利用OnGestureListener 去监听手势的变化。,当然,其实后面发现大可不必。直接在OnTouch里面写就好。更简单。记录Down的位置,之后move事件,取得当前触摸位置的绝对坐标。记得是绝对坐标,不要用getX() 取坐标。那样只是取得一个相对的坐标。而你的主页面在移动,你希望的是手指和主页面的相对移动距离为0 。自然是不能够用getRawX() 取相对坐标。
另外如果用OnGestureListener 去实现的,记得不要用OnScroll函数里面的distanceX 那个也是由相对坐标得到。自然,实现后也是会有很多错误的。所以应该用e2去获得绝对坐标与e1的绝对坐标相减,得到移动的距离。
@Override
public void onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) { //distanceX 是getX() 相减的,即是相对控件的坐标
Log.i(TAG,"distanceX:"+distanceX+","+"e2-e1:"+e2.getRawX()+"-"+e1.getRawX());
int dis = (int) (e2.getRawX()-e1.getRawX());
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) content.getLayoutParams();
if(dis<0){
//left e2-e1<0
if(-dis<menuWidth&¶ms.rightMargin<menuWidth){
params.rightMargin =-dis;
params.leftMargin =dis;
Log.i(TAG,"params.rightMargin:"+params.rightMargin+",params.leftMargin:"+params.leftMargin);
content.setLayoutParams(params);
}else{
params.rightMargin =menuWidth;
params.leftMargin =-menuWidth;
Log.i(TAG,"params.rightMargin:"+params.rightMargin+",params.leftMargin:"+params.leftMargin);
content.setLayoutParams(params);
}
}else{
//right
if(dis<menuWidth&¶ms.rightMargin>0){
params.rightMargin =menuWidth-dis;
params.leftMargin =-(menuWidth-dis);
Log.i(TAG,"params.rightMargin:"+params.rightMargin+",params.leftMargin:"+params.leftMargin);
content.setLayoutParams(params);
}else{
params.rightMargin =0;
params.leftMargin =0;
Log.i(TAG,"params.rightMargin:"+params.rightMargin+",params.leftMargin:"+params.leftMargin);
content.setLayoutParams(params);
}
}
Log.i(TAG,"onscroll");
}
建议直接设置主页面的OnTouchListener,免得一大堆东西。那个onGestureListener 很多函数都用不上。
当然最后就是移动部分后面,自动的动画了。学了下AysncTask 。这个用起来就会逻辑性很好了。
content.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Log.i(TAG,"ontouchEvent");
boolean result = detector.onTouchEvent(event); //建议直接在此处检测手势
if(event.getAction()==MotionEvent.ACTION_UP){
//结束
switch(gestureListener.getDirection()){
case SlideMenuOnGestureListener.LEFT:
//启动向左的动画
new UpdateMargin(MoveDirection.LEFT).execute(gestureListener.getVelocityX());
menuhasOpen = true;
Log.i(TAG,"left end");
break;
case SlideMenuOnGestureListener.RIGHT:
//启动向右的动画
new UpdateMargin(MoveDirection.RIGHT).execute(gestureListener.getVelocityX());
menuhasOpen = false;
Log.i(TAG,"right end");
break;
case SlideMenuOnGestureListener.NO_SCROLL:
Log.i(TAG,"no scroll");
//返回 恢复
if(menuhasOpen){
new UpdateMargin(MoveDirection.LEFT).execute(gestureListener.getVelocityX());
}else{
new UpdateMargin(MoveDirection.RIGHT).execute(gestureListener.getVelocityX());
}
break;
}
}
return result;
}
});
动画:
static enum MoveDirection{
LEFT,RIGHT;
}
/**
*
* @author houzhi
* Boolean true 代表左
*/
class UpdateMargin extends AsyncTask<Float, Integer, Void>{
final static long SLEEP_TIME = 50L;
final static int MOVE_DISTANCE = 30;
public MoveDirection direction;
public UpdateMargin(MoveDirection direction){
this.direction = direction;
}
boolean isLeft ;
@Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Integer... values) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams )content.getLayoutParams();
layoutParams.leftMargin=values[0];
layoutParams.rightMargin=values[1];
content.setLayoutParams(layoutParams);
}
@Override
protected Void doInBackground(Float... params) {
RelativeLayout.LayoutParams layoutParams ;
int v = (int)(float)(params[0]/(100/SLEEP_TIME));
switch(direction){
case LEFT:
//left
while(true){
layoutParams = (RelativeLayout.LayoutParams )content.getLayoutParams();
if(layoutParams.rightMargin>=menuWidth){
publishProgress(-menuWidth,menuWidth);
break;
}
publishProgress(layoutParams.leftMargin-MOVE_DISTANCE,layoutParams.rightMargin+MOVE_DISTANCE);
try {
TimeUnit.MILLISECONDS.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
case RIGHT:
//right
while(true){
layoutParams = (RelativeLayout.LayoutParams )content.getLayoutParams();
if(layoutParams.rightMargin-MOVE_DISTANCE<=0){ //保证下一次能够运行。
publishProgress(0,0);
break;
}
publishProgress(layoutParams.leftMargin+MOVE_DISTANCE,layoutParams.rightMargin-MOVE_DISTANCE);
try {
TimeUnit.MILLISECONDS.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
}
return null;
}