这个效果的实现是参考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.youkuaiyun.com/jingyening/article/details/8504530