Android 向右滑动销毁(finish)Activity, 随着手势的滑动而滑动的效果

转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/20934541),请尊重他人的辛勤劳动成果,谢谢!

今天给大家带来一个向右滑动销毁Activity的效果,Activtiy随着手指的移动而移动,该效果在Android应用中还是比较少见的,在IOS中就比较常见了,例如“网易新闻” ,"美食杰" , "淘宝"等应用采用此效果,而Android应用中“知乎”采用的也是这种滑动切换Activity的效果, 不过我发现“淘宝”并没有随着手势的移动而移动,只是捕捉到滑动手势,然后产生平滑切换界面的动画效果,这个在Android中还是很好实现的,  网上很多滑动切换Activity的Demo貌似都是这种效果的吧,如果要实现类似“网易新闻”的随手势的滑动而滑动,似乎就要复杂一些了,我之前在IOS中看到"网易新闻"的这种效果就很感兴趣,然后群里也有朋友问我怎么实现类似“知乎”这个应用的滑动切换的效果,我也特意去下了一个“知乎”,在之前的实现中我遇到了一些瓶颈,没有实现出来就搁置了在那里,今天无意中看到给Activity设置透明的背景,于是乎我恍然大悟,真是灵感来源于瞬间,不能强求啊,然后自己就将此效果实现了出来,给大家分享一下,希望给有此需求的你一点点帮助。

不知道大家对Scroller这个类以及View的scrollBy() 和scrollTo()的使用熟悉不?我之前介绍了Scroller类的滑动实现原理Android 带你从源码的角度解析Scroller的滚动实现原理,在那里面也介绍了scrollBy() 和scrollTo()方法,不明白的同学可以去看看,这对实现此效果有很大的帮助,了解scrollBy() 和scrollTo()的朋友应该知道,如果想对某个View(例如Button)就行滚动,我们直接调用该View(Button)的scrollBy()方法,并不是该View(Button)进行滚动,而是该View里面的内容(Button上面的文字)进行滚动,所以我们假如要让View整体滚动就需要对其View的父布局调用scrollBy()方法,回到这篇文章来,假如我们想要对一个Activity进行滚动,我们就需求对这个Activity布局文件的顶层布局的父布局进行滚动

例如下面的XML布局文件

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.     xmlns:tools="http://schemas.android.com/tools" 
  3.     android:layout_width="match_parent" 
  4.     android:layout_height="match_parent" 
  5.     android:gravity="center" 
  6.     android:orientation="vertical" > 
  7.  
  8.  
  9. </LinearLayout> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >


</LinearLayout>
如果我们对LinearLayout进行滚动,并不能实现我们想要的效果,而只能对LinearLayout里面的内容或者说是子View进行滚动,所以我们需要获取利用LinearLayout的getParent()方法获取父布局,其实Android系统会对我们的布局文件的最外层套一个FrameLayout,所以我们其实就是对FrameLayout进行滚动就行了

了解了实现的原理之后,我们就来编写代码吧,首先新建一个android工程,取名SildingFinish

由于我们的需求可能不是在一个界面提供这个滑动切换的效果,所以我们应该将这部分滑动的逻辑抽取出来,我这里就他写成了一个扩展RelativeLayout的自定义布局SildingFinishLayout,首先我们看其代码

  1. package com.example.view; 
  2.  
  3. import android.content.Context; 
  4. import android.util.AttributeSet; 
  5. import android.view.MotionEvent; 
  6. import android.view.View; 
  7. import android.view.View.OnTouchListener; 
  8. import android.view.ViewConfiguration; 
  9. import android.view.ViewGroup; 
  10. import android.widget.AbsListView; 
  11. import android.widget.RelativeLayout; 
  12. import android.widget.ScrollView; 
  13. import android.widget.Scroller; 
  14.  
  15. /**
  16. * 自定义可以滑动的RelativeLayout, 类似于IOS的滑动删除页面效果,当我们要使用
  17. * 此功能的时候,需要将该Activity的顶层布局设置为SildingFinishLayout,
  18. * 然后需要调用setTouchView()方法来设置需要滑动的View
  19. *
  20. * @author xiaanming
  21. *
  22. * @blog http://blog.csdn.net/xiaanming
  23. *
  24. */ 
  25. public class SildingFinishLayout extends RelativeLayout implements 
  26.         OnTouchListener { 
  27.     /**
  28.      * SildingFinishLayout布局的父布局
  29.      */ 
  30.     private ViewGroup mParentView; 
  31.     /**
  32.      * 处理滑动逻辑的View
  33.      */ 
  34.     private View touchView; 
  35.     /**
  36.      * 滑动的最小距离
  37.      */ 
  38.     private int mTouchSlop; 
  39.     /**
  40.      * 按下点的X坐标
  41.      */ 
  42.     private int downX; 
  43.     /**
  44.      * 按下点的Y坐标
  45.      */ 
  46.     private int downY; 
  47.     /**
  48.      * 临时存储X坐标
  49.      */ 
  50.     private int tempX; 
  51.     /**
  52.      * 滑动类
  53.      */ 
  54.     private Scroller mScroller; 
  55.     /**
  56.      * SildingFinishLayout的宽度
  57.      */ 
  58.     private int viewWidth; 
  59.     /**
  60.      * 记录是否正在滑动
  61.      */ 
  62.     private boolean isSilding; 
  63.      
  64.     private OnSildingFinishListener onSildingFinishListener; 
  65.     private boolean isFinish; 
  66.      
  67.  
  68.     public SildingFinishLayout(Context context, AttributeSet attrs) { 
  69.         this(context, attrs, 0); 
  70.     } 
  71.  
  72.     public SildingFinishLayout(Context context, AttributeSet attrs, int defStyle) { 
  73.         super(context, attrs, defStyle); 
  74.  
  75.         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 
  76.         mScroller = new Scroller(context); 
  77.     } 
  78.  
  79.     @Override 
  80.     protected void onLayout(boolean changed, int l, int t, int r, int b) { 
  81.         super.onLayout(changed, l, t, r, b); 
  82.         if (changed) { 
  83.             // 获取SildingFinishLayout所在布局的父布局 
  84.             mParentView = (ViewGroup) this.getParent(); 
  85.             viewWidth = this.getWidth(); 
  86.         } 
  87.     } 
  88.  
  89.     /**
  90.      * 设置OnSildingFinishListener, 在onSildingFinish()方法中finish Activity
  91.      *
  92.      * @param onSildingFinishListener
  93.      */ 
  94.     public void setOnSildingFinishListener( 
  95.             OnSildingFinishListener onSildingFinishListener) { 
  96.         this.onSildingFinishListener = onSildingFinishListener; 
  97.     } 
  98.  
  99.     /**
  100.      * 设置Touch的View
  101.      *
  102.      * @param touchView
  103.      */ 
  104.     public void setTouchView(View touchView) { 
  105.         this.touchView = touchView; 
  106.         touchView.setOnTouchListener(this); 
  107.     } 
  108.  
  109.     public View getTouchView() { 
  110.         return touchView; 
  111.     } 
  112.  
  113.     /**
  114.      * 滚动出界面
  115.      */ 
  116.     private void scrollRight() { 
  117.         final int delta = (viewWidth + mParentView.getScrollX()); 
  118.         // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item 
  119.         mScroller.startScroll(mParentView.getScrollX(), 0, -delta + 1, 0
  120.                 Math.abs(delta)); 
  121.         postInvalidate(); 
  122.     } 
  123.  
  124.     /**
  125.      * 滚动到起始位置
  126.      */ 
  127.     private void scrollOrigin() { 
  128.         int delta = mParentView.getScrollX(); 
  129.         mScroller.startScroll(mParentView.getScrollX(), 0, -delta, 0
  130.                 Math.abs(delta)); 
  131.         postInvalidate(); 
  132.     } 
  133.  
  134.     /**
  135.      * touch的View是否是AbsListView, 例如ListView, GridView等其子类
  136.      *
  137.      * @return
  138.      */ 
  139.     private boolean isTouchOnAbsListView() { 
  140.         return touchView instanceof AbsListView ? true : false
  141.     } 
  142.  
  143.     /**
  144.      * touch的view是否是ScrollView或者其子类
  145.      *
  146.      * @return
  147.      */ 
  148.     private boolean isTouchOnScrollView() { 
  149.         return touchView instanceof ScrollView ? true : false
  150.     } 
  151.  
  152.     @Override 
  153.     public boolean onTouch(View v, MotionEvent event) { 
  154.         switch (event.getAction()) { 
  155.         case MotionEvent.ACTION_DOWN: 
  156.             downX = tempX = (int) event.getRawX(); 
  157.             downY = (int) event.getRawY(); 
  158.             break
  159.         case MotionEvent.ACTION_MOVE: 
  160.             int moveX = (int) event.getRawX(); 
  161.             int deltaX = tempX - moveX; 
  162.             tempX = moveX; 
  163.             if (Math.abs(moveX - downX) > mTouchSlop 
  164.                     && Math.abs((int) event.getRawY() - downY) < mTouchSlop) { 
  165.                 isSilding = true
  166.  
  167.                 // 若touchView是AbsListView, 
  168.                 // 则当手指滑动,取消item的点击事件,不然我们滑动也伴随着item点击事件的发生 
  169.                 if (isTouchOnAbsListView()) { 
  170.                     MotionEvent cancelEvent = MotionEvent.obtain(event); 
  171.                     cancelEvent 
  172.                             .setAction(MotionEvent.ACTION_CANCEL 
  173.                                     | (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT)); 
  174.                     v.onTouchEvent(cancelEvent); 
  175.                 } 
  176.  
  177.             } 
  178.  
  179.             if (moveX - downX >= 0 && isSilding) { 
  180.                 mParentView.scrollBy(deltaX, 0); 
  181.  
  182.                 // 屏蔽在滑动过程中ListView ScrollView等自己的滑动事件 
  183.                 if (isTouchOnScrollView() || isTouchOnAbsListView()) { 
  184.                     return true
  185.                 } 
  186.             } 
  187.             break
  188.         case MotionEvent.ACTION_UP: 
  189.             isSilding = false
  190.             if (mParentView.getScrollX() <= -viewWidth / 2) { 
  191.                 isFinish = true
  192.                 scrollRight(); 
  193.             } else
  194.                 scrollOrigin(); 
  195.                 isFinish = false
  196.             } 
  197.             break
  198.         } 
  199.  
  200.         // 假如touch的view是AbsListView或者ScrollView 我们处理完上面自己的逻辑之后 
  201.         // 再交给AbsListView, ScrollView自己处理其自己的逻辑 
  202.         if (isTouchOnScrollView() || isTouchOnAbsListView()) { 
  203.             return v.onTouchEvent(event); 
  204.         } 
  205.  
  206.         // 其他的情况直接返回true 
  207.         return true
  208.     } 
  209.  
  210.     @Override 
  211.     public void computeScroll() { 
  212.         // 调用startScroll的时候scroller.computeScrollOffset()返回true, 
  213.         if (mScroller.computeScrollOffset()) { 
  214.             mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); 
  215.             postInvalidate(); 
  216.  
  217.             if (mScroller.isFinished()) { 
  218.  
  219.                 if (onSildingFinishListener != null && isFinish) { 
  220.                     onSildingFinishListener.onSildingFinish(); 
  221.                 } 
  222.             } 
  223.         } 
  224.     } 
  225.      
  226.  
  227.     public interface OnSildingFinishListener { 
  228.         public void onSildingFinish(); 
  229.     } 
  230.  
package com.example.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.Scroller;

/**
 * 自定义可以滑动的RelativeLayout, 类似于IOS的滑动删除页面效果,当我们要使用
 * 此功能的时候,需要将该Activity的顶层布局设置为SildingFinishLayout,
 * 然后需要调用setTouchView()方法来设置需要滑动的View
 * 
 * @author xiaanming
 * 
 * @blog http://blog.csdn.net/xiaanming
 * 
 */
public class SildingFinishLayout extends RelativeLayout implements
		OnTouchListener {
	/**
	 * SildingFinishLayout布局的父布局
	 */
	private ViewGroup mParentView;
	/**
	 * 处理滑动逻辑的View
	 */
	private View touchView;
	/**
	 * 滑动的最小距离
	 */
	private int mTouchSlop;
	/**
	 * 按下点的X坐标
	 */
	private int downX;
	/**
	 * 按下点的Y坐标
	 */
	private int downY;
	/**
	 * 临时存储X坐标
	 */
	private int tempX;
	/**
	 * 滑动类
	 */
	private Scroller mScroller;
	/**
	 * SildingFinishLayout的宽度
	 */
	private int viewWidth;
	/**
	 * 记录是否正在滑动
	 */
	private boolean isSilding;
	
	private OnSildingFinishListener onSildingFinishListener;
	private boolean isFinish;
	

	public SildingFinishLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public SildingFinishLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
		mScroller = new Scroller(context);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (changed) {
			// 获取SildingFinishLayout所在布局的父布局
			mParentView = (ViewGroup) this.getParent();
			viewWidth = this.getWidth();
		}
	}

	/**
	 * 设置OnSildingFinishListener, 在onSildingFinish()方法中finish Activity
	 * 
	 * @param onSildingFinishListener
	 */
	public void setOnSildingFinishListener(
			OnSildingFinishListener onSildingFinishListener) {
		this.onSildingFinishListener = onSildingFinishListener;
	}

	/**
	 * 设置Touch的View
	 * 
	 * @param touchView
	 */
	public void setTouchView(View touchView) {
		this.touchView = touchView;
		touchView.setOnTouchListener(this);
	}

	public View getTouchView() {
		return touchView;
	}

	/**
	 * 滚动出界面
	 */
	private void scrollRight() {
		final int delta = (viewWidth + mParentView.getScrollX());
		// 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item
		mScroller.startScroll(mParentView.getScrollX(), 0, -delta + 1, 0,
				Math.abs(delta));
		postInvalidate();
	}

	/**
	 * 滚动到起始位置
	 */
	private void scrollOrigin() {
		int delta = mParentView.getScrollX();
		mScroller.startScroll(mParentView.getScrollX(), 0, -delta, 0,
				Math.abs(delta));
		postInvalidate();
	}

	/**
	 * touch的View是否是AbsListView, 例如ListView, GridView等其子类
	 * 
	 * @return
	 */
	private boolean isTouchOnAbsListView() {
		return touchView instanceof AbsListView ? true : false;
	}

	/**
	 * touch的view是否是ScrollView或者其子类
	 * 
	 * @return
	 */
	private boolean isTouchOnScrollView() {
		return touchView instanceof ScrollView ? true : false;
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			downX = tempX = (int) event.getRawX();
			downY = (int) event.getRawY();
			break;
		case MotionEvent.ACTION_MOVE:
			int moveX = (int) event.getRawX();
			int deltaX = tempX - moveX;
			tempX = moveX;
			if (Math.abs(moveX - downX) > mTouchSlop
					&& Math.abs((int) event.getRawY() - downY) < mTouchSlop) {
				isSilding = true;

				// 若touchView是AbsListView,
				// 则当手指滑动,取消item的点击事件,不然我们滑动也伴随着item点击事件的发生
				if (isTouchOnAbsListView()) {
					MotionEvent cancelEvent = MotionEvent.obtain(event);
					cancelEvent
							.setAction(MotionEvent.ACTION_CANCEL
									| (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
					v.onTouchEvent(cancelEvent);
				}

			}

			if (moveX - downX >= 0 && isSilding) {
				mParentView.scrollBy(deltaX, 0);

				// 屏蔽在滑动过程中ListView ScrollView等自己的滑动事件
				if (isTouchOnScrollView() || isTouchOnAbsListView()) {
					return true;
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			isSilding = false;
			if (mParentView.getScrollX() <= -viewWidth / 2) {
				isFinish = true;
				scrollRight();
			} else {
				scrollOrigin();
				isFinish = false;
			}
			break;
		}

		// 假如touch的view是AbsListView或者ScrollView 我们处理完上面自己的逻辑之后
		// 再交给AbsListView, ScrollView自己处理其自己的逻辑
		if (isTouchOnScrollView() || isTouchOnAbsListView()) {
			return v.onTouchEvent(event);
		}

		// 其他的情况直接返回true
		return true;
	}

	@Override
	public void computeScroll() {
		// 调用startScroll的时候scroller.computeScrollOffset()返回true,
		if (mScroller.computeScrollOffset()) {
			mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
			postInvalidate();

			if (mScroller.isFinished()) {

				if (onSildingFinishListener != null && isFinish) {
					onSildingFinishListener.onSildingFinish();
				}
			}
		}
	}
	

	public interface OnSildingFinishListener {
		public void onSildingFinish();
	}

}

我们在onLayout()方法中利用getParent()方法获取该布局的父布局和获取其控件的宽度,主要是为之后的实现做准备工作。

我们的滑动逻辑主要是利用View的scrollBy() 方法, scrollTo()方法和Scroller类来实现的,当手指拖动视图的时候,我们监听手指在屏幕上滑动的距离利用View的scrollBy() 方法使得View随着手指的滑动而滑动,而当手指离开屏幕,我们在根据逻辑使用Scroller类startScroll()方法设置滑动的参数,然后再根据View的scrollTo进行滚动。

对于View的滑动,存在一些Touch事件消费的处理等问题,因此我们需要对View的整个Touch事件很熟悉 ,最主要的就是Activity里面有一些ListView、 GridView、ScrollView等控件了, 假如我们Activity里面存在ListView、GridView等控件的话,我们对Activity的最外层布局进行滚动根本就无效果,因为Touch事件被ListView、GridView等控件消费了,所以Activity的最外层布局根本得不到Touch事件,也就实现不了Touch逻辑了,所以为了解决此Touch事件问题我提供了setTouchView(View touchView) 方法,这个方法是将Touch事件动态的设置到到View上面,所以针对上面的问题,我们将OnTouchListener直接设置到ListView、GridView上面,这样子就避免了Activity的最外层接受不到Touch事件的问题了


接下来看onTouch()方法

首先我们在ACTION_DOWN记录按下点的X,Y坐标

然后在ACTION_MOVE中判断,如果我们在水平方向滑动的距离大于mTouchSlop并且在竖直方向滑动的距离小于mTouchSlop,表示Activity处于滑动状态,我们判断如果touchView是ListView、GridView或者其子类的时候,因为我们手指在ListView、GridView上面,伴随着item的点击事件的发生,所以我们对touchView设置ACTION_CANCEL来取消item的点击事件,然后对该布局的父布局调用scrollBy()进行滚动,并且如果TouchView是AbsListView或者ScrollView直接返回true,来取消AbsListView或者ScrollView本身的ACTION_MOVE事件,最直观的感受就是我们在滑动Activity的时候,禁止AbsListView或者ScrollView的上下滑动

最后在ACTION_UP中判断如果手指滑动的距离大于控件长度的二分之一,表示将Activity滑出界面,否则滑动到起始位置,我们利用Scroller类的startScroll()方法设置好开始位置,滑动距离和时间,然后调用postInvalidate()刷新界面,之后就到computeScroll()方法中,我们利用scrollTo()方法对该布局的父布局进行滚动,滚动结束之后,我们判断界面是否滑出界面,如果是就调用OnSildingFinishListener接口的onSildingFinish()方法,所以只要在onSildingFinish()方法中finish界面就行了

整个滑动布局的代码就是这个样子,接下来我们就来使用了,主界面Activity只有三个按钮,分别跳转到普通布局的Activity,有ListView的Activity和有ScrollView的Activity中

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.     xmlns:tools="http://schemas.android.com/tools" 
  3.     android:layout_width="match_parent" 
  4.     android:layout_height="match_parent" 
  5.     android:gravity="center" 
  6.     android:orientation="vertical" > 
  7.  
  8.     <Button 
  9.         android:id="@+id/normal_activity" 
  10.         android:layout_width="match_parent" 
  11.         android:layout_height="wrap_content" 
  12.         android:text="普通的Activity" /> 
  13.  
  14.     <Button 
  15.         android:id="@+id/absListview_activity" 
  16.         android:layout_width="match_parent" 
  17.         android:layout_height="wrap_content" 
  18.         android:text="有AbsListView的Activity" /> 
  19.  
  20.     <Button 
  21.         android:id="@+id/scrollview_activity" 
  22.         android:layout_width="match_parent" 
  23.         android:layout_height="wrap_content" 
  24.         android:text="有ScrollView的Activity" /> 
  25.  
  26. </LinearLayout> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <Button
        android:id="@+id/normal_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="普通的Activity" />

    <Button
        android:id="@+id/absListview_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="有AbsListView的Activity" />

    <Button
        android:id="@+id/scrollview_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="有ScrollView的Activity" />

</LinearLayout>

然后就是MainActivity的代码,根据ID实例化Button,然后为Button设置OnClickListener事件,不同的按钮跳转到不同的Activity,然后设置从右向左滑动的动画,重写onBackPressed()方法,当我们按下手机物理键盘的返回键,添加从左向右滑出的动画

  1. package com.example.slidingfinish; 
  2.  
  3. import android.app.Activity; 
  4. import android.content.Intent; 
  5. import android.os.Bundle; 
  6. import android.view.View; 
  7. import android.view.View.OnClickListener; 
  8. import android.view.Window; 
  9. import android.widget.Button; 
  10.  
  11. import com.example.slidingfinish.R; 
  12.  
  13. public class MainActivity extends Activity implements OnClickListener { 
  14.  
  15.     @Override 
  16.     protected void onCreate(Bundle savedInstanceState) { 
  17.         requestWindowFeature(Window.FEATURE_NO_TITLE); 
  18.         super.onCreate(savedInstanceState); 
  19.         setContentView(R.layout.activity_main); 
  20.  
  21.         Button mButtonNormal = (Button) findViewById(R.id.normal_activity); 
  22.         mButtonNormal.setOnClickListener(this); 
  23.  
  24.         Button mButtonAbs = (Button) findViewById(R.id.absListview_activity); 
  25.         mButtonAbs.setOnClickListener(this); 
  26.  
  27.         Button mButtonScroll = (Button) findViewById(R.id.scrollview_activity); 
  28.         mButtonScroll.setOnClickListener(this); 
  29.  
  30.     } 
  31.  
  32.     @Override 
  33.     public void onClick(View v) { 
  34.         Intent mIntent = null
  35.         switch (v.getId()) { 
  36.         case R.id.normal_activity: 
  37.             mIntent = new Intent(MainActivity.this, NormalActivity.class); 
  38.             break
  39.         case R.id.absListview_activity: 
  40.             mIntent = new Intent(MainActivity.this, AbsActivity.class); 
  41.             break
  42.         case R.id.scrollview_activity: 
  43.             mIntent = new Intent(MainActivity.this, ScrollActivity.class); 
  44.             break
  45.         } 
  46.  
  47.         startActivity(mIntent); 
  48.         overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain); 
  49.     } 
  50.      
  51.     //Press the back button in mobile phone 
  52.     @Override 
  53.     public void onBackPressed() { 
  54.         super.onBackPressed(); 
  55.         overridePendingTransition(0, R.anim.base_slide_right_out); 
  56.     } 
  57.  
package com.example.slidingfinish;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;

import com.example.slidingfinish.R;

public class MainActivity extends Activity implements OnClickListener {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		Button mButtonNormal = (Button) findViewById(R.id.normal_activity);
		mButtonNormal.setOnClickListener(this);

		Button mButtonAbs = (Button) findViewById(R.id.absListview_activity);
		mButtonAbs.setOnClickListener(this);

		Button mButtonScroll = (Button) findViewById(R.id.scrollview_activity);
		mButtonScroll.setOnClickListener(this);

	}

	@Override
	public void onClick(View v) {
		Intent mIntent = null;
		switch (v.getId()) {
		case R.id.normal_activity:
			mIntent = new Intent(MainActivity.this, NormalActivity.class);
			break;
		case R.id.absListview_activity:
			mIntent = new Intent(MainActivity.this, AbsActivity.class);
			break;
		case R.id.scrollview_activity:
			mIntent = new Intent(MainActivity.this, ScrollActivity.class);
			break;
		}

		startActivity(mIntent);
		overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain);
	}
	
	//Press the back button in mobile phone
	@Override
	public void onBackPressed() {
		super.onBackPressed();
		overridePendingTransition(0, R.anim.base_slide_right_out);
	}

}
在这里我之贴出含有ListView的Activity的代码,先看布局,我们自定义滑动布局SildingFinishLayout应该放在XML的最顶层

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <com.example.view.SildingFinishLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     xmlns:tools="http://schemas.android.com/tools" 
  4.     android:id="@+id/sildingFinishLayout" 
  5.     android:layout_width="match_parent" 
  6.     android:layout_height="match_parent" 
  7.     android:background="#556677"
  8.  
  9.     <ListView 
  10.         android:id="@+id/listView" 
  11.         android:cacheColorHint="@android:color/transparent" 
  12.         android:layout_width="match_parent" 
  13.         android:layout_height="match_parent"
  14.     </ListView> 
  15.      
  16.      
  17. </com.example.view.SildingFinishLayout> 
<?xml version="1.0" encoding="UTF-8"?>
<com.example.view.SildingFinishLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/sildingFinishLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#556677" >

    <ListView
        android:id="@+id/listView"
        android:cacheColorHint="@android:color/transparent"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>
    
    
</com.example.view.SildingFinishLayout>


  1. package com.example.slidingfinish; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.List; 
  5.  
  6. import android.app.Activity; 
  7. import android.content.Intent; 
  8. import android.os.Bundle; 
  9. import android.view.View; 
  10. import android.view.Window; 
  11. import android.widget.AdapterView; 
  12. import android.widget.AdapterView.OnItemClickListener; 
  13. import android.widget.ArrayAdapter; 
  14. import android.widget.ListView; 
  15.  
  16. import com.example.slidingfinish.R; 
  17. import com.example.view.SildingFinishLayout; 
  18. import com.example.view.SildingFinishLayout.OnSildingFinishListener; 
  19.  
  20. public class AbsActivity extends Activity { 
  21.     private List<String> list = new ArrayList<String>(); 
  22.  
  23.     @Override 
  24.     protected void onCreate(Bundle savedInstanceState) { 
  25.         requestWindowFeature(Window.FEATURE_NO_TITLE); 
  26.         super.onCreate(savedInstanceState); 
  27.         setContentView(R.layout.activity_abslistview); 
  28.  
  29.         for (int i = 0; i <= 30; i++) { 
  30.             list.add("测试数据" + i); 
  31.         } 
  32.  
  33.         ListView mListView = (ListView) findViewById(R.id.listView); 
  34.         ArrayAdapter<String> adapter = new ArrayAdapter<String>( 
  35.                 AbsActivity.this, android.R.layout.simple_list_item_1, list); 
  36.         mListView.setAdapter(adapter); 
  37.  
  38.         SildingFinishLayout mSildingFinishLayout = (SildingFinishLayout) findViewById(R.id.sildingFinishLayout); 
  39.         mSildingFinishLayout 
  40.                 .setOnSildingFinishListener(new OnSildingFinishListener() { 
  41.  
  42.                     @Override 
  43.                     public void onSildingFinish() { 
  44.                         AbsActivity.this.finish(); 
  45.                     } 
  46.                 }); 
  47.  
  48.         // touchView要设置到ListView上面 
  49.         mSildingFinishLayout.setTouchView(mListView); 
  50.  
  51.         mListView.setOnItemClickListener(new OnItemClickListener() { 
  52.  
  53.             @Override 
  54.             public void onItemClick(AdapterView<?> parent, View view, 
  55.                     int position, long id) { 
  56.  
  57.                 startActivity(new Intent(AbsActivity.this, NormalActivity.class)); 
  58.                 overridePendingTransition(R.anim.base_slide_right_in, 
  59.                         R.anim.base_slide_remain); 
  60.             } 
  61.         }); 
  62.     } 
  63.  
  64.     // Press the back button in mobile phone 
  65.     @Override 
  66.     public void onBackPressed() { 
  67.         super.onBackPressed(); 
  68.         overridePendingTransition(0, R.anim.base_slide_right_out); 
  69.     } 
  70.  
package com.example.slidingfinish;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.example.slidingfinish.R;
import com.example.view.SildingFinishLayout;
import com.example.view.SildingFinishLayout.OnSildingFinishListener;

public class AbsActivity extends Activity {
	private List<String> list = new ArrayList<String>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_abslistview);

		for (int i = 0; i <= 30; i++) {
			list.add("测试数据" + i);
		}

		ListView mListView = (ListView) findViewById(R.id.listView);
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(
				AbsActivity.this, android.R.layout.simple_list_item_1, list);
		mListView.setAdapter(adapter);

		SildingFinishLayout mSildingFinishLayout = (SildingFinishLayout) findViewById(R.id.sildingFinishLayout);
		mSildingFinishLayout
				.setOnSildingFinishListener(new OnSildingFinishListener() {

					@Override
					public void onSildingFinish() {
						AbsActivity.this.finish();
					}
				});

		// touchView要设置到ListView上面
		mSildingFinishLayout.setTouchView(mListView);

		mListView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {

				startActivity(new Intent(AbsActivity.this, NormalActivity.class));
				overridePendingTransition(R.anim.base_slide_right_in,
						R.anim.base_slide_remain);
			}
		});
	}

	// Press the back button in mobile phone
	@Override
	public void onBackPressed() {
		super.onBackPressed();
		overridePendingTransition(0, R.anim.base_slide_right_out);
	}

}
利用ID找到SildingFinishLayout实例,利用setTouchView()方法设置touchView到ListView上面,然后调用setOnSildingFinishListener()设置OnSildingFinishListener,在onSildingFinish()中finish界面就可以啦。

在运行项目之前还有一个很重要的操作,也是之前我被卡到的问题,就是我们需要对Activity设置为透明,即设置主题android:theme="@android:style/Theme.Translucent"

  1. <activity 
  2.            android:name=".AbsActivity" 
  3.            android:theme="@android:style/Theme.Translucent" > 
  4.        </activity> 
  5.        <activity 
  6.            android:name=".NormalActivity" 
  7.            android:theme="@android:style/Theme.Translucent" > 
  8.        </activity> 
  9.        <activity 
  10.            android:name=".ScrollActivity" 
  11.            android:theme="@android:style/Theme.Translucent" > 
  12.        </activity> 
 <activity
            android:name=".AbsActivity"
            android:theme="@android:style/Theme.Translucent" >
        </activity>
        <activity
            android:name=".NormalActivity"
            android:theme="@android:style/Theme.Translucent" >
        </activity>
        <activity
            android:name=".ScrollActivity"
            android:theme="@android:style/Theme.Translucent" >
        </activity>
好了,现在我们可以运行项目看看效果啦

tail/xiaanming/7026873



正是我们想要的效果,如果想要加入滑动切换界面的效果只需要三步就行了,首先将Activity布局的最外层修改为SildingFinishLayout,然后在Activity里面调用setTouchView()方法设置touchView,设置OnSildingFinishListener监听在onSildingFinish()方法中finish界面,最后设置Activity的背景为透明(不是设置Activity布局文件的最顶层布局背景颜色透明,这点要区分一下)是不是很方便呢?好了,今天的讲解到这里就结束了,有疑问的朋友请在下面留言,有兴趣的朋友可以下载源码看看!

项目源码,点击下载

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值