亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

 更新時間:2016年02月01日 10:59:02   作者:_jerry_min_  
這篇文章主要介紹了Android中SwipeBack實現(xiàn)右滑返回效果的相關資料,需要的朋友可以參考下

現(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.將當前事件納入到追蹤器中
    mVelocityTracker.addMovement(ev);

    int pointId = -1;

    switch (ev.getAction()) {
      case MotionEvent.ACTION_DOWN:
        //如果屏幕的動畫還沒結束,你就按下了,我們就結束上一次動畫,即開始這次新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.計算當前速度
        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();//這里必須調用invalidate()才能保證computeScroll()會被調用,否則不一定會刷新界面,看不到滾動效果
  }

  public void closeActivityAnimation() {
    clearScrollHis();
    mScroller.startScroll(getScrollX(), 0, -getScrollX(), 0, OPEN_ANIM_DURATION);
    invalidate();//這里必須調用invalidate()才能保證computeScroll()會被調用,否則不一定會刷新界面,看不到滾動效果
  }

  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);
    }
  }

  //  //調用此方法滾動到目標位置
  public void smoothScrollTo(int fx, int fy) {
    int dx = fx - getScrollX();
    int dy = fy - getScrollY();
    smoothScrollBy(dx, dy);
  }

  //調用此方法設置滾動的相對偏移
  public void smoothScrollBy(int dx, int dy) {

    //設置mScroller的滾動偏移量
    mScroller.startScroll(getScrollX(), 0, dx, dy, Math.abs(dx * DURATION / mMaxScrollX));
    invalidate();//這里必須調用invalidate()才能保證computeScroll()會被調用,否則不一定會刷新界面,看不到滾動效果
  }

  @Override
  public void computeScroll() {

    //先判斷mScroller滾動是否完成
    if (mScroller.computeScrollOffset()) {

      //這里調用View的scrollTo()完成實際的滾動
      scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

      //必須調用該方法,否則不一定能看到滾動效果
      postInvalidate();
    }
    super.computeScroll();
  }

  /**
   * fragment或者activity 結束的接口
   */
  public interface OnFinishListener{
    void onFinish();
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助。

相關文章

  • Android自定義view制作抽獎轉盤

    Android自定義view制作抽獎轉盤

    這篇文章主要為大家詳細介紹了Android自定義view制作抽獎轉盤,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • 安卓圖片反復壓縮后為什么普遍會變綠而不是其它顏色?

    安卓圖片反復壓縮后為什么普遍會變綠而不是其它顏色?

    今天小編就為大家分享一篇關于安卓圖片反復壓縮后為什么普遍會變綠而不是其它顏色?,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • android動態(tài)壁紙調用的簡單實例

    android動態(tài)壁紙調用的簡單實例

    動態(tài)壁紙的實現(xiàn)其實就是在Activity中調用動態(tài)壁紙服務,通過綁定服務得到IWallpaperService,調用該接口中的attach函數(shù)實現(xiàn)壁紙的調用。
    2013-06-06
  • Android studio 4.1打包失敗和插件錯誤提示的解決

    Android studio 4.1打包失敗和插件錯誤提示的解決

    這篇文章主要介紹了Android studio 4.1打包失敗和插件錯誤提示的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • Android 實現(xiàn)局部圖片滑動指引效果

    Android 實現(xiàn)局部圖片滑動指引效果

    這篇文章主要介紹了Android 實現(xiàn)局部圖片滑動指引效果的相關資料,需要的朋友可以參考下
    2017-01-01
  • Android 圖片顯示與屏幕適配的問題

    Android 圖片顯示與屏幕適配的問題

    這篇文章主要介紹了Android 圖片顯示與屏幕適配的問題的相關資料,Android的分辨率問題是每個Android 開發(fā)者頭疼的問題,那么這里給大家介紹個萬能辦法,需要的朋友可以參考下
    2017-08-08
  • 自定義Adapter并通過布局泵LayoutInflater抓取layout模板編輯每一個item實現(xiàn)思路

    自定義Adapter并通過布局泵LayoutInflater抓取layout模板編輯每一個item實現(xiàn)思路

    自定義Adapter并通過布局泵LayoutInflater抓取layout模板編輯每一個item,下面我們開始學習這一篇的內容,感興趣的朋友可以了解下哈
    2013-06-06
  • 更新Android Studio 3.0碰到的問題小結

    更新Android Studio 3.0碰到的問題小結

    本文是小編給大家分享的更新Android Studio 3.0碰到的問題小結,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-11-11
  • Android四大組件之broadcast廣播使用講解

    Android四大組件之broadcast廣播使用講解

    Android開發(fā)的四大組件分別是:活動(activity),用于表現(xiàn)功能;服務(service),后臺運行服務,不提供界面呈現(xiàn);廣播接受者(Broadcast Receive),勇于接收廣播;內容提供者(Content Provider),支持多個應用中存儲和讀取數(shù)據(jù),相當于數(shù)據(jù)庫,本篇著重介紹廣播組件
    2022-12-12
  • Android EditText隨輸入法一起移動并懸浮在輸入法之上的示例代碼

    Android EditText隨輸入法一起移動并懸浮在輸入法之上的示例代碼

    這篇文章主要介紹了Android EditText隨輸入法一起移動并懸浮在輸入法之上,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06

最新評論