最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

最近手機(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),但是對于我這種已經(jīng)基本完成的項(xiàng)目來說,如果全部的Activity再重新使用自定義的View無疑是一種可怕的噩夢。

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

原理

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

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

注意?。。≡诨瑒拥臅r候必須需要考慮到Activity里面有可能會有類似于ListView一類的滑動控件,因此,我們必須對事件進(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<>();
  /**
   * 移動距離
   */
  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)在算是有點(diǎn)效果了,但是和微信的差距還是很大,接下來我們便需要開始處理自動滑動了

自動滑動

這個就不需要多說了,這個主要就是利用屬性動畫進(jì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?NDK開發(fā)之FFmpeg視頻添加水印

    Android?NDK開發(fā)之FFmpeg視頻添加水印

    這篇文章主要介紹了在Android?NDK開發(fā)中如何通過FFmpeg為視頻添加水印,文中的示例代碼講解詳細(xì),對我們了解Android開發(fā)有一定的幫助,感興趣的可以學(xué)習(xí)一下
    2021-12-12
  • 一步步教你寫Slack的Loading動畫

    一步步教你寫Slack的Loading動畫

    這篇文章主要為大家詳細(xì)手摸手教你寫Slack的Loading動畫,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • android打開本地圖像的方法

    android打開本地圖像的方法

    這篇文章主要介紹了android打開本地圖像的方法,涉及Android操作圖像的相關(guān)技巧,需要的朋友可以參考下
    2015-04-04
  • Spi機(jī)制在Android開發(fā)的應(yīng)用示例詳解

    Spi機(jī)制在Android開發(fā)的應(yīng)用示例詳解

    這篇文章主要為大家介紹了Spi機(jī)制在Android開發(fā)的應(yīng)用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Android 沉浸式改變小米魅族狀態(tài)欄顏色的實(shí)例代碼

    Android 沉浸式改變小米魅族狀態(tài)欄顏色的實(shí)例代碼

    這篇文章主要介紹了Android 沉浸式改變小米魅族狀態(tài)欄顏色的實(shí)例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-02-02
  • Android編程實(shí)現(xiàn)自定義分享列表ACTION_SEND功能的方法

    Android編程實(shí)現(xiàn)自定義分享列表ACTION_SEND功能的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)自定義分享列表ACTION_SEND功能的方法,結(jié)合實(shí)例形式詳細(xì)分析了自定義分享列表功能的步驟與具體操作技巧,需要的朋友可以參考下
    2017-02-02
  • Android Studio手動配置Gradle的方法

    Android Studio手動配置Gradle的方法

    Gradle:Gradle是一個基于Apache Ant和Apache Maven概念的項(xiàng)目自動化建構(gòu)工具。它使用一種基于Groovy的特定領(lǐng)域語言(DSL)來聲明項(xiàng)目設(shè)置,拋棄了基于XML的各種繁瑣配置,本文給大家介紹Android Studio手動配置Gradle的方法,一起看看吧
    2017-11-11
  • Android網(wǎng)絡(luò)編程之UDP通信模型實(shí)例

    Android網(wǎng)絡(luò)編程之UDP通信模型實(shí)例

    這篇文章主要介紹了Android網(wǎng)絡(luò)編程之UDP通信模型實(shí)例,本文給出了服務(wù)端代碼和客戶端代碼,需要的朋友可以參考下
    2014-10-10
  • Android全面屏與異形(劉海)屏的適配教程

    Android全面屏與異形(劉海)屏的適配教程

    Apple一直在引領(lǐng)設(shè)計(jì)的潮流,自從 iPhone X 發(fā)布之后,各種異形屏、劉海屏也都出來,下面這篇文章主要給大家分享介紹了關(guān)于Android全面屏與異形(劉海)屏的適配教程,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-07-07
  • Android Studio ADB網(wǎng)絡(luò)調(diào)試匯總

    Android Studio ADB網(wǎng)絡(luò)調(diào)試匯總

    這篇文章主要為大家詳細(xì)介紹了Android Studio ADB網(wǎng)絡(luò)調(diào)試的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05

最新評論

四平市| 门源| 乐陵市| 当涂县| 营山县| 梅河口市| 新密市| 黄山市| 武定县| 奉新县| 洛川县| 沂源县| 武威市| 江西省| 扶风县| 扎兰屯市| 吉水县| 临沧市| 酉阳| 伊金霍洛旗| 阿拉善右旗| 宜黄县| 韶山市| 驻马店市| 淮北市| 常宁市| 宁南县| 卢龙县| 滨州市| 普宁市| 铁岭市| 叙永县| 静安区| 汉源县| 海宁市| 沁水县| 铜陵市| 阜宁县| 泰州市| 增城市| 方山县|