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

首頁 > 系統 > Android > 正文

android 右滑返回的示例代碼

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

類似于微信的右滑返回,在BaseActivity里利用dispatchTouchEvent()攔截右滑動作,利用setTranslationX()實現動畫,在DecorView里添加View作為滑動時的左側陰影。

android,右滑返回

漸進步驟:

  • 設置activity背景透明
  • 重寫finish()等方法設置activity的跳轉動畫
  • 重寫dispatchTouchEvent()攔截 所需要 右滑動作
  • 重寫onTouchEvent()給根布局設置偏移量
  • 添加滑動時上層activity的左側陰影
  • 滑動時關聯下層activity滑動

注意:步驟中的代碼為了不關聯到后面的步驟,會與最終的有點不同

背景透明

  <item name="android:windowBackground">@android:color/transparent</item>  <item name="android:windowIsTranslucent">true</item>

activity的跳轉動畫

根據項目需要,重寫用到的startActivity(Intent intent),startActivityForResult(Intent intent, int requestCode),finish()等activity跳轉和銷毀方法

@Overridepublic void startActivity(Intent intent) {  super.startActivity(intent);  overridePendingTransition(R.anim.slide_right_in, 0);}@Overridepublic void startActivityForResult(Intent intent, int requestCode) {  super.startActivityForResult(intent, requestCode);  overridePendingTransition(R.anim.slide_right_in, 0);}@Overridepublic void finish() {  super.finish();  overridePendingTransition(0, R.anim.slide_right_out);}//R.anim.slide_right_in<set xmlns:android="http://schemas.android.com/apk/res/android"> <translate   android:duration="300"   android:fromXDelta="100%"   android:toXDelta="0"   android:fromYDelta="0"   android:toYDelta="0"/></set>//R.anim.slide_right_out<set xmlns:android="http://schemas.android.com/apk/res/android"> <translate   android:duration="300"   android:fromXDelta="0"   android:toXDelta="100%"   android:fromYDelta="0"   android:toYDelta="0" /></set>

攔截右滑動作

所有的觸摸事件通過activity.dispatchTouchEvent(MotionEvent ev)向view分發。
手指在X軸方向右滑動50~100px時,判斷是否為(產品經理要)右滑動作

  • 手指落點為全屏幕,X方向滑動距離要比Y方向的大一些;
  • 手指落點為左側邊,X方向滑動距離有一些就行
private float downX = 0;private float downY = 0;private boolean shouldIntercept = false;private boolean hadJudge = false;@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {  if (shouldIntercept) {    return onTouchEvent(ev);  }  switch (ev.getAction()) {    case MotionEvent.ACTION_DOWN: {      downX = ev.getRawX();      downY = ev.getRawY();      hadJudge = false;      break;    }    case MotionEvent.ACTION_MOVE: {      if (hadJudge) break;      if (ev.getRawX() == downX) break;      if (ev.getRawX() < downX) {        //左滑        hadJudge = true;        break;      }      if (ev.getRawX() - downX >=100){        //超出判斷距離        hadJudge = true;        break;      }      if (ev.getRawX() - downX > 50) {        //x軸右滑50~100px        float rate = (ev.getRawX() - downX) / (Math.abs(ev.getRawY() - downY));        if ((downX < 50 && rate > 0.5f) || rate > 2) {          shouldIntercept = true;        }      }      break;    }    case MotionEvent.ACTION_UP: {      downX =0;      downY = 0;      shouldIntercept = false;      hadJudge=false;      break;    }  }  //Activity的默認分發  if (ev.getAction() == MotionEvent.ACTION_DOWN) {    onUserInteraction();  }  if (getWindow().superDispatchTouchEvent(ev)) {    return true;  }  return true;}

根布局位移動畫

根據手指滑動距離設置根布局偏移距離,用滑動距離和手指抬起時的速度判斷是否返回

private View rootView = null;private float lastX = -1;  private VelocityTracker velocityTracker = null;private int maxFlingVelocity;@Overridepublic boolean onTouchEvent(MotionEvent event) {  if (rootView == null) {    ViewGroup rootGroup = (ViewGroup) (getWindow().getDecorView());    rootView = rootGroup.getChildAt(0);  }  //測量手指抬起時的速度  if (velocityTracker == null) {    velocityTracker = VelocityTracker.obtain();    maxFlingVelocity = ViewConfiguration.get(this).getScaledMaximumFlingVelocity();  }  velocityTracker.addMovement(event);  switch (event.getAction()) {    case MotionEvent.ACTION_DOWN: {      lastX = event.getRawX();      break;    }    case MotionEvent.ACTION_MOVE: {      if (lastX == -1) {        lastX = event.getRawX();        break;      }      //根據手指滑動距離設置根布局偏移距離      rootView.setTranslationX(rootView.getTranslationX() + event.getRawX() - lastX);      if (rootView.getTranslationX() < 0) rootView.setTranslationX(0);      lastX = event.getRawX();      break;    }    case MotionEvent.ACTION_UP: {      //測量手指抬起時的速度      velocityTracker.computeCurrentVelocity(1000, maxFlingVelocity);      float velocityX = velocityTracker.getXVelocity();      if (velocityTracker != null) {        velocityTracker.recycle();        velocityTracker = null;      }      //判斷是否返回      if (downX < 50 && velocityX > 1000) {        //手指在左側邊落下,返回        onBack();      } else if (velocityX > 3600) {        //手指快速滑動,返回        onBack();      } else if (rootView.getTranslationX() > ConvertUtil.getWidthInPx() * 0.3) {        //滑動距離超過30%屏幕寬度,返回        onBack();      } else {        //不返回,根布局偏移歸零        rootView.animate().translationX(0).setDuration(200).start();      }            lastX = -1;      shouldIntercept = false;      hadJudge=false;      downX = 0;      downY = 0;      break;    }  }  return super.onTouchEvent(event);}

添加左側陰影

Activity的最頂層View為DecorView,DecorView是一個FrameLayout,里面只有一個Linearlayout,Linearlayout包含著標題欄和自定義布局(setContentView)。
上一步跟隨手指滑動進行偏移的就是Linearlayout,現在要在DecorView里添加一個View,設置背景作為陰影,并跟隨Linearlayout進行移動

private View shadowView = null;@Overridepublic boolean onTouchEvent(MotionEvent event) {  if (rootView == null) {    //添加陰影        ViewGroup rootGroup = (ViewGroup) (getWindow().getDecorView());    shadowView = new View(this);    rootGroup.addView(shadowView, 0);    ViewGroup.LayoutParams params = shadowView.getLayoutParams();    //陰影寬度    params.width = (int) ((float) ConvertUtil.getWidthInPx() * 0.05f);    params.height = ConvertUtil.getHeightInPx();    shadowView.setLayoutParams(params);    shadowView.setBackgroundResource(R.drawable.shadow_grey_h);    shadowView.setTranslationX(params.width);    rootView = rootGroup.getChildAt(1);  }  ...  switch (event.getAction()) {    ...    case MotionEvent.ACTION_MOVE: {      if (lastX == -1) {        lastX = event.getRawX();        break;      }      //根據手指滑動距離設置根布局偏移距離      rootView.setTranslationX(rootView.getTranslationX() + event.getRawX() - lastX);      if (rootView.getTranslationX() < 0) rootView.setTranslationX(0);      //陰影跟隨根布局移動      shadowView.setTranslationX(-shadowView.getWidth()+rootView.getTranslationX());      lastX = event.getRawX();      break;    }    case MotionEvent.ACTION_UP: {      ...      } else {        //不返回,根布局偏移歸零        rootView.animate().translationX(0).setDuration(200).start();        //陰影偏移歸零        shadowView.animate().translationX(-shadowView.getWidth()).setDuration(200).start();      }      ...    }  }  ...}

關聯下層activity滑動

  • 保存所有的activity以獲取下層activity
  • 給下層activity添加退出和進入的動畫
  • 在上層activity滑動時調用下層滑動

獲取下層activity

private static ArrayList<Activity> Activity_Stack = new ArrayList<>();private BaseSwipeBackActivity lastActivity = null;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  maxFlingVelocity = ViewConfiguration.get(this).getScaledMaximumFlingVelocity();  if (!Activity_Stack.contains(this)) Activity_Stack.add(this);  if (Activity_Stack.size() >= 2) {    Activity last = Activity_Stack.get(Activity_Stack.size() - 2);    if (last instanceof BaseSwipeBackActivity) {      lastActivity = (BaseSwipeBackActivity) last;    }  }}@Overrideprotected void onDestroy() {  super.onDestroy();  Activity_Stack.remove(this);}

下層activity的退出、進入動畫

private void lowerActivityExitAnim() {  if (rootView == null) return;  //只移動30%  rootView.animate().translationX(-ConvertUtil.getWidthInPx() * 0.3f).setDuration(300).start();}private void lowerActivityEnterAnim(float upperTranslationX) {  if (rootView == null) return;  //保證滑動退出時,上下層時間同步  float r = 1-upperTranslationX/ (float) ConvertUtil.getWidthInPx();  rootView.animate().translationX(0).setDuration((long) (300f * r)).start();}

在跳轉時,調用下層activity的退出、進入動畫

@Overridepublic void startActivity(Intent intent) {  super.startActivity(intent);  overridePendingTransition(R.anim.slide_right_in, 0);  lowerActivityExitAnim();}@Overridepublic void startActivityForResult(Intent intent, int requestCode) {  super.startActivityForResult(intent, requestCode);  overridePendingTransition(R.anim.slide_right_in, 0);  lowerActivityExitAnim();}@Overridepublic void finish() {  super.finish();  overridePendingTransition(0, R.anim.slide_right_out);  if (lastActivity != null) lastActivity.lowerActivityEnterAnim(rootView.getTranslationX());  Activity_Stack.remove(this);}

上層activity滑動時關聯下層滑動

@Overridepublic boolean onTouchEvent(MotionEvent event) {  ...  switch (event.getAction()) {    ...    case MotionEvent.ACTION_MOVE: {      ...      //根據手指滑動距離設置根布局偏移距離      rootView.setTranslationX(rootView.getTranslationX() + event.getRawX() - lastX);      if (rootView.getTranslationX() < 0) rootView.setTranslationX(0);      //陰影跟隨根布局移動      shadowView.setTranslationX(-shadowView.getWidth() + rootView.getTranslationX());      //下層activity跟隨移動      if (lastActivity != null && lastActivity.rootView != null)        //-ConvertUtil.getWidthInPx() * 0.3f初始的偏移        lastActivity.rootView.setTranslationX(-ConvertUtil.getWidthInPx() * 0.3f + rootView.getTranslationX() * 0.3f);      ...    }    case MotionEvent.ACTION_UP: {      ...      } else {        //不返回,根布局偏移歸零        rootView.animate().translationX(0).setDuration(200).start();        //陰影偏移歸零        shadowView.animate().translationX(-shadowView.getWidth()).setDuration(200).start();        //下層activity偏移復原        if (lastActivity != null)          lastActivity.lowerActivityExitAnim();      }      ...    }  }  return super.onTouchEvent(event);}

完整的

public abstract class BaseSwipeBackActivity extends AppCompatActivity {  private static ArrayList<Activity> Activity_Stack = new ArrayList<>();  private BaseSwipeBackActivity lastActivity = null;  private View rootView = null;  private View shadowView = null;  private float downX = 0;  private float downY = 0;  private boolean shouldIntercept = false;  private boolean hadJudge = false;  private float lastX = -1;  private VelocityTracker velocityTracker = null;  private int maxFlingVelocity;  @Override  protected void onCreate(@Nullable Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    maxFlingVelocity = ViewConfiguration.get(this).getScaledMaximumFlingVelocity();    if (!Activity_Stack.contains(this)) Activity_Stack.add(this);    if (Activity_Stack.size() >= 2) {      Activity last = Activity_Stack.get(Activity_Stack.size() - 2);      if (last instanceof BaseSwipeBackActivity) {        lastActivity = (BaseSwipeBackActivity) last;      }    }  }  @Override  protected void onResume() {    initShadow();    super.onResume();  }  @Override  protected void onDestroy() {    super.onDestroy();    Activity_Stack.remove(this);  }  @Override  public void startActivity(Intent intent) {    super.startActivity(intent);    overridePendingTransition(R.anim.slide_right_in, 0);    lowerActivityExitAnim();  }  @Override  public void startActivityForResult(Intent intent, int requestCode) {    super.startActivityForResult(intent, requestCode);    overridePendingTransition(R.anim.slide_right_in, 0);    lowerActivityExitAnim();  }  @Override  public void finish() {    super.finish();    overridePendingTransition(0, R.anim.slide_right_out);    if (lastActivity != null) lastActivity.lowerActivityEnterAnim(rootView.getTranslationX());    Activity_Stack.remove(this);  }  private void initShadow() {    if (shadowView == null) {      ViewGroup rootGroup = (ViewGroup) (getWindow().getDecorView());      shadowView = new View(this);      rootGroup.addView(shadowView, 0);      ViewGroup.LayoutParams params = shadowView.getLayoutParams();      //陰影寬度      params.width = (int) ((float) ConvertUtil.getWidthInPx() * 0.05f);      params.height = ConvertUtil.getHeightInPx();      shadowView.setLayoutParams(params);      //漸變背景作為陰影      shadowView.setBackgroundResource(R.drawable.shadow_grey_h);      shadowView.setTranslationX(-params.width);      rootView = rootGroup.getChildAt(1);    }  }  @Override  public boolean dispatchTouchEvent(MotionEvent ev) {    if (shouldIntercept) {      return onTouchEvent(ev);    }    switch (ev.getAction()) {      case MotionEvent.ACTION_DOWN: {        downX = ev.getRawX();        downY = ev.getRawY();        hadJudge = false;        break;      }      case MotionEvent.ACTION_MOVE: {        if (hadJudge) break;        if (ev.getRawX() == downX) break;        if (ev.getRawX() < downX) {          //左滑          hadJudge = true;          break;        }        if (ev.getRawX() - downX >= 100) {          //超出判斷距離          hadJudge = true;          break;        }        if (ev.getRawX() - downX > 50) {          //x軸右滑50~100px          float rate = (ev.getRawX() - downX) / (Math.abs(ev.getRawY() - downY));          if ((downX < 50 && rate > 0.5f) || rate > 2) {            shouldIntercept = true;          }        }        break;      }      case MotionEvent.ACTION_UP: {        downX = 0;        downY = 0;        shouldIntercept = false;        hadJudge = false;        break;      }    }    //Activity的默認分發    if (ev.getAction() == MotionEvent.ACTION_DOWN) {      onUserInteraction();    }    if (getWindow().superDispatchTouchEvent(ev)) {      return true;    }    return true;  }  @Override  public boolean onTouchEvent(MotionEvent event) {    initShadow();    //測量手指抬起時的速度    if (velocityTracker == null) {      velocityTracker = VelocityTracker.obtain();      maxFlingVelocity = ViewConfiguration.get(this).getScaledMaximumFlingVelocity();    }    velocityTracker.addMovement(event);    switch (event.getAction()) {      case MotionEvent.ACTION_DOWN: {        lastX = event.getRawX();        break;      }      case MotionEvent.ACTION_MOVE: {        if (lastX == -1) {          lastX = event.getRawX();          break;        }        //根據手指滑動距離設置根布局偏移距離        rootView.setTranslationX(rootView.getTranslationX() + event.getRawX() - lastX);        if (rootView.getTranslationX() < 0) rootView.setTranslationX(0);        //陰影跟隨根布局移動        shadowView.setTranslationX(-shadowView.getWidth() + rootView.getTranslationX());        //下層activity跟隨移動        if (lastActivity != null && lastActivity.rootView != null)          lastActivity.rootView.setTranslationX(-ConvertUtil.getWidthInPx() * 0.3f + rootView.getTranslationX() * 0.3f);        lastX = event.getRawX();        break;      }      case MotionEvent.ACTION_UP: {        //測量手指抬起時的速度        velocityTracker.computeCurrentVelocity(1000, maxFlingVelocity);        float velocityX = velocityTracker.getXVelocity();        if (velocityTracker != null) {          velocityTracker.recycle();          velocityTracker = null;        }        //判斷是否返回        if (downX < 50 && velocityX > 1000) {          //手指在左側邊落下,返回          onBack();        } else if (velocityX > 3600) {          //手指快速滑動,返回          onBack();        } else if (rootView.getTranslationX() > ConvertUtil.getWidthInPx() * 0.3) {          //滑動距離超過30%屏幕寬度,返回          onBack();        } else {          //不返回,根布局偏移歸零          rootView.animate().translationX(0).setDuration(200).start();          //陰影偏移歸零          shadowView.animate().translationX(-shadowView.getWidth()).setDuration(200).start();          //下層activity偏移復原          if (lastActivity != null) lastActivity.lowerActivityExitAnim();        }        lastX = -1;        shouldIntercept = false;        hadJudge = false;        downX = 0;        downY = 0;        break;      }    }    return super.onTouchEvent(event);  }    private void lowerActivityExitAnim() {    if (rootView == null) return;    rootView.animate().translationX(-ConvertUtil.getWidthInPx() * 0.3f).setDuration(300).start();  }  private void lowerActivityEnterAnim(float upperTranslationX) {    if (rootView == null) return;    float r = 1-upperTranslationX/ (float) ConvertUtil.getWidthInPx();    rootView.animate().translationX(0).setDuration(r == 0.0f ? 10 : (long) (300f * r)).start();  }  //退出  abstract public void onBack();}

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


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 德格县| 高淳县| 大竹县| 扬中市| 宝丰县| 新干县| 内丘县| 秭归县| 宜州市| 当雄县| 西吉县| 秦安县| 商南县| 万荣县| 托克逊县| 沅江市| 郴州市| 沧源| 永清县| 玛曲县| 马龙县| 六枝特区| 邯郸县| 黄梅县| 甘孜县| 怀柔区| 濉溪县| 济宁市| 上思县| 苍溪县| 九龙县| 荆州市| 铁岭市| 丰城市| 临江市| 元江| 麦盖提县| 松阳县| 衢州市| 年辖:市辖区| 竹北市|