Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 自定義左下角弧形旋轉菜單欄

自定義左下角弧形旋轉菜單欄

編輯:關於Android編程

要做這種效果

1- 整個自定義控件其實就是一個ArcMenu .(半圓形那一圈),左下角的圖標沒有加入進控件中。
 

2- 我基於他的類改了點。

  • 他是將左下角的關閉icon都加入到整個自定義menu的layout中的,我是獨立出來

  • 我menu中的item添加的思路是首先都給它固定在界面的最左邊,往屏幕左邊外面便宜半個item的寬度。然後在draw時,將每一個item的位置根據自身的角度,設置rotate值,不但外面要rotate到item本身應該所在的位置(pivot要設置為左下角為原點),它自身也得根據偏移的角度rotate到一個正確的向上的角度。其實在初始化時都給它們偏移過了。

    3- 當然現在6.0、7.0上的那些自帶效果比我這漂亮多了,不過為了完成設計師給的設計稿,不得不這樣寫。所以輕噴。

    4- 下面po上實現步驟。

    a,自定義一個類ArcMenu繼承自FrameLayout.重載三個構造方法。

     

    public class ArcMenu extends FrameLayout {
    public ArcMenu(Context context) {super(context);}
    public ArcMenu(Context context, AttributeSet attrs) {super(context, attrs);}
    
    
    b,重寫 onSizeChanged方法,確定控件的高寬,並初始化控件中的一些參數
    
     
    
    
    
    
    
    private void init() { if (!isInEditMode()) { for (int i = 0; i < ICON_COUNT; i++) {
    	   //初始化默認和點擊的圖片bitmap
                m_iconGrayBitmaps[i] = DrawableManager.instance().getAssetBitmap(s_iconNamePrefixes[i] + "_gray.png");
                m_iconWhiteBitmaps[i] = DrawableManager.instance().getAssetBitmap(s_iconNamePrefixes[i] + "_white.png");
    //       m_tangent[i] = Math.tan(90.0f / ICON_COUNT * i);
             }
          }
          m_arcWidth = m_height / 4;//弧形的寬度
    //    m_itemIndex = 0;
          m_startDegree = 90.0f / ICON_COUNT / 2; //第一個item初始化時應該待的位置的偏移角度
          m_stepDegree = 90.0f / ICON_COUNT;  //每一個item相對前一個item所偏移的角度
    
    
          //新建一個矩形,中心點為左下角
          m_arcRect = new RectF(-(m_width - m_arcWidth / 2), m_arcWidth / 2,
                m_width - m_arcWidth / 2, 2 * m_height - m_arcWidth / 2);
    
          int shadow_arc_width = Utils.dp2px(SHADOW_ARC_WIDTH);
          m_arcShadow = new RectF(-(m_width - m_arcWidth - shadow_arc_width / 2), m_arcWidth + shadow_arc_width / 2,
                (m_width - m_arcWidth - shadow_arc_width / 2), 2 * m_height - m_arcWidth - shadow_arc_width / 2);
    
          m_arcbgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
          m_arcbgPaint.setStyle(Paint.Style.STROKE);
          m_arcbgPaint.setStrokeWidth(m_arcWidth);
          m_arcbgPaint.setColor(getResources().getColor(R.color.bg_menu_arc));
          m_arcfgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
          m_arcfgPaint.setStyle(Paint.Style.STROKE);
          m_arcfgPaint.setStrokeWidth(m_arcWidth);
          m_arcfgPaint.setColor(getResources().getColor(R.color.fg_menu_arc));
          m_shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
          m_shadowPaint.setStyle(Paint.Style.STROKE);
          m_shadowPaint.setStrokeWidth(shadow_arc_width);
          m_shadowPaint.setColor(getResources().getColor(R.color.default_black));
    
          setOnTouchListener(new OnTouchListener() {
             @Override
             public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                   int index = pointInArc(event.getX(), event.getY());
                   if (index >= 0) {
                      Logger.debug("click on icon " + index);
                      m_itemIndex = index;
                      invalidate();
                      m_itemClickedListener.onMenuItemClicked(index);
                      return true;
                   }
                }
                return false;
             }
          });
       }
    
    
    上面圖畫錯了。。綠色框其實就是外面的m_arcRect
    shadowArc其實是 那一層黑色的arc..我懶得再畫了。。
    
    
    接下來就是畫圖了。把那些item要畫上去,還得畫上這兩層弧形
    用到dipatchDraw
    
    
    @Override protected void dispatchDraw(Canvas canvas) { Path path = new Path();  /// draw out arc  path.arcTo(m_arcRect, 270.0f, 90.0f);  canvas.drawPath(path, m_arcbgPaint);   canvas.drawArc(m_arcRect, 270.0f + m_stepDegree * m_itemIndex, m_stepDegree, false, m_arcfgPaint);  /// draw shadow arc  canvas.drawArc(m_arcShadow, 270.0f, 90.0f, false, m_shadowPaint);   /// draw bitmaps  for (int i = 0; i < ICON_COUNT; i++) { Bitmap bitmap;  if (i == m_itemIndex) { /// selected icon  bitmap = m_iconWhiteBitmaps[i];  } else { /// not selected  bitmap = m_iconGrayBitmaps[i];  } if (bitmap != null) { Matrix matrix = new Matrix();  matrix.postTranslate(-bitmap.getWidth() / 2, (m_arcWidth - bitmap.getHeight()) / 2);  matrix.postRotate(-m_startDegree - m_stepDegree * i, 0, m_arcWidth / 2);  matrix.postRotate(m_startDegree + m_stepDegree * i, 0, m_height);  canvas.drawBitmap(bitmap, matrix, null);  } } super.dispatchDraw(canvas); }

    
    
    寫到這裡不知道怎麼說了。。干脆貼代碼算了。
    
    
    /**  * check if point (x, y) is within arc icon  *  * @param x  * @param y  * @return index of the icon clicked, or -1  */ private int pointInArc(float x, float y) { float[] pts = {x, y};  float[] target_pts = new float[2];  Matrix matrix = new Matrix();  matrix.postRotate(-m_startDegree, 0, m_height);  for (int i = 0; i < ICON_COUNT; i++) { matrix.mapPoints(target_pts, pts);  if (pointInStartRectOfIcon(target_pts)) { return i;  } matrix.postRotate(-m_stepDegree, 0, m_height);  } return -1; } /**  * check if (target_pts[0], target_pts[1]) is in the start position of icons  *  * @param target_pts  * @return  */ private boolean pointInStartRectOfIcon(float[] target_pts) { return target_pts[0] > -m_arcWidth / 2 && target_pts[0] < m_arcWidth / 2  && target_pts[1] > 0 && target_pts[1] < m_arcWidth; }
    /**
     * Sets the click listener for menu items.
     */
    public void setOnItemClickedListener(ArcMenuItemClickedListener itemClickedListener) {
       this.m_itemClickedListener = itemClickedListener;
    }
    
    public void setSelectedIcon(int index, boolean bInvalidate) {
       m_itemIndex = index;
       if(bInvalidate) {
          invalidate();
       }
    }
    就醬吧。。。寫個博客煩球死。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved