当前位置: 代码迷 >> Android >> Android学习之可滑动目前的Activity视图看见上一个活动的视图
  详细解决方案

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

热度:40   发布时间:2016-04-28 07:29:11.0
Android学习之可滑动当前的Activity视图看见上一个活动的视图

先看一下我的效果图吧:


好大的图啊!!!

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

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

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

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

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Button" />    <ToggleButton        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="ToggleButton" />    <CheckBox        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="CheckBox" />    <RadioButton        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="RadioButton" />    <SeekBar        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <RatingBar        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/layout_value_animation_layout_text"        android:layout_width="fill_parent"        android:layout_height="0dip"        android:layout_weight="1"        android:gravity="center"        android:text="A"        android:textAppearance="?android:attr/textAppearanceLarge"        android:textSize="80sp" /></LinearLayout>

第一个活动: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); <br> * 参数配置类:[email protected] 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;	/**	 * [email protected] LayoutValueAnimation} 的辅助参数类,用于指定位移和移动方向 <br>	 * 	 * @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		 *            指明运动方向,有<br>		 *            [email protected] LayoutValueParams.DIRECTION_LEFT},<br>		 *            [email protected] LayoutValueParams.DIRECTION_RIGHT},<br>		 *            [email protected] LayoutValueParams.DIRECTION_TOP},<br>		 *            [email protected] LayoutValueParams.DIRECTION_BOTTOM},<br>		 */		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文件就打工告成了,大家可以运行看下效果。

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="org.mrchen.commlib.example"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="14" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="org.mrchen.commlib.example.LayoutValueAnimationExampleA"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <activity            android:name="org.mrchen.commlib.example.LayoutValueAnimationExampleB"            android:label="@string/app_name"            android:theme="@style/AppTheme.Transparent" >        </activity>    </application></manifest>
看来还有主题没贴出来:

	<resources>		    <!--	        Base application theme, dependent on API level. This theme is replaced	        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.	    -->	    <style name="AppBaseTheme" parent="android:Theme.Black.NoTitleBar">	        <!--	            Theme customizations available in newer API levels can go in	            res/values-vXX/styles.xml, while customizations related to	            backward-compatibility can go here.	        -->	    </style>		    <!-- Application theme. -->	    <style name="AppTheme" parent="AppBaseTheme">		        <!-- All customizations that are NOT specific to a particular API-level can go here. -->	        <item name="android:windowContentOverlay">@null</item>	    </style>		    <style name="AppTheme.Transparent" parent="AppTheme">	        <!-- All customizations that are NOT specific to a particular API-level can go here. -->	        <item name="android:windowBackground">@android:color/transparent</item>	        <item name="android:colorBackgroundCacheHint">@null</item>	        <item name="android:windowIsTranslucent">true</item>	        <item name="android:windowAnimationStyle">@android:style/Animation</item>	    </style></resources>


  相关解决方案