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

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

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

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

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

原理

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

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

  /**
   * 手勢(shì)監(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)前頁面滑動(dòng)
     */
    private void handlerCurrentActivityScroll(MotionEvent e2) {
      mRootView.setTranslationX(e2.getX());
      if (e2.getX() > mWindowWidth - 20) {
        finish();
      }
    }
  }
}

這是我們的效果

Activity聯(lián)動(dòng)

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

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

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

注意?。。≡诨瑒?dòng)的時(shí)候必須需要考慮到Activity里面有可能會(huì)有類似于ListView一類的滑動(dòng)控件,因此,我們必須對(duì)事件進(jìn)行分發(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<>();
  /**
   * 移動(dòng)距離
   */
  private float mWindowWidth;
  private TestActivity mBeforeActivity;
  /**
   * 上一個(gè)Activity偏移量
   */
  private float mOffsetX;
  /**
   * 上一個(gè)頁面移出的位置
   */
  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ā)拖動(dòng)的范圍
   */
  @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;
  }

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

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

  /**
   * 手勢(shì)監(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)前頁面滑動(dòng)
     */
    private void handlerCurrentActivityScroll(MotionEvent e2) {
      mRootView.setTranslationX(e2.getX());
      if (e2.getX() > mWindowWidth - 20) {
        finish();
      }
    }

    /**
     * 處理上一個(gè)頁面滑動(dòng)
     */
    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)動(dòng)后的效果圖

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

自動(dòng)滑動(dòng)

這個(gè)就不需要多說了,這個(gè)主要就是利用屬性動(dòng)畫進(jìn)行移動(dòng)

以下是完整的代碼

public class SlideActivity extends AppCompatActivity {
  private static final String TAG = "SlideActivity";
  private static List<SlideActivity> mActivitys = new ArrayList<>();
  /**
   * 手勢(shì)監(jiān)聽
   */
  private GestureDetector mGestureDetector;
  private View mRootView;
  private boolean isScroll = false;
  /**
   * 移動(dòng)距離
   */
  private float mWindowWidth;
  private SlideActivity mBeforeActivity;
  /**
   * 上一個(gè)Activity偏移量
   */
  private float mOffsetX;
  /**
   * 上一個(gè)頁面移出的位置
   */
  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();

  }

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

  /**
   * 設(shè)置是否能滑動(dòng)
   *
   * @param canScrollBack true 可以滑動(dòng)
   */
  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;
  }

  /**
   * 手勢(shì)監(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)前頁面滑動(dòng)
     */
    private void handlerCurrentActivityScroll(MotionEvent e2) {
      isScroll = true;
      mRootView.setTranslationX(e2.getX());
      if (e2.getX() > mWindowWidth - 20) {
        finish();
      }
    }

    /**
     * 處理上一個(gè)頁面滑動(dòng)
     */
    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)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

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

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

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

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

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

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

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

    android自定義view用path畫長方形

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

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

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

    Android Studio3.0.1填坑筆記

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

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

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

    Android中的Parcelable序列化對(duì)象

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

    淺析Android的啟動(dòng)原理

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

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

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

最新評(píng)論