转载(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布局文件

**[html]** [view plain](http://blog.csdn.net/xiaanming/article/details/20934541#)[copy](http://blog.csdn.net/xiaanming/article/details/20934541#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/232806)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/232806/fork)
  <div>
    <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1">
    </embed>
  </div>
</div>
- <span class="tag"><</span><span class="tag-name">LinearLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span>

- <span class="attribute">xmlns:tools</span>=<span class="attribute-value">&#8220;http://schemas.android.com/tools&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span>

- <span class="attribute">android:gravity</span>=<span class="attribute-value">&#8220;center&#8221;</span>

- <span class="attribute">android:orientation</span>=<span class="attribute-value">&#8220;vertical&#8221;</span> <span class="tag">></span>

- 
- 
- <span class="tag"></</span><span class="tag-name">LinearLayout</span><span class="tag">></span>

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

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

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

**[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/20934541#)[copy](http://blog.csdn.net/xiaanming/article/details/20934541#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/232806)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/232806/fork)
  <div>
    <embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2">
    </embed>
  </div>
</div>
- <span class="keyword">package</span> com.example.view;

- 
- <span class="keyword">import</span> android.content.Context;

- <span class="keyword">import</span> android.util.AttributeSet;

- <span class="keyword">import</span> android.view.MotionEvent;

- <span class="keyword">import</span> android.view.View;

- <span class="keyword">import</span> android.view.View.OnTouchListener;

- <span class="keyword">import</span> android.view.ViewConfiguration;

- <span class="keyword">import</span> android.view.ViewGroup;

- <span class="keyword">import</span> android.widget.AbsListView;

- <span class="keyword">import</span> android.widget.RelativeLayout;

- <span class="keyword">import</span> android.widget.ScrollView;

- <span class="keyword">import</span> android.widget.Scroller;

- 
- <span class="comment">/**</span>

- <span class="comment"> * 自定义可以滑动的RelativeLayout, 类似于IOS的滑动删除页面效果,当我们要使用</span>

- <span class="comment"> * 此功能的时候,需要将该Activity的顶层布局设置为SildingFinishLayout,</span>

- <span class="comment"> * 然后需要调用setTouchView()方法来设置需要滑动的View</span>

- <span class="comment"> * </span>

- <span class="comment"> * @author xiaanming</span>

- <span class="comment"> * </span>

- <span class="comment"> * @blog http://blog.csdn.net/xiaanming</span>

- <span class="comment"> * </span>

- <span class="comment"> */</span>

- <span class="keyword">public</span> <span class="keyword">class</span> SildingFinishLayout <span class="keyword">extends</span> RelativeLayout <span class="keyword">implements</span>

- OnTouchListener {

- <span class="comment">/**</span>

- <span class="comment">     * SildingFinishLayout布局的父布局</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> ViewGroup mParentView;

- <span class="comment">/**</span>

- <span class="comment">     * 处理滑动逻辑的View</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> View touchView;

- <span class="comment">/**</span>

- <span class="comment">     * 滑动的最小距离</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">int</span> mTouchSlop;

- <span class="comment">/**</span>

- <span class="comment">     * 按下点的X坐标</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">int</span> downX;

- <span class="comment">/**</span>

- <span class="comment">     * 按下点的Y坐标</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">int</span> downY;

- <span class="comment">/**</span>

- <span class="comment">     * 临时存储X坐标</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">int</span> tempX;

- <span class="comment">/**</span>

- <span class="comment">     * 滑动类</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> Scroller mScroller;

- <span class="comment">/**</span>

- <span class="comment">     * SildingFinishLayout的宽度</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">int</span> viewWidth;

- <span class="comment">/**</span>

- <span class="comment">     * 记录是否正在滑动</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">boolean</span> isSilding;

- 
- <span class="keyword">private</span> OnSildingFinishListener onSildingFinishListener;

- <span class="keyword">private</span> <span class="keyword">boolean</span> isFinish;

- 
- 
- <span class="keyword">public</span> SildingFinishLayout(Context context, AttributeSet attrs) {

- <span class="keyword">this</span>(context, attrs, <span class="number"></span>);

- }

- 
- <span class="keyword">public</span> SildingFinishLayout(Context context, AttributeSet attrs, <span class="keyword">int</span> defStyle) {

- <span class="keyword">super</span>(context, attrs, defStyle);

- 
- mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

- mScroller = <span class="keyword">new</span> Scroller(context);

- }

- 
- <span class="annotation">@Override</span>

- <span class="keyword">protected</span> <span class="keyword">void</span> onLayout(<span class="keyword">boolean</span> changed, <span class="keyword">int</span> l, <span class="keyword">int</span> t, <span class="keyword">int</span> r, <span class="keyword">int</span> b) {

- <span class="keyword">super</span>.onLayout(changed, l, t, r, b);

- <span class="keyword">if</span> (changed) {

- <span class="comment">// 获取SildingFinishLayout所在布局的父布局</span>

- mParentView = (ViewGroup) <span class="keyword">this</span>.getParent();

- viewWidth = <span class="keyword">this</span>.getWidth();

- }

- }

- 
- <span class="comment">/**</span>

- <span class="comment">     * 设置OnSildingFinishListener, 在onSildingFinish()方法中finish Activity</span>

- <span class="comment">     * </span>

- <span class="comment">     * @param onSildingFinishListener</span>

- <span class="comment">     */</span>

- <span class="keyword">public</span> <span class="keyword">void</span> setOnSildingFinishListener(

- OnSildingFinishListener onSildingFinishListener) {

- <span class="keyword">this</span>.onSildingFinishListener = onSildingFinishListener;

- }

- 
- <span class="comment">/**</span>

- <span class="comment">     * 设置Touch的View</span>

- <span class="comment">     * </span>

- <span class="comment">     * @param touchView</span>

- <span class="comment">     */</span>

- <span class="keyword">public</span> <span class="keyword">void</span> setTouchView(View touchView) {

- <span class="keyword">this</span>.touchView = touchView;

- touchView.setOnTouchListener(<span class="keyword">this</span>);

- }

- 
- <span class="keyword">public</span> View getTouchView() {

- <span class="keyword">return</span> touchView;

- }

- 
- <span class="comment">/**</span>

- <span class="comment">     * 滚动出界面</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">void</span> scrollRight() {

- <span class="keyword">final</span> <span class="keyword">int</span> delta = (viewWidth + mParentView.getScrollX());

- <span class="comment">// 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item</span>

- mScroller.startScroll(mParentView.getScrollX(), <span class="number"></span>, -delta + <span class="number">1</span>, <span class="number"></span>,

- Math.abs(delta));

- postInvalidate();

- }

- 
- <span class="comment">/**</span>

- <span class="comment">     * 滚动到起始位置</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">void</span> scrollOrigin() {

- <span class="keyword">int</span> delta = mParentView.getScrollX();

- mScroller.startScroll(mParentView.getScrollX(), <span class="number"></span>, -delta, <span class="number"></span>,

- Math.abs(delta));

- postInvalidate();

- }

- 
- <span class="comment">/**</span>

- <span class="comment">     * touch的View是否是AbsListView, 例如ListView, GridView等其子类</span>

- <span class="comment">     * </span>

- <span class="comment">     * @return</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">boolean</span> isTouchOnAbsListView() {

- <span class="keyword">return</span> touchView <span class="keyword">instanceof</span> AbsListView ? <span class="keyword">true</span> : <span class="keyword">false</span>;

- }

- 
- <span class="comment">/**</span>

- <span class="comment">     * touch的view是否是ScrollView或者其子类</span>

- <span class="comment">     * </span>

- <span class="comment">     * @return</span>

- <span class="comment">     */</span>

- <span class="keyword">private</span> <span class="keyword">boolean</span> isTouchOnScrollView() {

- <span class="keyword">return</span> touchView <span class="keyword">instanceof</span> ScrollView ? <span class="keyword">true</span> : <span class="keyword">false</span>;

- }

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">boolean</span> onTouch(View v, MotionEvent event) {

- <span class="keyword">switch</span> (event.getAction()) {

- <span class="keyword">case</span> MotionEvent.ACTION_DOWN:

- downX = tempX = (<span class="keyword">int</span>) event.getRawX();

- downY = (<span class="keyword">int</span>) event.getRawY();

- <span class="keyword">break</span>;

- <span class="keyword">case</span> MotionEvent.ACTION_MOVE:

- <span class="keyword">int</span> moveX = (<span class="keyword">int</span>) event.getRawX();

- <span class="keyword">int</span> deltaX = tempX &#8211; moveX;

- tempX = moveX;

- <span class="keyword">if</span> (Math.abs(moveX &#8211; downX) > mTouchSlop

- && Math.abs((<span class="keyword">int</span>) event.getRawY() &#8211; downY) < mTouchSlop) {

- isSilding = <span class="keyword">true</span>;

- 
- <span class="comment">// 若touchView是AbsListView,</span>

- <span class="comment">// 则当手指滑动,取消item的点击事件,不然我们滑动也伴随着item点击事件的发生</span>

- <span class="keyword">if</span> (isTouchOnAbsListView()) {

- MotionEvent cancelEvent = MotionEvent.obtain(event);

- cancelEvent

- .setAction(MotionEvent.ACTION_CANCEL

- | (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));

- v.onTouchEvent(cancelEvent);

- }

- 
- }

- 
- <span class="keyword">if</span> (moveX &#8211; downX >= <span class="number"></span> && isSilding) {

- mParentView.scrollBy(deltaX, <span class="number"></span>);

- 
- <span class="comment">// 屏蔽在滑动过程中ListView ScrollView等自己的滑动事件</span>

- <span class="keyword">if</span> (isTouchOnScrollView() || isTouchOnAbsListView()) {

- <span class="keyword">return</span> <span class="keyword">true</span>;

- }

- }

- <span class="keyword">break</span>;

- <span class="keyword">case</span> MotionEvent.ACTION_UP:

- isSilding = <span class="keyword">false</span>;

- <span class="keyword">if</span> (mParentView.getScrollX() <= -viewWidth / <span class="number">2</span>) {

- isFinish = <span class="keyword">true</span>;

- scrollRight();

- } <span class="keyword">else</span> {

- scrollOrigin();

- isFinish = <span class="keyword">false</span>;

- }

- <span class="keyword">break</span>;

- }

- 
- <span class="comment">// 假如touch的view是AbsListView或者ScrollView 我们处理完上面自己的逻辑之后</span>

- <span class="comment">// 再交给AbsListView, ScrollView自己处理其自己的逻辑</span>

- <span class="keyword">if</span> (isTouchOnScrollView() || isTouchOnAbsListView()) {

- <span class="keyword">return</span> v.onTouchEvent(event);

- }

- 
- <span class="comment">// 其他的情况直接返回true</span>

- <span class="keyword">return</span> <span class="keyword">true</span>;

- }

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> computeScroll() {

- <span class="comment">// 调用startScroll的时候scroller.computeScrollOffset()返回true,</span>

- <span class="keyword">if</span> (mScroller.computeScrollOffset()) {

- mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

- postInvalidate();

- 
- <span class="keyword">if</span> (mScroller.isFinished()) {

- 
- <span class="keyword">if</span> (onSildingFinishListener != <span class="keyword">null</span> && isFinish) {

- onSildingFinishListener.onSildingFinish();

- }

- }

- }

- }

- 
- 
- <span class="keyword">public</span> <span class="keyword">interface</span> OnSildingFinishListener {

- <span class="keyword">public</span> <span class="keyword">void</span> 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中

**[html]** [view plain](http://blog.csdn.net/xiaanming/article/details/20934541#)[copy](http://blog.csdn.net/xiaanming/article/details/20934541#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/232806)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/232806/fork)
  <div>
    <embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_3">
    </embed>
  </div>
</div>
- <span class="tag"><</span><span class="tag-name">LinearLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span>

- <span class="attribute">xmlns:tools</span>=<span class="attribute-value">&#8220;http://schemas.android.com/tools&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span>

- <span class="attribute">android:gravity</span>=<span class="attribute-value">&#8220;center&#8221;</span>

- <span class="attribute">android:orientation</span>=<span class="attribute-value">&#8220;vertical&#8221;</span> <span class="tag">></span>

- 
- <span class="tag"><</span><span class="tag-name">Button</span>

- <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/normal_activity&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span>

- <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;普通的Activity&#8221;</span> <span class="tag">/></span>

- 
- <span class="tag"><</span><span class="tag-name">Button</span>

- <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/absListview_activity&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span>

- <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;有AbsListView的Activity&#8221;</span> <span class="tag">/></span>

- 
- <span class="tag"><</span><span class="tag-name">Button</span>

- <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/scrollview_activity&#8221;</span>

- <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span>

- <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span>

- <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;有ScrollView的Activity&#8221;</span> <span class="tag">/></span>

- 
- <span class="tag"></</span><span class="tag-name">LinearLayout</span><span class="tag">></span>

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

**[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/20934541#)[copy](http://blog.csdn.net/xiaanming/article/details/20934541#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/232806)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/232806/fork)
  <div>
    <embed id="ZeroClipboardMovie_4" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_4">
    </embed>
  </div>
</div>
- <span class="keyword">package</span> com.example.slidingfinish;

- 
- <span class="keyword">import</span> android.app.Activity;

- <span class="keyword">import</span> android.content.Intent;

- <span class="keyword">import</span> android.os.Bundle;

- <span class="keyword">import</span> android.view.View;

- <span class="keyword">import</span> android.view.View.OnClickListener;

- <span class="keyword">import</span> android.view.Window;

- <span class="keyword">import</span> android.widget.Button;

- 
- <span class="keyword">import</span> com.example.slidingfinish.R;

- 
- <span class="keyword">public</span> <span class="keyword">class</span> MainActivity <span class="keyword">extends</span> Activity <span class="keyword">implements</span> OnClickListener {

- 
- <span class="annotation">@Override</span>

- <span class="keyword">protected</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) {

- requestWindowFeature(Window.FEATURE_NO_TITLE);

- <span class="keyword">super</span>.onCreate(savedInstanceState);

- setContentView(R.layout.activity_main);

- 
- Button mButtonNormal = (Button) findViewById(R.id.normal_activity);

- mButtonNormal.setOnClickListener(<span class="keyword">this</span>);

- 
- Button mButtonAbs = (Button) findViewById(R.id.absListview_activity);

- mButtonAbs.setOnClickListener(<span class="keyword">this</span>);

- 
- Button mButtonScroll = (Button) findViewById(R.id.scrollview_activity);

- mButtonScroll.setOnClickListener(<span class="keyword">this</span>);

- 
- }

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) {

- Intent mIntent = <span class="keyword">null</span>;

- <span class="keyword">switch</span> (v.getId()) {

- <span class="keyword">case</span> R.id.normal_activity:

- mIntent = <span class="keyword">new</span> Intent(MainActivity.<span class="keyword">this</span>, NormalActivity.<span class="keyword">class</span>);

- <span class="keyword">break</span>;

- <span class="keyword">case</span> R.id.absListview_activity:

- mIntent = <span class="keyword">new</span> Intent(MainActivity.<span class="keyword">this</span>, AbsActivity.<span class="keyword">class</span>);

- <span class="keyword">break</span>;

- <span class="keyword">case</span> R.id.scrollview_activity:

- mIntent = <span class="keyword">new</span> Intent(MainActivity.<span class="keyword">this</span>, ScrollActivity.<span class="keyword">class</span>);

- <span class="keyword">break</span>;

- }

- 
- startActivity(mIntent);

- overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain);

- }

- 
- <span class="comment">//Press the back button in mobile phone</span>

- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onBackPressed() {

- <span class="keyword">super</span>.onBackPressed();

- overridePendingTransition(<span class="number"></span>, R.anim.base_slide_right_out);

- }

- 
- }

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

**[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/20934541#)[copy](http://blog.csdn.net/xiaanming/article/details/20934541#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/232806)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/232806/fork)
  <div>
    <embed id="ZeroClipboardMovie_5" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_5">
    </embed>
  </div>
</div>
- <?xml version=<span class="string">&#8220;1.0&#8221;</span> encoding=<span class="string">&#8220;UTF-8&#8221;</span>?>

- <com.example.view.SildingFinishLayout xmlns:android=<span class="string">&#8220;http://schemas.android.com/apk/res/android&#8221;</span>

- xmlns:tools=<span class="string">&#8220;http://schemas.android.com/tools&#8221;</span>

- android:id=<span class="string">&#8220;@+id/sildingFinishLayout&#8221;</span>

- android:layout_width=<span class="string">&#8220;match_parent&#8221;</span>

- android:layout_height=<span class="string">&#8220;match_parent&#8221;</span>

- android:background=<span class="string">&#8220;#556677&#8221;</span> >

- 
- <ListView

- android:id=<span class="string">&#8220;@+id/listView&#8221;</span>

- android:cacheColorHint=<span class="string">&#8220;@android:color/transparent&#8221;</span>

- android:layout_width=<span class="string">&#8220;match_parent&#8221;</span>

- android:layout_height=<span class="string">&#8220;match_parent&#8221;</span> >

- </ListView>

- 
- 
- </com.example.view.SildingFinishLayout>
**[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/20934541#)[copy](http://blog.csdn.net/xiaanming/article/details/20934541#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/232806)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/232806/fork)
  <div>
    <embed id="ZeroClipboardMovie_6" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_6">
    </embed>
  </div>
</div>
- <span class="keyword">package</span> com.example.slidingfinish;

- 
- <span class="keyword">import</span> java.util.ArrayList;

- <span class="keyword">import</span> java.util.List;

- 
- <span class="keyword">import</span> android.app.Activity;

- <span class="keyword">import</span> android.content.Intent;

- <span class="keyword">import</span> android.os.Bundle;

- <span class="keyword">import</span> android.view.View;

- <span class="keyword">import</span> android.view.Window;

- <span class="keyword">import</span> android.widget.AdapterView;

- <span class="keyword">import</span> android.widget.AdapterView.OnItemClickListener;

- <span class="keyword">import</span> android.widget.ArrayAdapter;

- <span class="keyword">import</span> android.widget.ListView;

- 
- <span class="keyword">import</span> com.example.slidingfinish.R;

- <span class="keyword">import</span> com.example.view.SildingFinishLayout;

- <span class="keyword">import</span> com.example.view.SildingFinishLayout.OnSildingFinishListener;

- 
- <span class="keyword">public</span> <span class="keyword">class</span> AbsActivity <span class="keyword">extends</span> Activity {

- <span class="keyword">private</span> List<String> list = <span class="keyword">new</span> ArrayList<String>();

- 
- <span class="annotation">@Override</span>

- <span class="keyword">protected</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) {

- requestWindowFeature(Window.FEATURE_NO_TITLE);

- <span class="keyword">super</span>.onCreate(savedInstanceState);

- setContentView(R.layout.activity_abslistview);

- 
- <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number"></span>; i <= <span class="number">30</span>; i++) {

- list.add(<span class="string">&#8220;测试数据&#8221;</span> + i);

- }

- 
- ListView mListView = (ListView) findViewById(R.id.listView);

- ArrayAdapter<String> adapter = <span class="keyword">new</span> ArrayAdapter<String>(

- AbsActivity.<span class="keyword">this</span>, android.R.layout.simple_list_item_1, list);

- mListView.setAdapter(adapter);

- 
- SildingFinishLayout mSildingFinishLayout = (SildingFinishLayout) findViewById(R.id.sildingFinishLayout);

- mSildingFinishLayout

- .setOnSildingFinishListener(<span class="keyword">new</span> OnSildingFinishListener() {

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onSildingFinish() {

- AbsActivity.<span class="keyword">this</span>.finish();

- }

- });

- 
- <span class="comment">// touchView要设置到ListView上面</span>

- mSildingFinishLayout.setTouchView(mListView);

- 
- mListView.setOnItemClickListener(<span class="keyword">new</span> OnItemClickListener() {

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onItemClick(AdapterView<?> parent, View view,

- <span class="keyword">int</span> position, <span class="keyword">long</span> id) {

- 
- startActivity(<span class="keyword">new</span> Intent(AbsActivity.<span class="keyword">this</span>, NormalActivity.<span class="keyword">class</span>));

- overridePendingTransition(R.anim.base_slide_right_in,

- R.anim.base_slide_remain);

- }

- });

- }

- 
- <span class="comment">// Press the back button in mobile phone</span>

- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onBackPressed() {

- <span class="keyword">super</span>.onBackPressed();

- overridePendingTransition(<span class="number"></span>, R.anim.base_slide_right_out);

- }

- 
- }

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

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

**[html]** [view plain](http://blog.csdn.net/xiaanming/article/details/20934541#)[copy](http://blog.csdn.net/xiaanming/article/details/20934541#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/232806)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/232806/fork)
  <div>
    <embed id="ZeroClipboardMovie_7" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_7">
    </embed>
  </div>
</div>
- <span class="tag"><</span><span class="tag-name">activity</span>

- <span class="attribute">android:name</span>=<span class="attribute-value">&#8220;.AbsActivity&#8221;</span>

- <span class="attribute">android:theme</span>=<span class="attribute-value">&#8220;@android:style/Theme.Translucent&#8221;</span> <span class="tag">></span>

- <span class="tag"></</span><span class="tag-name">activity</span><span class="tag">></span>

- <span class="tag"><</span><span class="tag-name">activity</span>

- <span class="attribute">android:name</span>=<span class="attribute-value">&#8220;.NormalActivity&#8221;</span>

- <span class="attribute">android:theme</span>=<span class="attribute-value">&#8220;@android:style/Theme.Translucent&#8221;</span> <span class="tag">></span>

- <span class="tag"></</span><span class="tag-name">activity</span><span class="tag">></span>

- <span class="tag"><</span><span class="tag-name">activity</span>

- <span class="attribute">android:name</span>=<span class="attribute-value">&#8220;.ScrollActivity&#8221;</span>

- <span class="attribute">android:theme</span>=<span class="attribute-value">&#8220;@android:style/Theme.Translucent&#8221;</span> <span class="tag">></span>

- <span class="tag"></</span><span class="tag-name">activity</span><span class="tag">></span>

好了,现在我们可以运行项目看看效果啦

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

项目源码,点击下载

博主后面又改了下代码,写了一个简洁加强版的demo,代码更加简洁了,也对里面是ViewPager做了处理,并且加了边界的阴影效果,也不必要调用setTouchView()来设置那个View响应滚动,对SildingFinishLayout里面的子View是什么没有任何关系,如果大家想使用此效果的话,建议下载如下版本

加强简洁版,点击下载

 

💬 评论