Android從上往下滑動或從下往上滑動結束Activity
阿新 • • 發佈:2019-02-01
之前有看過xiaanming寫的側滑返回,於是仿照他的Demo,寫了這個從上往下滑動或者從下往上滑動結束Activity
先附圖一張,由於這臺電腦解析度有問題以及模擬器的緣故,先湊活看吧
先貼程式碼:
從上往下滑動:
import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.RelativeLayout; import android.widget.Scroller; /*** * * 從上向下滑結束Activity * * @author 帽檐遮不住陽光 * */ public class TopToBottomFinishLayout extends RelativeLayout { /** * TopToBottomFinishLayout佈局的父佈局 */ private ViewGroup mParentView; /** * 滑動的最小距離 */ private int mTouchSlop; /** * 按下點的X座標 */ private int downX; /** * 按下點的Y座標 */ private int downY; /** * 臨時儲存X座標 */ private int tempY; /** * 滑動類 */ private Scroller mScroller; /** * TopToBottomFinishLayout的寬度 */ private int viewHeight; private boolean isSilding; private OnFinishListener onFinishListener; private boolean isFinish; public TopToBottomFinishLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TopToBottomFinishLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mScroller = new Scroller(context); } /** * 事件攔截操作 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downX = (int) ev.getRawX(); downY = tempY = (int) ev.getRawY(); break; case MotionEvent.ACTION_MOVE: int moveY = (int) ev.getRawY(); // 滿足此條件遮蔽SildingFinishLayout裡面子類的touch事件 if (Math.abs(moveY - downY) > mTouchSlop && Math.abs((int) ev.getRawX() - downX) < mTouchSlop) { return true; } break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: int moveY = (int) event.getRawY();// 觸控點相對於螢幕的位置 int deltaY = tempY - moveY; tempY = moveY; if (Math.abs(moveY - downY) > mTouchSlop && Math.abs((int) event.getRawX() - downX) < mTouchSlop) { isSilding = true; } if (moveY - downY >= 0 && isSilding) { mParentView.scrollBy(0, deltaY); } break; case MotionEvent.ACTION_UP: isSilding = false; if (mParentView.getScrollY() <= -viewHeight / 3) { isFinish = true; scrollBottom(); } else { scrollOrigin(); isFinish = false; } break; } return true; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { mParentView = (ViewGroup) this.getParent(); viewHeight = this.getHeight(); } } /*** * 介面回撥 */ public void setOnFinishListener( OnFinishListener onSildingFinishListener) { this.onFinishListener = onSildingFinishListener; } /** * 滾動出界面 */ private void scrollBottom() { final int delta = (viewHeight + mParentView.getScrollY()); mScroller.startScroll(0, mParentView.getScrollY(), 0, -delta + 1, Math.abs(delta)); postInvalidate(); } /** * 滾動到起始位置 */ private void scrollOrigin() { int delta = mParentView.getScrollY(); mScroller.startScroll(0, mParentView.getScrollY(), 0, -delta, Math.abs(delta)); postInvalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); if (mScroller.isFinished() && isFinish) { if (onFinishListener != null) { onFinishListener.onFinish(); } else { // 沒有設定OnSildingFinishListener,讓其滾動到其實位置 scrollOrigin(); isFinish = false; } } } } public interface OnFinishListener { public void onFinish(); } }
從下往上滑動:
Activity:import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.RelativeLayout; import android.widget.Scroller; /*** * * 從下向上滑結束Activity * * @author 帽檐遮不住陽光 * */ public class BottomToTopFinishLayout extends RelativeLayout { /** * BottomFinishLayout佈局的父佈局 */ private ViewGroup mParentView; /** * 滑動的最小距離 */ private int mTouchSlop; /** * 按下點的X座標 */ private int downX; /** * 按下點的Y座標 */ private int downY; /** * 臨時儲存X座標 */ private int tempY; /** * 滑動類 */ private Scroller mScroller; /** * BottomFinishLayout的寬度 */ private int viewHeight; private boolean isSilding; private OnFinishListener onFinishListener; private boolean isFinish; public BottomToTopFinishLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BottomToTopFinishLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mScroller = new Scroller(context); } /** * 事件攔截操作 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downX = (int) ev.getRawX(); downY = tempY = (int) ev.getRawY(); break; case MotionEvent.ACTION_MOVE: int moveY = (int) ev.getRawY(); // 滿足此條件遮蔽SildingFinishLayout裡面子類的touch事件 if (Math.abs(downY - moveY) > mTouchSlop && Math.abs((int) ev.getRawX() - downX) < mTouchSlop) { return true; } break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: int moveY = (int) event.getRawY();// 觸控點相對於螢幕的位置 int deltaY = moveY - tempY; tempY = moveY; if (Math.abs(downY - moveY) > mTouchSlop && Math.abs((int) event.getRawX() - downX) < mTouchSlop) { isSilding = true; } if (downY - moveY >= 0 && isSilding) { mParentView.scrollBy(0, -deltaY); } break; case MotionEvent.ACTION_UP: isSilding = false; System.out.println("vvv===========" + mParentView.getScrollY()); System.out.println("/3============" + viewHeight / 3); if (mParentView.getScrollY() >= viewHeight / 3) { isFinish = true; scrollTop(); } else { scrollOrigin(); isFinish = false; } break; } return true; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { mParentView = (ViewGroup) this.getParent(); viewHeight = this.getHeight(); } } /*** * 介面回撥 */ public void setOnFinishListener(OnFinishListener onSildingFinishListener) { this.onFinishListener = onSildingFinishListener; } /** * 滾動出界面 */ private void scrollTop() { final int delta = (viewHeight - mParentView.getScrollY()); mScroller.startScroll(0, mParentView.getScrollY(), 0, delta - 1, Math.abs(delta)); postInvalidate(); } /** * 滾動到起始位置 */ private void scrollOrigin() { int delta = mParentView.getScrollY(); mScroller.startScroll(0, mParentView.getScrollY(), 0, -delta, Math.abs(delta)); postInvalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); if (mScroller.isFinished() && isFinish) { if (onFinishListener != null) { onFinishListener.onFinish(); } else { // 沒有設定OnSildingFinishListener,讓其滾動到其實位置 scrollOrigin(); isFinish = false; } } } } public interface OnFinishListener { public void onFinish(); } }
public class FromTopActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_from_top); TopToBottomFinishLayout bottomFinishLayout = (TopToBottomFinishLayout) findViewById(R.id.layout); bottomFinishLayout.setOnFinishListener(new OnFinishListener() { @Override public void onFinish() { finish(); } }); } }
layout:
<?xml version="1.0" encoding="utf-8"?>
<com.example.mytest.TopToBottomFinishLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#5DC890"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="TestActivity"
android:textColor="#ff8840" />
</com.example.mytest.TopToBottomFinishLayout>
要實現其實很簡單,在onTouchEvent裡判斷手指移動的距離,如果大於自己設定的臨界值,則滾動到頂部或者底部,否則回到初始位置。所以這裡用到了Scroller,scroller.startScroll後,postInvalidate重新整理介面。
最後重寫computeScroll,在computeScroll裡判斷Scroller是否已經finish以及手指移動的距離是否大於自己設定的臨界值。
最後一定要記得,在AndroidManifest.xml裡要將Activity的Theme設定為Theme.Translucent,否則看不到效果
Demo:http://download.csdn.net/detail/qq_18612815/9615890