欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實現(xiàn)微信側(cè)滑關(guān)閉頁面效果

 更新時間:2017年12月02日 09:43:59   作者:AriaLyy  
這篇文章主要為大家詳細介紹了Android實現(xiàn)微信側(cè)滑關(guān)閉頁面效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下

最近手機升級了5.0系統(tǒng)后,突然間發(fā)現(xiàn)微信竟然有IOS一樣的側(cè)滑關(guān)閉當(dāng)前頁面的效果,就想把這種效果也加進自己的項目里面。本著不重復(fù)造輪子的原則,就在網(wǎng)上百度了很久,發(fā)現(xiàn)大多數(shù)人都是采用自定義View來實現(xiàn),但是對于我這種已經(jīng)基本完成的項目來說,如果全部的Activity再重新使用自定義的View無疑是一種可怕的噩夢。

因此,我這里實現(xiàn)了另外一種不需要自定義View也能實現(xiàn)的方法,其子類只要繼承于它,便能擁有其側(cè)滑滑動的功能。
隨便說一句,此方法僅對5.0以上的手機有效(反正微信也是5.0上才能用),5.0以下的請無視?。?!

原理

在每個Activity里面都有一個底層的View,也就是所謂的rootView,當(dāng)我們加載一個xml布局時,系統(tǒng)就會自動給你生成這個rootView,由于它是一個View,那么也就意味著你可以通過一定的代碼隨意移動這個根布局。
如下代碼所示,只要簡單的幾行代碼便能實現(xiàn)布局的移動。

public class SlideActivity extends AppCompatActivity {
  View mRootView;
  private GestureDetector mDetector;
  private int mWindowWidth;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_demo);
    mRootView = getWindow().getDecorView();
    mRootView.setBackgroundColor(Color.BLUE);
    mDetector = new GestureDetector(this, new GestureListener());
    mWindowWidth = getWindow().getWindowManager().getDefaultDisplay().getWidth();
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    return mDetector.onTouchEvent(event);
  }

  /**
   * 手勢監(jiān)聽
   */
  private class GestureListener extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
      if (e1 != null) {
        handlerCurrentActivityScroll(e2);
      }
      return super.onScroll(e1, e2, distanceX, distanceY);
    }

    /**
     * 處理當(dāng)前頁面滑動
     */
    private void handlerCurrentActivityScroll(MotionEvent e2) {
      mRootView.setTranslationX(e2.getX());
      if (e2.getX() > mWindowWidth - 20) {
        finish();
      }
    }
  }
}

這是我們的效果

Activity聯(lián)動

這差距還是很大的,最明顯的地方是,我們移動 的時候,上一層Activity竟然沒有跟著聯(lián)動。

解決這個問題的方法也簡單,如圖所示,每當(dāng)啟動一個Activity時,系統(tǒng)都會把Activity放到一個棧里面,由于棧的工作原理可知,APP里面的Activity是一層覆蓋一層的,就如上圖所示。為此,每當(dāng)啟動一個Activity時,就可以把當(dāng)前的Actiivty存儲到一個List里面,這樣,我們就可以在當(dāng)前的Activity里面取出上一個Activity進行操作。

因此,在進入一個新的Activity的時候,在其onCreate方法里面把當(dāng)前的Activity加載到列表里,當(dāng)退出時,在finish的重載方法里面,將當(dāng)前Activity從列表里面移除。

注意!??!在滑動的時候必須需要考慮到Activity里面有可能會有類似于ListView一類的滑動控件,因此,我們必須對事件進行分發(fā)控制。

代碼如下

/**
 * Created by yuyu on 2015/10/29.
 */
public class TestActivity extends AppCompatActivity {
  View mRootView;
  private GestureDetector mGestureDetector;
  private static List<TestActivity> mActivitys = new ArrayList<>();
  /**
   * 移動距離
   */
  private float mWindowWidth;
  private TestActivity mBeforeActivity;
  /**
   * 上一個Activity偏移量
   */
  private float mOffsetX;
  /**
   * 上一個頁面移出的位置
   */
  private float mOutsideWidth;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_demo);
    /**
     * 把當(dāng)前Activity加到列表里面
     */
    mActivitys.add(this);
    initScrollBack();
  }

  /**
   * 初始化左滑退出功能
   */
  private void initScrollBack() {
    mWindowWidth = getWindowManager().getDefaultDisplay().getWidth();
    mOutsideWidth = -mWindowWidth / 4;
    mOffsetX = mOutsideWidth;
    mGestureDetector = new GestureDetector(this, new GestureListener());
    mRootView = getWindow().getDecorView();
    mRootView.setBackgroundColor(Color.BLUE);
  }

  /**
   * 控制分發(fā)事件,在這里控制能能觸發(fā)拖動的范圍
   */
  @Override
  public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
    if (ev.getX() < mWindowWidth / 10) {
      if (mActivitys.size() > 1) {
        mBeforeActivity = mActivitys.get(mActivitys.size() - 2);
        beforeActivityTranslationX(mOutsideWidth);
      }
      return onTouchEvent(ev);
    }
    return super.dispatchTouchEvent(ev);
  }

  @Override
  public void finish() {
    mActivitys.remove(this);
    if (mOffsetX < 0.0001 || mOffsetX > 0.0001) {
      beforeActivityTranslationX(0);
    }
    super.finish();
  }

  public void onClick(View view) {
    Intent intent = new Intent(this, Activity5.class);
    startActivity(intent);
  }

  public View getRootView() {
    return mRootView;
  }

  /**
   * 控制上一個Activity移動
   */
  private void beforeActivityTranslationX(float translationX) {
    if (mBeforeActivity != null) {
      mBeforeActivity.getRootView().setTranslationX(translationX);
    }
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    return mGestureDetector.onTouchEvent(event);
  }

  /**
   * 手勢監(jiān)聽
   */
  private class GestureListener extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
      if (e1 != null) {
        handlerCurrentActivityScroll(e2);
        handleBeforeActivityScroll(e2, distanceX);
      }
      return super.onScroll(e1, e2, distanceX, distanceY);
    }

    /**
     * 處理當(dāng)前頁面滑動
     */
    private void handlerCurrentActivityScroll(MotionEvent e2) {
      mRootView.setTranslationX(e2.getX());
      if (e2.getX() > mWindowWidth - 20) {
        finish();
      }
    }

    /**
     * 處理上一個頁面滑動
     */
    private void handleBeforeActivityScroll(MotionEvent e2, float distanceX) {
      if (mBeforeActivity != null) {
        mOffsetX = distanceX < 0 ? mOffsetX + Math.abs(distanceX) / 4 : mOffsetX - Math.abs(distanceX) / 4;
        if (mOffsetX > 0.0001) {
          mOffsetX = 0f;
        }
        mBeforeActivity.getRootView().setTranslationX(mOffsetX);
      }
    }
  }
}

這是聯(lián)動后的效果圖

現(xiàn)在算是有點效果了,但是和微信的差距還是很大,接下來我們便需要開始處理自動滑動了

自動滑動

這個就不需要多說了,這個主要就是利用屬性動畫進行移動

以下是完整的代碼

public class SlideActivity extends AppCompatActivity {
  private static final String TAG = "SlideActivity";
  private static List<SlideActivity> mActivitys = new ArrayList<>();
  /**
   * 手勢監(jiān)聽
   */
  private GestureDetector mGestureDetector;
  private View mRootView;
  private boolean isScroll = false;
  /**
   * 移動距離
   */
  private float mWindowWidth;
  private SlideActivity mBeforeActivity;
  /**
   * 上一個Activity偏移量
   */
  private float mOffsetX;
  /**
   * 上一個頁面移出的位置
   */
  private float mOutsideWidth;
  private boolean canScrollBack = true;
  private boolean canScroll = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().setEnterTransition(new Slide(Gravity.RIGHT));
    super.onCreate(savedInstanceState);
    /**
     * 把當(dāng)前Activity加到列表里面
     */
    mActivitys.add(this);
    initScrollBack();
  }

  @Override
  public void startActivity(Intent intent) {
    startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
  }

  /**
   * 初始化左滑退出功能
   */
  private void initScrollBack() {
    mWindowWidth = getWindowManager().getDefaultDisplay().getWidth();
    mOutsideWidth = -mWindowWidth / 4;
    mOffsetX = mOutsideWidth;
    mGestureDetector = new GestureDetector(this, new GestureListener());
    mRootView = getWindow().getDecorView();

  }

  /**
   * 控制上一個Activity移動
   */
  private void beforeActivityTranslationX(float translationX) {
    if (mBeforeActivity != null) {
      mBeforeActivity.getRootView().setTranslationX(translationX);
    }
  }

  /**
   * 設(shè)置是否能滑動
   *
   * @param canScrollBack true 可以滑動
   */
  protected void setCanScrollBack(boolean canScrollBack) {
    this.canScrollBack = canScrollBack;
  }

  public View getRootView() {
    return mRootView;
  }

  @Override
  public void finish() {
    mActivitys.remove(this);
    if (mOffsetX < 0.0001 || mOffsetX > 0.0001) {
      beforeActivityTranslationX(0);
    }
    super.finish();
  }

  /**
   * 控制分發(fā)事件
   */
  @Override
  public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
    if (canScrollBack && ev.getX() < mWindowWidth / 10) {
      if (mActivitys.size() > 1) {
        mBeforeActivity = mActivitys.get(mActivitys.size() - 2);
        beforeActivityTranslationX(mOutsideWidth);
      }
      canScroll = true;
      return onTouchEvent(ev);
    }
    return super.dispatchTouchEvent(ev);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (canScrollBack && canScroll) {
      if (event.getAction() == MotionEvent.ACTION_UP && isScroll) {
        isScroll = false;
        canScroll = false;
        //退出當(dāng)前Activity
        if (event.getX() > mWindowWidth / 2) {
          if (mBeforeActivity != null) {
            ObjectAnimator.ofFloat(mBeforeActivity.getRootView(), "translationX", mOffsetX, 0).setDuration(500).start();
          }
          ObjectAnimator moveIn = ObjectAnimator.ofFloat(mRootView, "translationX", event.getX(), mWindowWidth);
          moveIn.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
              super.onAnimationEnd(animation);
              finish();
            }
          });
          moveIn.setDuration(500).start();
          //反彈回來
        } else if (event.getX() < mWindowWidth / 2) {
          ObjectAnimator.ofFloat(mRootView, "translationX", event.getX(), 0).setDuration(500).start();
          if (mBeforeActivity != null) {
            ObjectAnimator.ofFloat(mBeforeActivity.getRootView(), "translationX", mOffsetX, mOutsideWidth).setDuration(500).start();
          }
          mOffsetX = mOutsideWidth;
        }
      } else {
        mGestureDetector.onTouchEvent(event);
      }
    }
    return true;
  }

  /**
   * 手勢監(jiān)聽
   */
  private class GestureListener extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
      if (e1 != null) {
        handlerCurrentActivityScroll(e2);
        handleBeforeActivityScroll(e2, distanceX);
      }
      return super.onScroll(e1, e2, distanceX, distanceY);
    }

    /**
     * 處理當(dāng)前頁面滑動
     */
    private void handlerCurrentActivityScroll(MotionEvent e2) {
      isScroll = true;
      mRootView.setTranslationX(e2.getX());
      if (e2.getX() > mWindowWidth - 20) {
        finish();
      }
    }

    /**
     * 處理上一個頁面滑動
     */
    private void handleBeforeActivityScroll(MotionEvent e2, float distanceX) {
      if (mBeforeActivity != null) {
        mOffsetX = distanceX < 0 ? mOffsetX + Math.abs(distanceX) / 4 : mOffsetX - Math.abs(distanceX) / 4;
        if (mOffsetX > 0.0001) {
          mOffsetX = 0f;
        }
        mBeforeActivity.getRootView().setTranslationX(mOffsetX);
      }
    }
  }
}

這是我們最終的效果圖

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

相關(guān)文章

  • android中使用SharedPreferences進行數(shù)據(jù)存儲的操作方法

    android中使用SharedPreferences進行數(shù)據(jù)存儲的操作方法

    本篇文章介紹了,在android中使用SharedPreferences進行數(shù)據(jù)存儲的操作方法。需要的朋友參考下
    2013-04-04
  • Android時間日期拾取器學(xué)習(xí)使用(DatePicker、TimePicker)

    Android時間日期拾取器學(xué)習(xí)使用(DatePicker、TimePicker)

    這篇文章主要為大家詳細介紹了Android提供的DatePicker日期拾取器和TimePicker時間拾取器的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Android仿天貓橫向滑動指示器功能的實現(xiàn)

    Android仿天貓橫向滑動指示器功能的實現(xiàn)

    這篇文章主要介紹了Android仿天貓橫向滑動指示器,Android開發(fā)中會有很多很新奇的交互,比如天貓商城的首頁頭部的分類,使用的是GridLayoutManager+橫向指示器實現(xiàn)的,需要的朋友可以參考下
    2022-08-08
  • android自定義view用path畫長方形

    android自定義view用path畫長方形

    這篇文章主要為大家詳細介紹了android自定義view用path畫長方形,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • Android實現(xiàn)分享功能

    Android實現(xiàn)分享功能

    如何在Android中實現(xiàn)分享功能?這篇文章主要為大家詳細介紹了Android實現(xiàn)分享功能的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android Studio3.0.1填坑筆記

    Android Studio3.0.1填坑筆記

    IntelliJ IDEA 功能強大,是Jet Brains 公司開發(fā)商業(yè)IDE(集成開發(fā)環(huán)境),同時支持Java, Scala 和Groovy。下面小編給大家?guī)砹薃ndroid Studio3.0.1填坑筆記,需要的朋友一起看看吧
    2018-01-01
  • Android自定義控件eBook實現(xiàn)翻書效果實例詳解

    Android自定義控件eBook實現(xiàn)翻書效果實例詳解

    這篇文章主要介紹了Android自定義控件eBook實現(xiàn)翻書效果的方法,結(jié)合實例形式分析了Android自定義控件實現(xiàn)翻書效果的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2016-10-10
  • Android中的Parcelable序列化對象

    Android中的Parcelable序列化對象

    這篇文章主要介紹了Android中的Parcelable序列化對象,需要的朋友可以參考下
    2016-01-01
  • 淺析Android的啟動原理

    淺析Android的啟動原理

    當(dāng)談到Android啟動原理時,我們進入了Android操作系統(tǒng)的核心,理解Android系統(tǒng)啟動的原理對于開發(fā)者來說非常重要,因為這有助于優(yōu)化應(yīng)用程序性能并提供更好的用戶體驗,本文給大家講講Android啟動原理,需要的朋友可以參考下
    2023-10-10
  • Android P實現(xiàn)靜默安裝的方法示例(官方Demo)

    Android P實現(xiàn)靜默安裝的方法示例(官方Demo)

    這篇文章主要介紹了Android P實現(xiàn)靜默安裝,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02

最新評論