안 드 로 이 드 오른쪽 미끄럼 반환 예제 코드

20393 단어 android우회전
위 챗 과 같은 오른쪽 슬라이딩 리 턴 은 BaseActivity 에서 dispatchTouchEvent()를 이용 해 오른쪽 슬라이딩 동작 을 차단 하고,setTranslationX()를 이용 해 애니메이션 을 구현 하 며,DecorView 에 View 를 슬라이딩 시 왼쪽 음영 으로 추가 합 니 다.

점진 적 단계:
  • 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),startActivity ForResult(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~100 px 오른쪽으로 미 끄 러 질 때(제품 매니저 가 원 하 는)오른쪽 미 끄 러 지 는 동작 인지 판단 합 니 다.
    4.567917.손가락 타 점 은 전체 화면 이 고 X 방향 미끄럼 거 리 는 Y 방향 보다 크다4.567917.손가락 타 점 은 왼쪽 이 고 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 은 제목 표시 줄 과 사용자 정의 레이아웃(set ContentView)을 포함 합 니 다.
    마지막 으로 손가락 이 미 끄 러 지 는 것 을 따라 이동 하 는 것 이 바로 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 가 미 끄 러 질 때 하층 미끄럼 을 호출 합 니 다
  • 하위 액 티 비 티 가 져 오기
    
    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();
    }
    
    
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기