Android 신축 탄력 분포 메뉴 효과 구현 예시

14168 단어 android메뉴
요 며칠 동안 본의 아니 게 한 원우 의 박문 이 Path 2.0 의 화려 한 회전 메뉴 를 실현 하 는 것 을 보 았 는데 효과 가 좋 았 지만 작가 가 스 레 드 안전 문 제 를 처리 하지 않 은 것 을 발 견 했 습 니 다.그래서 여기 서 제 가 수정 하고 다음 부분 기능 을 개선 하 겠 습 니 다.오늘 이 글 을 발표 한 목적 은 안 드 로 이 드 사용자 체험 에서 관련 해결 방안 을 제시 하여 우리 가 프로젝트 나 제품 을 개발 할 때 사용자 체험 효 과 를 강화 하 는 데 편리 하도록 하 는 것 입 니 다.물론 벽돌 을 던 져 옥 을 끌 어 올 리 는 역할 도 하고 싶 습 니 다.
=군말 이 많 지 않 은 지,낡은 규칙 인지,먼저 실현 의 효과 도 를 살 펴 보 자.

=위의 그림 에서 메뉴 팝 업 효 과 를 직선 형 으로 설정 하고 마지막 팝 업 이나 집합 점 은 아래 빨간색 단추 에 있 습 니 다.
그것 의 실현 원 리 는 애니메이션 을 설정 하 는 동시에 애니메이션 의 삽입 기(interpolator)를 이용 하여 탄력 을 실현 하 는 것 이다.주로 Overshoot Interpolator 와 Anticipate Overshoot Interpolator 를 사용 하여 이 두 개의 삽입 기 를 간단하게 소개 합 니 다.
  • Overshoot Interpolator:앞으로 일정 치 를 던 진 후에 원래 위치 로 돌아 가 겠 다 는 뜻 입 니 다
  • Anticipate Overshoot Interpolator:시작 할 때 뒤로 한 다음 에 일정한 값 을 앞으로 던 진 후에 마지막 값 을 되 돌려 줍 니 다
  • 4.567917.물론 다른 삽입 기 도 있 습 니 다.그 역할 을 간략하게 알 아 보 세 요.4.567918.
  • Anticipate Interpolator:시작 할 때 뒤로 젖 히 고 앞으로 떨 어 지 는 것 을 나타 낸다
  • BounceInterpolator:애니메이션 이 끝 날 때 팝 업 을 표시 합 니 다
  • Overshoot Interpolator:앞으로 일정 치 를 던 진 후에 원래 위치 로 돌아 가 겠 다 는 뜻 입 니 다
  • CycleInterpolator:애니메이션 순환 재생 의 특정한 횟수 를 나타 내 고 속 도 는 사인 곡선 을 따라 변 한다
  • DecelerateInterpolator:애니메이션 이 시작 되 는 곳 에서 빠 르 고 느 린 것 을 나타 낸다
  • Linear Interpolator:상수 속도 로 변 하 는 것 을 나타 낸다
  • 우 리 는 몇몇 예 시 를 통 해 이 몇 개의 삽입 기 에 대한 이 해 를 깊이 있 게 할 수 있다.API Demos 에 서 는 API Demos 의 Animation 부분 을 직접 연구 할 수 있 는 예제 가 있 습 니 다.
    먼저 MainActivity 의 코드 를 알 아 보 겠 습 니 다.다음 과 같 습 니 다.
    
    package com.spring.menu.activity;
    
    import com.spring.menu.R;
    import com.spring.menu.animation.SpringAnimation;
    import com.spring.menu.animation.EnlargeAnimationOut;
    import com.spring.menu.animation.ShrinkAnimationOut;
    import com.spring.menu.animation.ZoomAnimation;
    import com.spring.menu.utility.DeviceUtility;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.View.OnClickListener;
    import android.view.animation.Animation;
    import android.view.animation.AnimationUtils;
    import android.view.animation.AnticipateInterpolator;
    import android.widget.RelativeLayout;
    
    /**
     * Android            
     * @Description: Android            
    
     * @File: MainActivity.java
    
     * @Package com.spring.menu.activity
    
     * @Author Hanyonglu
    
     * @Date 2012-10-25   09:41:31
    
     * @Version V1.0
     */
    public class MainActivity extends Activity {
     private boolean areMenusShowing;
     private ViewGroup menusWrapper;
     private View imageViewPlus;
     private View shrinkRelativeLayout;
     private RelativeLayout layoutMain;
     //        
     private Animation animRotateClockwise;
     //        
     private Animation animRotateAntiClockwise;
     private Class<?>[] intentActivity = {
       SecondActivity.class,ThreeActivity.class,FourActivity.class,
       SecondActivity.class,ThreeActivity.class,FourActivity.class};
     private int[] mainResources = {
       R.drawable.bg_main_1,R.drawable.bg_main_2,
       R.drawable.bg_main_3,R.drawable.bg_main_4,
       R.drawable.bg_main_1,R.drawable.bg_main_4};
    
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main_activity);
      
      //    
      initViews();
     }
     
     //    
     private void initViews(){
      imageViewPlus = findViewById(R.id.imageview_plus);
      menusWrapper = (ViewGroup) findViewById(R.id.menus_wrapper);
      shrinkRelativeLayout = findViewById(R.id.relativelayout_shrink);
      layoutMain = (RelativeLayout) findViewById(R.id.layout_content);
      
      animRotateClockwise = AnimationUtils.loadAnimation(
        this,R.anim.rotate_clockwise);
      animRotateAntiClockwise = AnimationUtils.loadAnimation(
        this,R.anim.rotate_anticlockwise);
    
      shrinkRelativeLayout.setOnClickListener(new OnClickListener() {
    
       public void onClick(View v) {
        // TODO Auto-generated method stub
        showLinearMenus();
       }
      });
      
      for (int i = 0; i < menusWrapper.getChildCount(); i++) {
       menusWrapper.getChildAt(i).setOnClickListener(
         new SpringMenuLauncher(null,mainResources[i]));
      }
     }
    
     /**
      *         
      */
     private void showLinearMenus() {
      int[] size = DeviceUtility.getScreenSize(this);
      
      if (!areMenusShowing) {
       SpringAnimation.startAnimations(
         this.menusWrapper, ZoomAnimation.Direction.SHOW, size);
       this.imageViewPlus.startAnimation(this.animRotateClockwise);
      } else {
       SpringAnimation.startAnimations(
         this.menusWrapper, ZoomAnimation.Direction.HIDE, size);
       this.imageViewPlus.startAnimation(this.animRotateAntiClockwise);
      }
      
      areMenusShowing = !areMenusShowing;
     }
    
     //          
     private class SpringMenuLauncher implements OnClickListener {
      private final Class<?> cls;
      private int resource;
    
      private SpringMenuLauncher(Class<?> c,int resource) {
       this.cls = c;
       this.resource = resource;
      }
    
      public void onClick(View v) {
       // TODO Auto-generated method stub
       MainActivity.this.startSpringMenuAnimations(v);
       layoutMain.setBackgroundResource(resource);
       
    //   MainActivity.this.startActivity(
    //     new Intent(
    //       MainActivity.this,
    //       MainActivity.SpringMenuLauncher.this.cls));
      }
     }
    
     /**
      *         
      * @param view
      * @param runnable
      */
     private void startSpringMenuAnimations(View view) {
      areMenusShowing = true;
      Animation shrinkOut1 = new ShrinkAnimationOut(300);
      Animation growOut = new EnlargeAnimationOut(300);
      shrinkOut1.setInterpolator(new AnticipateInterpolator(2.0F));
      shrinkOut1.setAnimationListener(new Animation.AnimationListener() {
    
       public void onAnimationEnd(Animation animation) {
        // TODO Auto-generated method stub
        MainActivity.this.imageViewPlus.clearAnimation();
       }
    
       public void onAnimationRepeat(Animation animation) {
        // TODO Auto-generated method stub
        
       }
    
       public void onAnimationStart(Animation animation) {
        // TODO Auto-generated method stub
        
       }
      });
      
      view.startAnimation(growOut);
     }
    }
    
    
    빨간색 단 추 를 눌 렀 을 때 맨 위 에 있 는 메뉴 를 팝 업 하고 어떤 메뉴 를 눌 렀 을 때 위의 배경 그림 을 바 꾸 면 물론 특정한 Activity 에 직접 들 어 갈 수 있 습 니 다.그래서 위 에서 intent Activity 와 mainrources 두 개의 배열 을 정 의 했 는데 각각 전환 할 Activity 와 변환 할 그림 을 대표 합 니 다.여러분 은 실제 수요 에 따라 설정 할 수 있 습 니 다.빨간색 단 추 를 눌 렀 을 때 중간 에 있 는 플러스 번 호 를 오른쪽으로 225 도 회전 시 켜 포크 번호 로 바 꾸 고 다음 과 같은 애니메이션 을 통 해:
    
    <?xml version="1.0" encoding="UTF-8"?>
    <rotate
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:interpolator="@android:anim/linear_interpolator"
     android:duration="200"
     android:fromDegrees="0.0"
     android:toDegrees="225.0"
     android:pivotX="50.0%"
     android:pivotY="50.0%"
     android:fillAfter="true"
     android:fillEnabled="true"/>
    
    다시 클릭 하면 왼쪽으로 회전 하여 복원 합 니 다.위의 android:from Degrees 와 android:toDegrees 를 교체 하면 됩 니 다.
    다음 중요 한 애니메이션 유형 은 SpringAnimation 입 니 다.각 메뉴 의 애니메이션 효 과 를 제어 합 니 다.코드 는 다음 과 같 습 니 다.
    
    package com.spring.menu.animation;
    
    import com.spring.menu.control.ImageButtonExtend;
    
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.ViewGroup.MarginLayoutParams;
    import android.view.animation.AnticipateInterpolator;
    import android.view.animation.AnticipateOvershootInterpolator;
    import android.view.animation.OvershootInterpolator;
    import android.view.animation.TranslateAnimation;
    
    /**
     *            
     * @Description:            
    
     * @File: SpringAnimation.java
    
     * @Package com.spring.menu.animation
    
     * @Author Hanyonglu
    
     * @Date 2012-10-25   12:18:39
    
     * @Version V1.0
     */
    public class SpringAnimation extends ZoomAnimation {
     private static int[] size;
     private static int xOffset = 210;
     private static int yOffset = -15;
     public static final int DURATION = 300;
     
     /**
      *    
      * @param direction
      * @param duration
      * @param view
      */
     public SpringAnimation(Direction direction, long duration, View view) {
      super(direction, duration, new View[] { view });
      SpringAnimation.xOffset = SpringAnimation.size[0] / 2 - 30;
     }
    
     /**
      *         
      * @param viewgroup
      * @param direction
      * @param size
      */
     public static void startAnimations(ViewGroup viewgroup,
       ZoomAnimation.Direction direction, int[] size) {
      SpringAnimation.size = size;
      
      switch (direction) {
      case HIDE:
       startShrinkAnimations(viewgroup);
       break;
      case SHOW:
       startEnlargeAnimations(viewgroup);
       break;
      }
     }
    
     /**
      *       
      * @param viewgroup
      */
     private static void startEnlargeAnimations(ViewGroup viewgroup) {
      for (int i = 0; i < viewgroup.getChildCount(); i++) {
       if (viewgroup.getChildAt(i) instanceof ImageButtonExtend) {
        ImageButtonExtend inoutimagebutton = (ImageButtonExtend) viewgroup
          .getChildAt(i);
        SpringAnimation animation = new SpringAnimation(
          ZoomAnimation.Direction.HIDE, DURATION, inoutimagebutton);
        animation.setStartOffset((i * 200)
          / (-1 + viewgroup.getChildCount()));
        animation.setInterpolator(new OvershootInterpolator(4F));
        inoutimagebutton.startAnimation(animation);
       }
      }
     }
    
     /**
      *       
      * @param viewgroup
      */
     private static void startShrinkAnimations(ViewGroup viewgroup) {
      for (int i = 0; i < viewgroup.getChildCount(); i++) {
       if (viewgroup.getChildAt(i) instanceof ImageButtonExtend) {
        ImageButtonExtend inoutimagebutton = (ImageButtonExtend) viewgroup
          .getChildAt(i);
        SpringAnimation animation = new SpringAnimation(
          ZoomAnimation.Direction.SHOW, DURATION,
          inoutimagebutton);
        animation.setStartOffset((100 * ((-1 + viewgroup
          .getChildCount()) - i))
          / (-1 + viewgroup.getChildCount()));
        animation.setInterpolator(new AnticipateOvershootInterpolator(2F));
        inoutimagebutton.startAnimation(animation);
       }
      }
     }
    
     @Override
     protected void addShrinkAnimation(View[] views) {
      // TODO Auto-generated method stub
      MarginLayoutParams mlp = (MarginLayoutParams) views[0].
        getLayoutParams();
      addAnimation(new TranslateAnimation(
        xOffset + -mlp.leftMargin, 
        0F,yOffset + mlp.bottomMargin, 0F));
     }
    
     @Override
     protected void addEnlargeAnimation(View[] views) {
      // TODO Auto-generated method stub
      MarginLayoutParams mlp = (MarginLayoutParams) views[0].
        getLayoutParams();
      addAnimation(new TranslateAnimation(
        0F, xOffset + -mlp.leftMargin, 
        0F,yOffset + mlp.bottomMargin));
     }
    }
    
    
    이 종 류 는 ZoomAnimation 에서 계승 합 니 다.ZoomAnimation 코드 는 다음 과 같 습 니 다.
    
    package com.spring.menu.animation;
    
    import android.view.View;
    import android.view.animation.AnimationSet;
    
    /**
     *        
     * @Description:        
    
     * @File: ZoomAnimation.java
    
     * @Package com.spring.menu.animation
    
     * @Author Hanyonglu
    
     * @Date 2012-10-25   11:37:52
    
     * @Version V1.0
     */
    public abstract class ZoomAnimation extends AnimationSet {
     public Direction direction;
    
     public enum Direction {
      HIDE, SHOW;
     }
    
     public ZoomAnimation(Direction direction, long duration, View[] views) {
      super(true);
      this.direction = direction;
      
      switch (this.direction) {
      case HIDE:
       addShrinkAnimation(views);
       break;
      case SHOW:
       addEnlargeAnimation(views);
       break;
      }
      
      setDuration(duration);
     }
    
     protected abstract void addShrinkAnimation(View[] views);
     
     protected abstract void addEnlargeAnimation(View[] views);
    }
    
    
    때때로 우 리 는 사용자 체험 을 강화 하기 위해 직선 을 반원형 이나 반원형 으로 설정 할 수 있 으 며,Bresenham 알고리즘 이나 다른 방안 을 이용 하여 반원 이나 반원 의 메뉴 를 만 들 수 있 으 며,메뉴 를 간단하게 어 딘 가 에 위치 시 키 는 것 이 아 닙 니 다.이것 에 대해 관심 이 있 는 친 구 는 관련 자 료 를 참고 하여 그것 을 실현 할 수 있다.
     또한 위의 예 는 동적 설정 메뉴 의 개 수 를 실현 하지 않 았 다.개인 적 으로 메뉴 의 레이아웃 을 동적 으로 설정 하 는 것 이 좋 습 니 다.메뉴 를 추가 하거나 줄 일 때 편리 합 니 다.일반적인 과정 은 하나의 배열(그림 자원 대표)을 이용 하여 배열 에 따라 구 조 를 실현 하 는 것 이다.상단 에서 언급 한 반원형 전개 실현 도 동적 으로 설정 해 야 한다.원래 나 는 그것 을 실현 하고 싶 었 지만,정말 그렇게 많은 시간 이 없 었 다.필요 한 친구 가 프로그램 을 채 울 수 있 는 SpringMenu Layout 류 가 있 었 다.여기 서 나 는 그것 을 실현 하지 않 았 다.
    
    package com.spring.menu.layout;
    
    /**
     *              
     * @Description:              
    
     * @File: SpringMenuLayout.java
    
     * @Package com.spring.menu.layout
    
     * @Author Hanyonglu
    
     * @Date 2012-10-26   07:57:56
    
     * @Version V1.0
     */
    public class SpringMenuLayout {
     //          
     
     //          
    } 
    
    
    이상 은 안 드 로 이 드 에서 신축 탄력 분포 메뉴 효 과 를 실현 하 는 과정 입 니 다.

    좋은 웹페이지 즐겨찾기