模仿的豌豆荚滑动Menu 的 实现

效果:



其实就是利用监听手势。将主页面滑开。将下面一层布局的菜单展露出来。下面是布局文件。

<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;
		}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值