仿网易、人人滑动界面的实现

这个效果的实现是参考android的SlidingDrawer类。大家用过就知道SlidingDrawer能够实现平滑的滑动来展示内容。这个和网易、人人的滑动界面有异曲同工之处。所以我看了一下SlidingDrawer类的源码。发现了布局的移动是依靠View类的offsetTopAndBottom()方法实现的。同时也有offsetLeftAndRight()方法,这个就是我用到的了。关于移动的动画,就是每隔一段时间移动一段距离,形成了人眼中的动画。实现的代码不多,不到200行。

效果图如下:

原始界面:

 

点击button之后,向右滑动:

实现代码如下:

package com.example.learn;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;

/**
 * 这个布局移动参考SlidingDrawer
 * 
 * @author admin
 * 
 */
public class MainActivity extends Activity implements OnTouchListener {

	private FrameLayout frameLayout1;
	private FrameLayout frameLayout2;
	private RelativeLayout relativeLayout;
	
	private int screenHeight;
	private Button button;
	
	private final Handler mHandler = new SlidingHandler();
	private VelocityTracker velocityTracker;

	private static final int ANIMATION_DURATION = 20;// 每次移动的时间间隔,20ms
	private long mCurrentAnimationTime;// 当前时间,是SystemClock的时间
	private int mCurrentPosition = 0;// 当前的位置
	boolean isShown = false;// 后面的布局是否已经显示

	private int offsetX;// 平移总量
	private int scale;// 每次平移的距离

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();

		initView();

	}

	private void init() {
		velocityTracker = VelocityTracker.obtain();
		screenHeight = getWindowManager().getDefaultDisplay().getHeight();
	}

	private void initView() {

		relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
		frameLayout1 = (FrameLayout) findViewById(R.id.frameLayout1);
		frameLayout2 = (FrameLayout) findViewById(R.id.frameLayout2);
		button = (Button) findViewById(R.id.button);

		frameLayout2.setOnTouchListener(this);

		button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				moveLayout();
			}
		});

	}

	/**
	 * 移动布局,偏移量为offsetX
	 */
	private void moveLayout() {
//		System.out.println(isShown);
		offsetX = frameLayout1.getWidth();
		scale = offsetX / 10;//分成十次移动,形成动画
		long now = SystemClock.uptimeMillis();
		mCurrentAnimationTime = now + ANIMATION_DURATION;
		mHandler.sendEmptyMessageAtTime(MSG_ANIMATE, mCurrentAnimationTime);

	}

	/**
	 * 移动布局的指定的偏移量
	 * @param scale 位移量
	 *            
	 */
	private void moveLayout(int scale) {
		int left = frameLayout2.getLeft();

		if ((left + scale) < offsetX && (left + scale) > 0) {
			frameLayout2.offsetLeftAndRight(scale);
			mCurrentPosition += scale;
		} else if ((left + scale) >= offsetX) {
			frameLayout2.offsetLeftAndRight(offsetX - left);
			mCurrentPosition += offsetX - left;
			isShown = true;
		} else {
			frameLayout2.offsetLeftAndRight(0 - left);
			mCurrentPosition += 0 - left;
			isShown = false;
		}
		relativeLayout.invalidate();
		frameLayout2.forceLayout();// 锁定布局,使它不受SlidingDrawer的影响
	}

	/**
	 * 通过 不断的移动布局,形成动画。
	 */
	private void doAnimation() {
		if (isShown) {
			moveLayout(-scale);

			if (mCurrentPosition <= 0) {

				mHandler.removeMessages(MSG_ANIMATE);
			} else {
				mCurrentAnimationTime += ANIMATION_DURATION;
				mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE),
						mCurrentAnimationTime);
			}

		} else {
			moveLayout(scale);
			// mCurrentPosition += scale;
			if (mCurrentPosition >= offsetX) {
				mHandler.removeMessages(MSG_ANIMATE);
			} else {
				mCurrentAnimationTime += ANIMATION_DURATION;
				mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE),
						mCurrentAnimationTime);
				// System.out.println("------------");
			}
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

	float x = 0;
	// int width = 0;
	int mTouchDelta;

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		offsetX = frameLayout1.getWidth();
		scale = offsetX /10;
		switch (v.getId()) {
		case R.id.frameLayout2:
			velocityTracker.addMovement(event);
			velocityTracker.computeCurrentVelocity(1000);
			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				x = event.getX();
//				int startLeft = frameLayout2.getLeft();
				
				break;
			case MotionEvent.ACTION_MOVE:

				scale = (int) (event.getX() - x);

				moveLayout(scale);

				break;
			case MotionEvent.ACTION_UP:
				float velocityX = velocityTracker.getXVelocity();
				int endLeft = frameLayout2.getLeft();
				mCurrentAnimationTime = SystemClock.uptimeMillis()
						+ ANIMATION_DURATION;
				if (Math.abs(velocityX) > 200) {
					if (velocityX > 0 && isShown == false) {
						mHandler.sendEmptyMessageAtTime(MSG_ANIMATE,
								mCurrentAnimationTime);
					} else if (velocityX < 0 && isShown == true) {
						mHandler.sendEmptyMessageAtTime(MSG_ANIMATE,
								mCurrentAnimationTime);
					}
				} else {
					if (endLeft >= offsetX / 2) {
						if (isShown) {
							isShown = false;
						}
						mHandler.sendEmptyMessageAtTime(MSG_ANIMATE,
								mCurrentAnimationTime);
					} else {
						if (!isShown) {
							isShown = true;
						}
						mHandler.sendEmptyMessageAtTime(MSG_ANIMATE,
								mCurrentAnimationTime);
					}

				}
//				System.out.println("velocityX:" + velocityX);

				break;
			}
			break;
		}
		return true;
	}

	public static final int MSG_ANIMATE = 1;

	private class SlidingHandler extends Handler {

		public void handleMessage(Message m) {
			switch (m.what) {
			case MSG_ANIMATE:
				doAnimation();
				break;
			}
		}

	}
}


转帖请注明出处:http://blog.csdn.net/jingyening/article/details/8504530

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值