91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

android 右滑返回的示例代碼

發布時間:2020-08-25 10:16:14 來源:腳本之家 閱讀:138 作者:沉寂chenji 欄目:移動開發

類似于微信的右滑返回,在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跳轉和銷毀方法

@Override
public void startActivity(Intent intent) {
  super.startActivity(intent);
  overridePendingTransition(R.anim.slide_right_in, 0);
}

@Override
public void startActivityForResult(Intent intent, int requestCode) {
  super.startActivityForResult(intent, requestCode);
  overridePendingTransition(R.anim.slide_right_in, 0);
}

@Override
public 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;

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

根布局位移動畫

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

private View rootView = null;
private float lastX = -1;  
private VelocityTracker velocityTracker = null;
private int maxFlingVelocity;


@Override
public 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;
@Override
public 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;

@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 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的退出、進入動畫

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

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

@Override
public 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();
}

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东阳市| 柳州市| 武功县| 东乡县| 泸溪县| 南丹县| 娱乐| 正定县| 乌兰察布市| 安远县| 铁岭市| 武义县| 黑水县| 蚌埠市| 晋城| 县级市| 贡嘎县| 阿鲁科尔沁旗| 阳原县| 拉孜县| 辽宁省| 宜章县| 洛扎县| 乌鲁木齐县| 威信县| 合阳县| 通榆县| 洪泽县| 寻乌县| 宿松县| 松阳县| 潞城市| 都安| 昭通市| 绥阳县| 江津市| 岑溪市| 金门县| 元朗区| 巨野县| 蓬安县|