Android学习之可滑动当前的Activity视图看见上一个活动的视图

先看一下我的效果图吧:

Android学习之可滑动当前的Activity视图看见上一个活动的视图_第1张图片Android学习之可滑动当前的Activity视图看见上一个活动的视图_第2张图片Android学习之可滑动当前的Activity视图看见上一个活动的视图_第3张图片


好大的图啊!!!

百度音乐由一个很酷的功能,当前的UI可以滑动,然后看见上一个活动的UI,当时顿时觉得百度的牛人好多啊,能将如此前沿的技术应用到app上。当然如果你熟悉了Android的框架,熟知Activity的布局原理,那么实现起来还是很简单的。本人粗略的实现过,用的是View.layout(l, t, r, b)方法移动布局,总觉得有点山寨,但终究还是实现了嘛。好了不多说了,看我自己实现的方式吧。

首先准备创建两个Activity,至于布局xml文件怎么写,大家随便了,两个活动用一个xml布局即可。

为了方便大家copy(PS:本来我不想全部代码包括xml文件都粘贴在这里的,但是鉴于有些人实在太懒,连布局文件都不愿意随便写一个,然后在评论里喊,楼主,源码!我还是贴出来吧!)

一个简单的布局xml文件:layout_value_animation_layout




    

第一个活动:LayoutValueAnimationExampleA

package org.mrchen.commlib.example;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class LayoutValueAnimationExampleA extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		View root = getLayoutInflater().inflate(R.layout.layout_value_animation_layout, null);
		setContentView(root);

		//
		root.setBackgroundColor(Color.parseColor("#978856"));
		TextView text = (TextView) findViewById(R.id.layout_value_animation_layout_text);
		text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25);
		text.setText("A\n Click Me go to Activity LayoutValueAnimationExampleB");
		text.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				startActivity(new Intent(LayoutValueAnimationExampleA.this, LayoutValueAnimationExampleB.class));
			}
		});
	}
}

第二个活动:LayoutValueAnimationExampleB

package org.mrchen.commlib.example;

import org.mrchen.commlib.animation.LayoutValueAnimation;
import org.mrchen.commlib.animation.LayoutValueAnimation.LayoutValueParams;
import org.mrchen.commlib.animation.SmoothInterpolator;
import org.mrchen.commlib.helper.LogHelper;
import org.mrchen.commlib.helper.ScreenHelper;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;

/**
 * 注意当前的Activity在AndroidManifest.xml中的注册信息,主题应用了透明主题:AppTheme.Transparent
 * 
 * @author chenjianli
 * 
 */
public class LayoutValueAnimationExampleB extends Activity {

	private final String TAG = "LayoutValueAnimationExampleB";

	private View mRootView;
	private LayoutValueAnimation mLayoutValueAnimation;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mRootView = getLayoutInflater().inflate(R.layout.layout_value_animation_layout, null);
		setContentView(mRootView);

		//
		mRootView.setBackgroundColor(Color.parseColor("#46b525"));
		TextView text = (TextView) findViewById(R.id.layout_value_animation_layout_text);
		text.setText("B");
		mRootView.setOnTouchListener(movingEventListener);
	}

	private OnTouchListener movingEventListener = new OnTouchListener() {

		int lastX, lastY;

		public boolean onTouch(View v, MotionEvent event) {
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				lastX = (int) event.getRawX();
				lastY = (int) event.getRawY();
			}
			if (event.getAction() == MotionEvent.ACTION_MOVE) {
				int dx = (int) event.getRawX() - lastX;
				int dy = (int) event.getRawY() - lastY;
				// TODO
				dy = 0;

				int left = v.getLeft() + dx;
				int top = v.getTop() + dy;
				int right = v.getRight() + dx;
				int bottom = v.getBottom() + dy;

				v.layout(left, top, right, bottom);

				lastX = (int) event.getRawX();
				lastY = (int) event.getRawY();

			}

			if (event.getAction() == MotionEvent.ACTION_UP) {

				int left = v.getLeft();
				int top = v.getTop();
				int right = v.getRight();
				int bottom = v.getBottom();

				LogHelper.d(TAG, "l:" + left + ",t:" + top + ",r:" + right + ",b:" + bottom);
				finishActivity(v, ScreenHelper.mScreenWidth - left);
			}
			return true;
		}
	};

	public boolean onKeyDown(int keyCode, android.view.KeyEvent event) {
		if (!isFinishing()) {
			finishActivity(mRootView, ScreenHelper.mScreenWidth);
			return true;
		}
		return super.onKeyDown(keyCode, event);
	};

	private void finishActivity(View v, int size) {
		int duration = 666;
		if (mLayoutValueAnimation == null) {
			ScreenHelper.initialize(LayoutValueAnimationExampleB.this);
			mLayoutValueAnimation = new LayoutValueAnimation(new LayoutValueParams(size,
					LayoutValueParams.DIRECTION_RIGHT), duration);
			mLayoutValueAnimation.setInterpolator(new SmoothInterpolator());
		}
		mLayoutValueAnimation.startAnimation(v);

		v.postDelayed(new Runnable() {
			@Override
			public void run() {
				LayoutValueAnimationExampleB.this.finish();
			}
		}, duration);
	}
}

许多人可能要崩溃了,怎么回事,这么多类没有,由一些类是我自己库中常用的工具类,比如ScreenHelper,这个类没什么功能,就是得到屏幕的宽度啥的,调用初始化方法
initialize(context)
完成初始化的工作,就可以拿来用了。

这里由必要贴一下

LayoutValueAnimation
类,这个类是拜一位大侠的文章所赐,产生出的属于我自己的衍生品,大家拿来用就好,具体的注释我已经卸载类里面了。

package org.mrchen.commlib.animation;

import org.mrchen.commlib.animation.LayoutValueAnimation.LayoutValueParams;
import org.mrchen.commlib.helper.LogHelper;

import android.view.View;
import android.view.animation.AnimationUtils;

/**
 * 促使调用mTargetView.layout(l,t,r,b); 
* 参数配置类:{@link LayoutValueParams} * * @author chenjianli * */ public class LayoutValueAnimation extends AbstractAnimation { private final static String TAG = "LayoutValueAnimation"; private int mCurrSize; private int originalLeft; private int originalRight; private int originalTop; private int originalBottom; private int targetLeft; private int targetRight; private int targetTop; private int targetBottom; /** * {@link LayoutValueAnimation} 的辅助参数类,用于指定位移和移动方向
* * @author chenjianli * */ public static class LayoutValueParams { public int size; public static final int DIRECTION_LEFT = 1; public static final int DIRECTION_RIGHT = 2; public static final int DIRECTION_TOP = 3; public static final int DIRECTION_BOTTOM = 4; public int direction; /** * * @param size * 只能是正整数 * @param direction * 指明运动方向,有
* {@link LayoutValueParams.DIRECTION_LEFT},
* {@link LayoutValueParams.DIRECTION_RIGHT},
* {@link LayoutValueParams.DIRECTION_TOP},
* {@link LayoutValueParams.DIRECTION_BOTTOM},
*/ public LayoutValueParams(int size, int direction) { this.size = size; this.direction = direction; } } private LayoutValueParams mParams; public LayoutValueAnimation(LayoutValueParams params, int duration) { mParams = params; mDuration = duration; } // 启动动画 public void startAnimation(View view) { if (view != null) { mTargetView = view; } else { LogHelper.e(TAG, "view 不能为空"); return; } if (isFinished) { mDurationReciprocal = 1.0f / (float) mDuration; isFinished = false; // 记录下动画开始的时间 mStartTime = AnimationUtils.currentAnimationTimeMillis(); mDSize = mParams.size; LogHelper.d(TAG, "mDSize=" + mDSize); int l = mTargetView.getLeft(); int t = mTargetView.getTop(); int r = mTargetView.getRight(); int b = mTargetView.getBottom(); LogHelper.d(TAG, "startAnimation >原始的> l = " + l + ", t = " + t + ", r = " + r + ", b = " + b); originalLeft = l; originalRight = r; originalTop = t; originalBottom = b; mHandler.start(); } } @Override public boolean computeSize() { // TODO Auto-generated method stub if (isFinished) { return isFinished; } int timePassed = (int) (AnimationUtils.currentAnimationTimeMillis() - mStartTime); if (timePassed <= mDuration) { float x = timePassed * mDurationReciprocal; if (mInterpolator != null) { x = mInterpolator.getInterpolation(x); } switch (mParams.direction) { case LayoutValueParams.DIRECTION_LEFT: case LayoutValueParams.DIRECTION_TOP: mCurrSize = -Math.round(x * mDSize); break; case LayoutValueParams.DIRECTION_RIGHT: case LayoutValueParams.DIRECTION_BOTTOM: mCurrSize = Math.round(x * mDSize); break; } } else { isFinished = true; switch (mParams.direction) { case LayoutValueParams.DIRECTION_LEFT: case LayoutValueParams.DIRECTION_TOP: mCurrSize = -mDSize; break; case LayoutValueParams.DIRECTION_RIGHT: case LayoutValueParams.DIRECTION_BOTTOM: mCurrSize = mDSize; break; } } // 计算最终目标坐标 switch (mParams.direction) { case LayoutValueParams.DIRECTION_LEFT: case LayoutValueParams.DIRECTION_RIGHT: targetLeft = originalLeft + mCurrSize; targetRight = originalRight + mCurrSize; targetTop = originalTop; targetBottom = originalBottom; break; case LayoutValueParams.DIRECTION_TOP: case LayoutValueParams.DIRECTION_BOTTOM: targetTop = originalTop + mCurrSize; targetBottom = originalBottom + mCurrSize; targetLeft = originalLeft; targetRight = originalRight; break; } LogHelper.d(TAG, "computeSize >目标> l = " + targetLeft + ", t = " + targetTop + ", r = " + targetRight + ", b = " + targetBottom); applySize(); return isFinished; } @Override public void applySize() { // TODO Auto-generated method stub if (mTargetView != null && mTargetView.getVisibility() != View.GONE) { mTargetView.layout(targetLeft, targetTop, targetRight, targetBottom); } } }

卧槽,又有一个类:AbstractAnimation

package org.mrchen.commlib.animation;

import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.animation.Interpolator;

public abstract class AbstractAnimation implements AbstractAnimationImpl {

	private final int FRAME_TIME = 20;// 一帧的时间 毫秒
	protected View mTargetView;// 执行"动画"的目标View
	protected Interpolator mInterpolator;// 插值器
	protected boolean isFinished = true;// 动画结束标识;

	protected int mDuration; // 动画运行的时间
	protected long mStartTime;// 动画开始时间
	protected float mDurationReciprocal;// Reciprocal:相互的,倒数的
	protected int mDSize; // 需要改变view大小的增量

	private AnimationListener mAnimationListener;

	public interface AnimationListener {
		public void animationEnd(View v);
	}

	public void setOnAnimationListener(AnimationListener listener) {
		mAnimationListener = listener;
	}

	public void setInterpolator(Interpolator interpolator) {
		mInterpolator = interpolator;
	}

	public boolean isFinished() {
		return isFinished;
	}

	public void setDuration(int duration) {
		mDuration = duration;
	}

	protected AnimationHandler mHandler = new AnimationHandler();

	class AnimationHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {

			if (msg.what == 1) {
				if (!computeSize()) {
					mHandler.sendEmptyMessageDelayed(1, FRAME_TIME);
				} else {
					if (mAnimationListener != null) {
						mAnimationListener.animationEnd(mTargetView);
					}
				}
			}
			super.handleMessage(msg);
		}

		public void start() {
			sendEmptyMessage(1);
		}
	}

}

没完了:AbstractAnimationImpl

package org.mrchen.commlib.animation;

import android.view.View;

public interface AbstractAnimationImpl {
	public boolean computeSize();// 计算变量

	public void applySize();// 应用计算的变量

	public void startAnimation(View v);// 启动动画
}

好了,代码基本上差不多了,最后贴一下AndroidManifest.xml文件就打工告成了,大家可以运行看下效果。




    

    
        
            
                

                
            
        
        
        
    

看来还有主题没贴出来:

	
	
	    
	    
	
	    
	    
	
	    


你可能感兴趣的:(Android)