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

首頁 > 系統 > Android > 正文

Android實現微信側滑關閉頁面效果

2019-10-22 18:21:40
字體:
來源:轉載
供稿:網友

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

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

原理

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

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

這是我們的效果

Android微信側滑關閉頁面,Android側滑關閉頁面,Android微信側滑

Activity聯動

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

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

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

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

代碼如下

/** * 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);    /**     * 把當前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);  }  /**   * 控制分發事件,在這里控制能能觸發拖動的范圍   */  @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);  }  /**   * 手勢監聽   */  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);    }    /**     * 處理當前頁面滑動     */    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);      }    }  }}

這是聯動后的效果圖

Android微信側滑關閉頁面,Android側滑關閉頁面,Android微信側滑

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

自動滑動

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

以下是完整的代碼

public class SlideActivity extends AppCompatActivity {  private static final String TAG = "SlideActivity";  private static List<SlideActivity> mActivitys = new ArrayList<>();  /**   * 手勢監聽   */  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);    /**     * 把當前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);    }  }  /**   * 設置是否能滑動   *   * @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();  }  /**   * 控制分發事件   */  @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;        //退出當前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;  }  /**   * 手勢監聽   */  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);    }    /**     * 處理當前頁面滑動     */    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);      }    }  }}

這是我們最終的效果圖

Android微信側滑關閉頁面,Android側滑關閉頁面,Android微信側滑

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 昭苏县| 辛集市| 城口县| 澄江县| 昭平县| 屏东市| 乌拉特后旗| 叶城县| 湄潭县| 仙居县| 镇江市| 门头沟区| 昌吉市| 溧水县| 萨嘎县| 大名县| 新闻| 陵水| 通许县| 内丘县| 阳谷县| 毕节市| 黑河市| 鄢陵县| 三都| 泰兴市| 丹江口市| 淮北市| 黄平县| 怀安县| 都昌县| 乾安县| 中西区| 武义县| 鸡泽县| 孟连| 大石桥市| 三江| 乌兰察布市| 孝义市| 安溪县|