Android 원형 회전 메뉴 개발 실례

최근 에 친 구 를 도와 애니메이션 메뉴 를 만 들 었 는데 실 용적 인 가치 가 있 는 것 같 습 니 다.여기 서 공유 해 드 리 겠 습 니 다.먼저 효 과 를 보 겠 습 니 다.

실현 방향:
그림 에서 알 수 있 듯 이 이 세 가지(또는 더 많 으 면 자신 이 다시 실현 해 야 한다)메뉴 는 중심 점 을 중심 으로 회전 하고 회전 은 2 층 으로 나 뉘 며 배경 회전 과 메뉴 회전,배경 회전 은 직접 회전 애니메이션 으로 이 루어 질 수 있다.메뉴 의 회전 은 중심 점 을 원심 으로 하 는 링 에 있 기 때문에 회전 각도 에 따라 이 점 이 직각 좌표계 에 있 는 좌표 점 을 구 하 는 함수(x=r*cos(rotation*3.14/180)와 y=r*sin(rotation*3.14/180)을 사용 한 다음 에 얻 은 점 의 위치 에 따라 메뉴 의 위 치 를 설정 하면 이러한 효 과 를 실현 할 수 있다.수학 이 중요 하 다 는 걸 알 수 있 습 니 다.하하~
생각 이 있 으 면 우 리 는 코드 로 실현 할 수 있다.
1.우선 사용자 정의 View 계승 상대 레이아웃 및 구조 함수 재 작성

/** 
 * Created by ywl on 2016/8/7. 
 */ 
public class CircleMenuLayout extends RelativeLayout { 
  public CircleMenuLayout(Context context) { 
    this(context, null); 
  } 
  public CircleMenuLayout(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
  } 
  /** 
   *                     
   * @param context 
   * @param attrs 
   * @param defStyleAttr 
   */ 
  public CircleMenuLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    this.context = context; 
    layoutInflater = LayoutInflater.from(context); 
    menuitems = new ArrayList<View>(); 
    centerview = new View(context);//    
    centerview.setId(ID_CENTER_VIEW); 
    LayoutParams lp = new LayoutParams(0, 0); 
    lp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); 
    addView(centerview, lp); //             
    progressBar = new ProgressBar(context);//      
    LayoutParams lp2 = new LayoutParams(dip2px(context, 90), dip2px(context, 90)); 
    lp2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); 
    addView(progressBar, lp2); 
    progressBar.setIndeterminateDrawable(context.getResources().getDrawable(R.mipmap.icon_circle_menu)); 
  } 
} 
구조 함수 에 중심 포 지 셔 닝 점 과 회전 배경 그림 을 추가 하고 적당 한 크기 를 설정 합 니 다.
2.들 어 오 는 그림 배열 과 메뉴 이름 배열 에 따라 메뉴 의 원래 위치 효 과 를 생 성 합 니 다.

/** 
   *                       3        
   * @param size 
   * @param center_distance 
   */ 
  public void initMenuItem(int size, int center_distance, String[] titles, int[] imgs) 
  { 
    radus = 360f / size; 
    int width = dip2px(context, 50); //     
    int height = dip2px(context, 50);//     
    for(int i = 0; i < size; i++) //       
    { 
      int top = 0; 
      int left = 0; 
      top = -(int)(Math.sin(radus * i * 3.1415f / 180) * center_distance); //r  *  cos(ao  *  3.14  /180  ) 
      left = -(int)(Math.cos(radus * i * 3.1415f / 180) * center_distance); //      
      LayoutParams lp = new LayoutParams(dip2px(context, 50), dip2px(context, 50)); 
      View view = layoutInflater.inflate(R.layout.item_circle_menu, this, false); 
      view.setTag(i); 
      TextView tvname = (TextView) view.findViewById(R.id.tv_name); 
      ImageView ivimg = (ImageView) view.findViewById(R.id.img); 
      tvname.setText(titles[i]); 
      ivimg.setImageResource(imgs[i]); 
      view.setOnClickListener(new OnClickListener() { 
        @Override 
        public void onClick(View v) {//             
          if(!isrun) { 
            tag = (int) v.getTag(); 
            currentPosition = tag; 
            if(tag == 0) 
            { 
              finishdus = -360; 
            } 
            else if(tag == 1) 
            { 
              finishdus = -120; 
            } 
            else if(tag == 2) 
            { 
              finishdus = -240; 
            } 
            LayoutParams lp = (LayoutParams) v.getLayoutParams(); 
            int l = lp.leftMargin; 
            int t = lp.topMargin; 
            if (t > -dip2px(context, 5) && l > -dip2px(context, 5)) { 
              oldradus = 120f; 
              isright = false; 
            } else if (t > -dip2px(context, 5) && l < -dip2px(context, 5)) { 
              oldradus = 120f; 
              isright = true; 
            } else if (t < -dip2px(context, 5)) { 
              oldradus = 0f; 
            } 
            sub = 0; 
            circleMenu(8, dip2px(context, 45), oldradus, isright); 
          } 
        } 
      }); 
      lp.addRule(RelativeLayout.BELOW, centerview.getId()); 
      lp.addRule(RelativeLayout.RIGHT_OF, centerview.getId()); 
      lp.setMargins(-width / 2 + top, -height / 2 + left, 0, 0); 
      addView(view, lp); 
      menuitems.add(view); 
    } 
    handler.postDelayed(runnable, 0); 
  } 
메뉴 의 수량 순환 에 따라 각 메뉴 의 위 치 를 계산 한 다음 해당 위치 에 해당 하 는 메뉴 를 추가 하면 메뉴 의 초기 화 를 실현 할 수 있 습 니 다.메뉴 마다 클릭 이 벤트 를 추 가 했 지만 3 개의 메뉴 만 적 용 된 경우,다른 수량의 메뉴 는 스스로 고치 거나 일반적인 방법 으로 클릭 위 치 를 계산 할 수 있 습 니 다.
3.배경 회전 애니메이션:

/** 
  *                                 
  * @param offserradius 
  * @param center_distance 
  * @param d 
  * @param right 
  */ 
  public void circleMenu(float offserradius, int center_distance, float d, boolean right) 
  { 
  if(oldradus != 0) 
  { 
    progressBar.clearAnimation(); 
    if(isright) 
    { 
      mRotateUpAnim = new RotateAnimation(bgdus, bgdus + 120, 
          Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 
          0.5f); 
      bgdus += 120; 
    } 
    else 
    { 
      mRotateUpAnim = new RotateAnimation(bgdus, bgdus - 120, 
          Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 
          0.5f); 
      bgdus -= 120; 
    } 
    lir = new LinearInterpolator(); 
    mRotateUpAnim.setDuration(350); 
    mRotateUpAnim.setFillAfter(true); 
    mRotateUpAnim.setInterpolator(lir); 
//    mRotateUpAnim.setRepeatCount(Animation.INFINITE); 
    progressBar.startAnimation(mRotateUpAnim); 
  } 
    circleMenuItem(offserradius, center_distance, d, right); 
  } 
이것 은 회전 각도 에 따라 회전 애니메이션 을 사용 하 는 것 이 간단 합 니 다.
4.회전 메뉴:

/** 
   *      
   * @param offserradius 
   * @param center_distance 
   * @param d 
   * @param right 
   */ 
  public void circleMenuItem(float offserradius, int center_distance, float d, boolean right) 
  { 
    sub += offserradius; 
    if(sub > d) 
    { 
      if(onMenuItemSelectedListener != null) 
      { 
        onMenuItemSelectedListener.onMenuItemOnclick(tag); 
      } 
      isrun = false; 
      return; 
    } 
    if(right) { 
      offsetradus -= offserradius; 
    } 
    else 
    { 
      offsetradus += offserradius; 
    } 
    int size = menuitems.size(); 
    int width = dip2px(context, 50); 
    int height = dip2px(context, 50); 
    for(int i = 0; i < size; i++) 
    { 
      if(Math.abs(sub - d) <= 8) 
      { 
        offsetradus = finishdus; 
      } 
      LayoutParams lp = (LayoutParams) menuitems.get(i).getLayoutParams(); 
      float ds = radus * i + offsetradus; 
      int top = -(int)(Math.sin(ds * 3.1415f / 180) * center_distance); //r  *  cos(ao  *  3.14  /180  ) 
      int left = -(int)(Math.cos(ds * 3.1415f / 180) * center_distance); 
      lp.setMargins(-width / 2 + top, -height / 2 + left, 0, 0); 
      menuitems.get(i).requestLayout(); 
    } 
    if(sub <= d) { 
      isrun = true; 
      offsetradus = offsetradus % 360; 
      handler.postDelayed(runnable, 5); 
    } 
    else 
    { 
      if(onMenuItemSelectedListener != null) 
      { 
        onMenuItemSelectedListener.onMenuItemOnclick(tag); 
      } 
      isrun = false; 
    } 
  } 
여기 서 회전 은 초기 화 할 때 모든 메뉴 가 있 는 위치 에 따라 회전 각 도 를 구 한 다음 에 handler 를 시작 하여 점차적으로 증가 하거나 감소 하 는 각도 로 응답 하 는 위 치 를 구하 면 애니메이션 효 과 를 실현 합 니 다.
5.메뉴 항목 을 수 동 으로 설정 합 니 다(제한 이 있 고 유 니 버 설 이 없습니다).

/** 
   *            
   * @param tag 
   */ 
  public void setCurrentTag(int tag) 
  { 
    if(currentPosition == tag) 
    { 
      return; 
    } 
    if(tag == 0) 
    { 
      finishdus = -360; 
    } 
    else if(tag == 1) 
    { 
      finishdus = -120; 
    } 
    else if(tag == 2) 
    { 
      finishdus = -240; 
    } 
    if(currentPosition == 0) //   0 
    { 
      if(tag == 1) 
      { 
        oldradus = 120f; 
        isright = true; 
      } 
      else if(tag == 2) 
      { 
        oldradus = 120f; 
        isright = false; 
      } 
    } 
    else if(currentPosition == 1) 
    { 
      if(tag == 2) 
      { 
        oldradus = 120f; 
        isright = true; 
      } 
      else if(tag == 0) 
      { 
        oldradus = 120f; 
        isright = false; 
      } 
    } 
    else if(currentPosition == 2) 
    { 
      if(tag == 0) 
      { 
        oldradus = 120f; 
        isright = true; 
      } 
      else if(tag == 1) 
      { 
        oldradus = 120f; 
        isright = false; 
      } 
    } 
    currentPosition = tag; 
    this.tag = tag; 
    sub = 0; 
    circleMenu(8, dip2px(context, 45), oldradus, isright); 
  } 
이렇게 하면 회전 효 과 를 실현 할 수 있다.
6.호출 방법:
(1)레이아웃 파일:

<com.ywl5320.circlemenu.CircleMenuLayout 
    android:id="@+id/cml_menu" 
    android:layout_width="150dp" 
    android:layout_height="150dp" 
    android:layout_centerHorizontal="true" 
    android:layout_alignParentBottom="true" 
    android:layout_marginBottom="92dp"/> 
(2)메뉴 레이아웃 파일:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:orientation="vertical"  
  android:layout_width="100dp" 
  android:layout_height="100dp" 
  android:padding="5dp" 
  android:gravity="center"> 
  <ImageView 
    android:id="@+id/img" 
    android:layout_width="25dp" 
    android:layout_height="25dp" 
    android:scaleType="fitXY"/> 
  <TextView 
    android:id="@+id/tv_name" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="   " 
    android:textSize="9sp" 
    android:gravity="center" 
    android:textColor="#ffffff"/> 
</LinearLayout> 
(3)Activity 에서 호출

<span style="white-space:pre">  </span>cmlmenu = (CircleMenuLayout) findViewById(R.id.cml_menu); 
    btn = (Button) findViewById(R.id.btn); 
    cmlmenu.initDatas(titles, imgs); 
    cmlmenu.setOnMenuItemSelectedListener(new CircleMenuLayout.OnMenuItemSelectedListener() { 
      @Override 
      public void onMenuItemOnclick(int code) { 
        if(code == 0)// 
        { 
          Toast.makeText(MainActivity.this, "   ", Toast.LENGTH_SHORT).show(); 
        } 
        else if(code == 1) 
        { 
          Toast.makeText(MainActivity.this, "  ", Toast.LENGTH_SHORT).show(); 
        } 
        else if(code == 2) 
        { 
          Toast.makeText(MainActivity.this, "  ", Toast.LENGTH_SHORT).show(); 
        } 
      } 
    }); 
OK.세 개의 메뉴 회전 효 과 를 완 성 했 습 니 다.
위 에서 말 한 것 은 소 편 이 소개 한 안 드 로 이 드 원형 회전 메뉴 개발 사례 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 메 시 지 를 남 겨 주세요.소 편 은 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기