android sink功能 android slide_android sink功能

实现原理: 在一个Activity的布局中需要有两部分,一个是菜单(menu)的布局,一个是内容(content)的布局。两个布局横向排列,菜单布局在左,内容布局在右。初始化的时候将菜单布局向左偏移,以至于能够完全隐藏,这样内容布局就会完全显示在Activity中。然后通过监听手指滑动事件,来改变菜单布局的左偏移距离,从而控制菜单布局的显示和隐藏。



下来来实现这个效果:



1.打开layout下的activity_main.xml



<LinearLayout xmlns:android="http:///apk/res/android"
 
  
xmlns:tools="http:///tools"
 
  
android:layout_width="match_parent"
 
  
android:layout_height="match_parent"
 
  
android:orientation="horizontal"
 
  
tools:context=".MainActivity" >
 
   
  
<LinearLayout 
 
  
android:id="@+id/ll_menu"
 
  
android:layout_width="fill_parent"
 
  
android:layout_height="fill_parent"
 
  
android:orientation="vertical"
 
  
android:background="@drawable/menu"
 
  
></LinearLayout>
 
  
<LinearLayout 
 
  
android:id="@+id/ll_content"
 
  
android:layout_width="fill_parent"
 
  
android:layout_height="fill_parent"
 
  
android:background="@drawable/content"
 
  
android:orientation="vertical"
 
  
></LinearLayout>
 
   
  
</LinearLayout>



这个布局文件的最外层布局是一个LinearLayout,排列方向是水平方向排列。这个LinearLayout下面嵌套了两个子LinearLayout,分别就是菜单的布局和内容的布局。



2.打开MainActivity.java



public class MainActivity extends Activity implements OnTouchListener {
 
   
  
//滚动显示和隐藏Menu,手指滑动需要达到的速度
 
  
public static final int SNAP_VELOCITY=200;
 
  
    
 
  
//屏幕宽度
 
  
private int screenWidth;
 
  
    
 
  
//menu最多可以滑动的左边缘
 
  
private int leftEdge;
 
  
    
 
  
//menu最多可以滑动的右边缘
 
  
private int rightEdge=0;
 
  
    
 
  
//menu完全显示时,留给content的宽度值
 
  
private int menuPadding=80;
 
  
    
 
  
//主内容布局
 
  
private View content;
 
  
//menu布局
 
  
private View menu;
 
  
    
 
  
//menu布局的参数,通过这个参数来更改leftMargin的值
 
  
private LinearLayout.LayoutParams menuParams;
 
  
    
 
  
//记录手指按下的横坐标
 
  
private float xDown;
 
  
    
 
  
//记录手指移动的横坐标
 
  
private float xMove;
 
  
    
 
  
//记录手指抬起的横坐标
 
  
private float xUp;
 
  
    
 
  
//menu当前是显示还是隐藏
 
  
private boolean isMenuVisible;
 
  
    
 
  
//用于计算手指滑动的速度
 
  
private VelocityTracker mVelocityTracker;
 
  
    
 
  
@Override
 
  
protected void
 
  
super.onCreate(savedInstanceState);
 
  
activity_main);
 
  
        init();
 
  
content.setOnTouchListener(this);
 
  
    }
 
  
    
 
  
private void
 
  
        WindowManager wm=getWindowManager();
 
  
screenWidth=wm.getDefaultDisplay().getWidth();
 
  
content=findViewById(.ll_content);
 
  
menu=findViewById(.ll_menu);
 
  
menuParams=(LayoutParams) menu.getLayoutParams();
 
  
//将menu的宽度设置为屏幕宽度减去menuPadding
 
  
menuParams.width=screenWidth-menuPadding;
 
  
leftEdge=-menuParams.width;
 
  
menuParams.leftMargin=leftEdge;
 
  
//将content的宽度设置为屏幕宽度
 
  
content.getLayoutParams().width=screenWidth;
 
  
    }
 
   
  
@Override
 
  
public boolean
 
  
        createVelocityTracker(event);
 
  
switch
 
  
case MotionEvent.ACTION_DOWN:
 
  
xDown=event.getRawX();
 
  
break;
 
  
case MotionEvent.ACTION_MOVE:
 
  
xMove=event.getRawX();
 
  
int distanceX=(int)(xMove-xDown);// 移动的距离
 
  
if(isMenuVisible){//判断当前Menu是否已经显示,如果true,说明已经显示
 
  
menuParams.leftMargin=distanceX;   
 
  
            }
 
  
else{
 
  
menuParams.leftMargin=leftEdge+distanceX;
 
  
            }
 
  
if(menuParams.leftMargin<leftEdge){
 
  
menuParams.leftMargin=leftEdge;
 
  
                
 
  
            }
 
  
else if(menuParams.leftMargin>rightEdge){
 
  
menuParams.leftMargin=rightEdge;
 
  
            }
 
  
menu.setLayoutParams(menuParams);
 
  
break;
 
  
case MotionEvent.ACTION_UP:
 
  
xUp=event.getRawX();
 
  
if(wantToShowMenu()){
 
  
if(shouldScrollToMenu()){
 
  
                    scrollToMenu();
 
  
                }
 
  
else{
 
  
                    scrollToContent();
 
  
                }
 
  
            }
 
  
else if(wantToShowContent()){
 
  
if(shouldScrollToContent()){
 
  
                    scrollToContent();
 
  
                }
 
  
else{
 
  
                    scrollToMenu();
 
  
                }
 
  
            }
 
  
            recycleVelocityTracker();
 
  
break;
 
  
default:
 
  
break;
 
  
        }
 
  
return true;
 
  
    }
 
  
    
 
  
/** 
 
  
     * 判断当前手势的意图是不是想显示content。如果手指移动的距离是负数,且当前menu是可见的,则认为当前手势是想要显示content。 
 
  
     *  
 
  
@return
 
  
     */  
 
  
private boolean
 
  
return xUp - xDown < 0 && isMenuVisible;  
 
  
    }  
 
  
    
 
  
/** 
 
  
     * 判断当前手势的意图是不是想显示menu。如果手指移动的距离是正数,且当前menu是不可见的,则认为当前手势是想要显示menu。 
 
  
     *  
 
  
@return
 
  
     */  
 
  
private boolean
 
  
return xUp-xDown>0&&!isMenuVisible;
 
  
    }
 
  
    
 
  
/** 
 
  
     * 判断是否应该滚动将menu展示出来。如果手指移动距离大于屏幕的1/2,或者手指移动速度大于SNAP_VELOCITY, 
 
  
     * 就认为应该滚动将menu展示出来。 
 
  
     *  
 
  
@return
 
  
     */ 
 
  
private boolean
 
  
return xUp-xDown>screenWidth/2||getScrollVelocity()>SNAP_VELOCITY;
 
  
    }
 
  
    
 
  
    
 
  
/** 
 
  
     * 判断是否应该滚动将content展示出来。如果手指移动距离加上menuPadding大于屏幕的1/2, 
 
  
     * 或者手指移动速度大于SNAP_VELOCITY, 就认为应该滚动将content展示出来。 
 
  
     *  
 
  
@return
 
  
     */  
 
  
private boolean
 
  
return xDown-xUp+menuPadding>screenWidth/2||getScrollVelocity()>SNAP_VELOCITY;
 
  
    }
 
  
    
 
  
//将屏幕滚动到menu界面,滚动速度设为30
 
  
private void
 
  
new
 
  
    }
 
  
//将屏幕滚到到content界面,滚动速度为-30
 
  
private void
 
  
new
 
  
    }
 
  
    
 
  
//创建velocityTracker对象,并将触摸content界面的滑动事件加入velocityTracker当中
 
  
private void
 
  
if(mVelocityTracker==null){
 
  
mVelocityTracker=VelocityTracker.obtain();
 
  
        }
 
  
mVelocityTracker.addMovement(event);
 
  
    }
 
  
//获取手指在Content界面滑动的速度
 
  
private int
 
  
mVelocityTracker.computeCurrentVelocity(1000);
 
  
int velocity=(int) mVelocityTracker.getXVelocity();
 
  
return Math.abs(velocity);
 
  
    }
 
  
//回收VelocityTracker
 
  
private void
 
  
mVelocityTracker.recycle();
 
  
mVelocityTracker=null;
 
  
    }
 
  
    
 
  
class ScrollTask extends
 
  
@Override
 
  
protected
 
  
int leftMargin=menuParams.leftMargin;
 
  
//根据传入速度来滚动界面,当滚动达到左边界或右边界,跳出循环
 
  
while(true){
 
  
                leftMargin=leftMargin+speed[0];
 
  
if(leftMargin>rightEdge){
 
  
rightEdge;
 
  
break;
 
  
                }
 
  
if(leftMargin<leftEdge){
 
  
leftEdge;
 
  
break;
 
  
                }
 
  
                publishProgress(leftMargin);
 
  
                sleep(10);
 
  
            }
 
  
if(speed[0]>0){
 
  
isMenuVisible=true;
 
  
            }
 
  
else{
 
  
isMenuVisible=false;
 
  
            }
 
  
return
 
  
        }
 
  
        
 
  
@Override
 
  
protected void
 
  
menuParams.leftMargin=values[0];
 
  
menu.setLayoutParams(menuParams);
 
  
        }
 
  
@Override
 
  
protected void
 
  
menuParams.leftMargin=result;
 
  
menu.setLayoutParams(menuParams);
 
  
        }
 
  
        
 
  
private void sleep(long
 
  
try
 
  
sleep(mills);
 
  
catch
 
  
                e.printStackTrace();
 
  
            }
 
  
        }
 
  
    }
 
  
}



初始化的时候调用initValues方法,在这里面将内容布局的宽度设定为屏幕的宽度,菜单布局的宽度设定为屏幕的宽度减去menuPadding值,这样可以保证在菜单布局展示的时候,仍有一部分内容布局可以看到。如果不在初始化的时候重定义两个布局宽度,就会按照layout文件里面声明的一样,两个布局都是fill_parent,这样就无法实现滑动菜单的效果了。然后将菜单布局的左偏移量设置为负的菜单布局的宽度,这样菜单布局就会被完全隐藏,只有内容布局会显示在界面上。

之后给内容布局注册监听事件,这样当手指在内容布局上滑动的时候就会触发onTouch事件。在onTouch事件里面,根据手指滑动的距离会改变菜单布局的左偏移量,从而控制菜单布局的显示和隐藏。当手指离开屏幕的时候,会判断应该滑动到菜单布局还是内容布局,判断依据是根据手指滑动的距离或者滑动的速度.


当前Demo只适用于单个Activity.