zoukankan      html  css  js  c++  java
  • 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
     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>
     * 参数配置类:{@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} 的辅助参数类,用于指定位移和移动方向 <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>
    		 *            {@link LayoutValueParams.DIRECTION_LEFT},<br>
    		 *            {@link LayoutValueParams.DIRECTION_RIGHT},<br>
    		 *            {@link LayoutValueParams.DIRECTION_TOP},<br>
    		 *            {@link 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>


     
  • 相关阅读:
    java代码读取yarn聚合目录日志
    Java内存区域的划分和异常
    Hbase restFul API
    Sql Server函数全解(一)字符串函数
    Sql Server之数据类型详解
    Sql Server之使用T_SQL创建,修改,查看数据库信息
    《Java编程思想》笔记 第一章 对象导论
    spring之Autowire
    spring之scope作用域
    spring之注入类型
  • 原文地址:https://www.cnblogs.com/riskyer/p/3402622.html
Copyright © 2011-2022 走看看