国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android中SwipeBack實現(xiàn)右滑返回效果

2020-04-11 10:52:38
字體:
供稿:網(wǎng)友

現(xiàn)在有很多App支持右滑返回,比如知乎,效果比較贊。

于是自己對Activity和Fragment進行了繼承,派生出SwipeBackActivity和SwipeBackFragment,用于對這種效果的實現(xiàn),也就是只要繼承這兩個類就可以了。

效果如下

  • Activity

Fragment

Frgament的效果實現(xiàn)比Activity稍微簡單,因為Activity要考慮到dectorView。

支持滑動的控件SwipeLayout,核心思路就是把原有的控件添加到支持滑動的控件中,SwipeLayout要注意計算手勢速度,源碼如下:

package com.ui.jerry.swipebackdemo;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewConfiguration;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.Scroller;import android.widget.Toast;public class SwipeLayout extends LinearLayout {  public static final String TAG = "SwipeLayout";  private View mEmptyView;  private View mContentView;  private int mLeftEdge;  private int mWidth;  private int mMaxScrollX;  private Scroller mScroller;  private VelocityTracker mVelocityTracker = null;  private int mMaxFlingVelocity;  private int mLastX;  ViewGroup.LayoutParams childParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);  private Context mContext;  public static final int DURATION = 1500;  //滿屏滑動時間  public static final int OPEN_ANIM_DURATION = 1000;  public static int SNAP_VELOCITY = 600; //最小的滑動速率  private OnFinishListener mOnFinishListener;  public SwipeLayout(Context context) {    this(context, null);  }  public SwipeLayout(Context context, AttributeSet attrs) {    super(context, attrs);    mContext = context;    init();  }  public void setOnFinishListener(OnFinishListener mOnFinishListener) {    this.mOnFinishListener = mOnFinishListener;  }  void init() {    mScroller = new Scroller(mContext);    mMaxFlingVelocity = ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity();    mWidth = DisplayUtils.getScreenWidth(mContext) * 2;    mMaxScrollX = mWidth / 2;    mLeftEdge = mMaxScrollX - mMaxScrollX / 3;    setOrientation(LinearLayout.HORIZONTAL);    childParams.width = DisplayUtils.getScreenWidth(mContext);    mEmptyView = LayoutInflater.from(mContext).inflate(R.layout.view_translate, null);    addView(mEmptyView, childParams);  }  public void setContentView(View contentView) {    if (mContentView != null) {      removeView(mContentView);    }    mContentView = contentView;    addView(contentView, childParams);    postDelayed(new Runnable() {      @Override      public void run() {        openActivityAnimation();      }    }, 200);  }  /**   * 獲取速度追蹤器   *   * @return   */  private VelocityTracker getVelocityTracker() {    if (mVelocityTracker == null) {      mVelocityTracker = VelocityTracker.obtain();    }    return mVelocityTracker;  }  /**   * 回收速度追蹤器   */  private void recycleVelocityTracker() {    if (mVelocityTracker != null) {      mVelocityTracker.clear();      mVelocityTracker.recycle();      mVelocityTracker = null;    }  }  @Override  public boolean onTouchEvent(MotionEvent ev) {    //1.獲取速度追蹤器    getVelocityTracker();    //2.將當(dāng)前事件納入到追蹤器中    mVelocityTracker.addMovement(ev);    int pointId = -1;    switch (ev.getAction()) {      case MotionEvent.ACTION_DOWN:        //如果屏幕的動畫還沒結(jié)束,你就按下了,我們就結(jié)束上一次動畫,即開始這次新ACTION_DOWN的動畫//        clearScrollHis();        mLastX = (int) ev.getX();        pointId = ev.getPointerId(0);        break;      case MotionEvent.ACTION_MOVE:        int nextScrollX = (int) (mLastX - ev.getX() + getScrollX());        if (scrollTo(nextScrollX)) {          mLastX = (int) ev.getX();        }        break;      case MotionEvent.ACTION_CANCEL:      case MotionEvent.ACTION_UP:        //3.計算當(dāng)前速度        mVelocityTracker.computeCurrentVelocity(1000, mMaxFlingVelocity);        //獲取x y方向上的速度        float vX = mVelocityTracker.getXVelocity(pointId);        Log.i(TAG, "mVelocityX:" + vX);        //大于某個速率 直接滑動        if (vX > SNAP_VELOCITY) {          scrollToLeft();        } else if (vX < -SNAP_VELOCITY) {          scrollToRight();        } else {          snapToDestation();        }        //4.回收速度追蹤器        recycleVelocityTracker();        break;    }    return true;  }  private void openActivityAnimation() {    clearScrollHis();    mScroller.startScroll(getScrollX(), 0, mMaxScrollX - getScrollX(), 0, OPEN_ANIM_DURATION);    invalidate();//這里必須調(diào)用invalidate()才能保證computeScroll()會被調(diào)用,否則不一定會刷新界面,看不到滾動效果  }  public void closeActivityAnimation() {    clearScrollHis();    mScroller.startScroll(getScrollX(), 0, -getScrollX(), 0, OPEN_ANIM_DURATION);    invalidate();//這里必須調(diào)用invalidate()才能保證computeScroll()會被調(diào)用,否則不一定會刷新界面,看不到滾動效果  }  private void clearScrollHis() {    if (mScroller != null) {      if (!mScroller.isFinished()) {        mScroller.abortAnimation();      }    }  }  /**   * 根據(jù)現(xiàn)在的滾動位置判斷   */  private void snapToDestation() {    int scrollX = getScrollX();    if (scrollX > 0 && scrollX <= mLeftEdge) {      smoothScrollTo(0);    } else if (scrollX > mLeftEdge) {      smoothScrollTo(mMaxScrollX);    }  }  /**   * 直接滾動   *   * @param x   * @return   */  public boolean scrollTo(int x) {    if (x < 0) {      scrollTo(0, 0);    } else if (x > mMaxScrollX) {      scrollTo(mMaxScrollX, 0);    } else {      scrollTo(x, 0);    }    return true;  }  public void scrollToRight() {    smoothScrollTo(mMaxScrollX);  }  public void scrollToLeft() {    smoothScrollTo(0);  }  @Override  protected void onScrollChanged(int l, int t, int oldl, int oldt) {    super.onScrollChanged(l, t, oldl, oldt);    Log.d(TAG, "left:" + l);    if (l == 0) {      Log.d(TAG, "OnFinish");      Toast.makeText(mContext, "Finished", Toast.LENGTH_SHORT).show();      if(mOnFinishListener!=null){        mOnFinishListener.onFinish();      }    }  }  public void smoothScrollTo(int fx) {    if (fx < 0) {      smoothScrollTo(0, 0);    } else if (fx > mMaxScrollX) {      smoothScrollTo(mMaxScrollX, 0);    } else {      smoothScrollTo(fx, 0);    }  }  //  //調(diào)用此方法滾動到目標(biāo)位置  public void smoothScrollTo(int fx, int fy) {    int dx = fx - getScrollX();    int dy = fy - getScrollY();    smoothScrollBy(dx, dy);  }  //調(diào)用此方法設(shè)置滾動的相對偏移  public void smoothScrollBy(int dx, int dy) {    //設(shè)置mScroller的滾動偏移量    mScroller.startScroll(getScrollX(), 0, dx, dy, Math.abs(dx * DURATION / mMaxScrollX));    invalidate();//這里必須調(diào)用invalidate()才能保證computeScroll()會被調(diào)用,否則不一定會刷新界面,看不到滾動效果  }  @Override  public void computeScroll() {    //先判斷mScroller滾動是否完成    if (mScroller.computeScrollOffset()) {      //這里調(diào)用View的scrollTo()完成實際的滾動      scrollTo(mScroller.getCurrX(), mScroller.getCurrY());      //必須調(diào)用該方法,否則不一定能看到滾動效果      postInvalidate();    }    super.computeScroll();  }  /**   * fragment或者activity 結(jié)束的接口   */  public interface OnFinishListener{    void onFinish();  }}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 西乌珠穆沁旗| 定州市| 桃园市| 镇平县| 定日县| 合川市| 北宁市| 元氏县| 西乌珠穆沁旗| 浪卡子县| 赞皇县| 逊克县| 宣汉县| 兰西县| 富宁县| 桓仁| 城口县| 大冶市| 安阳市| 漳平市| 洛隆县| 皮山县| 郑州市| 巍山| 息烽县| 佛教| 蒙阴县| 罗定市| 治多县| 东阿县| 双牌县| 临漳县| 乌审旗| 迭部县| 萨嘎县| 天镇县| 榆中县| 叶城县| 宝清县| 全椒县| 招远市|