<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android自定義實(shí)現(xiàn)六邊形按鈕繪制

          共 2857字,需瀏覽 6分鐘

           ·

          2021-11-14 00:35

          今天逛酷安的時(shí)候,發(fā)現(xiàn)酷安的設(shè)置按鈕(截圖的右上角),是一個(gè)六邊形 + 中心圓的圖標(biāo),所以又是一個(gè)自定義View練習(xí)對(duì)象了。畫圓很簡(jiǎn)單,知道半徑即可,而重點(diǎn)就在畫出六邊形。



          最終效果:


          原理:

          1、中心畫一個(gè)小圓

          2、再畫一個(gè)六邊形(難點(diǎn))


          怎樣才能畫六邊形,?只要我們計(jì)算出6個(gè)角的坐標(biāo)點(diǎn),用Path連接即可。至于怎么計(jì)算,就要使用三角函數(shù)。我們這樣分析:


          在六邊形中心畫一個(gè)內(nèi)切圓,6個(gè)角都在圓上。360被六邊形的6個(gè)角平分,每個(gè)角就為60度,而每個(gè)角的2條腰的長(zhǎng)都是圓的半徑。如下圖所示:


          至于三角函數(shù),可能我們會(huì)忘記,我們對(duì)著這張圖解圖來(lái)回憶一下。


          只要我們計(jì)算出中心角的角度,用三角函數(shù)中的cos()就可以計(jì)算出點(diǎn)的x坐標(biāo),sin()就可以計(jì)算出y坐標(biāo)(注意這個(gè)2個(gè)方法傳入的角度需要轉(zhuǎn)為弧度)。重點(diǎn)計(jì)算代碼在drawPolygon()方法。


          完整代碼:


          自定義屬性

                                  


          Java代碼

          public class PolygonSettingView extends View {    /**     * View默認(rèn)最小寬度     */    private static final int DEFAULT_MIN_WIDTH = 100;    /**     * 畫筆     */    private Paint mPaint;    /**     * 控件寬     */    private int mViewWidth;    /**     * 控件高     */    private int mViewHeight;
          /** * 多邊形的邊數(shù) */ private int mNum; /** * 最小的多邊形的半徑 */ private float mRadius; /** * 360度對(duì)應(yīng)的弧度(為什么2π就是360度?弧度的定義:弧長(zhǎng) / 半徑,一個(gè)圓的周長(zhǎng)是2πr,如果是一個(gè)360度的圓,它的弧長(zhǎng)就是2πr,如果這個(gè)圓的半徑r長(zhǎng)度為1,那么它的弧度就是,2πr / r = 2π) */ private final double mPiDouble = 2 * Math.PI; /** * 多邊形中心角的角度(每個(gè)多邊形的內(nèi)角和為360度,一個(gè)多邊形2個(gè)相鄰角頂點(diǎn)和中心的連線所組成的角為中心角 * 中心角的角度都是一樣的,所以360度除以多邊形的邊數(shù),就是一個(gè)中心角的角度),這里注意,因?yàn)楹罄m(xù)要用到Math類的三角函數(shù) * Math類的sin和cos需要傳入的角度值是弧度制,所以這里的中心角的角度,也是弧度制的弧度 */ private float mCenterAngle; /** * 顏色 */ private int mColor; /** * 中心小圓的半徑 */ private float mSmallCircleRadius; /** * 線寬 */ private float mLineWidth;
          public PolygonSettingView(Context context) { this(context, null); }
          public PolygonSettingView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); }
          public PolygonSettingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs, defStyleAttr); }
          private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { initAttr(context, attrs, defStyleAttr); //取消硬件加速 setLayerType(LAYER_TYPE_SOFTWARE, null); //畫筆 mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(mColor); mPaint.setStrokeWidth(mLineWidth); }
          private void initAttr(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { //默認(rèn)邊數(shù)和最小邊數(shù) int defaultNum = 6; int minNum = 3; int defaultColor = Color.argb(255, 0, 0, 0); int defaultLineWidth = dip2px(context, 1.5f); if (attrs != null) { TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PolygonSettingView, defStyleAttr, 0); mColor = array.getColor(R.styleable.PolygonSettingView_psv_color, defaultColor); int num = array.getInt(R.styleable.PolygonSettingView_psv_num, defaultNum); mNum = num <= minNum ? minNum : num; mLineWidth = array.getDimension(R.styleable.PolygonSettingView_psv_line_width, defaultLineWidth); array.recycle(); } else { mColor = defaultColor; mNum = defaultNum; } //計(jì)算中心角弧度 mCenterAngle = (float) (mPiDouble / mNum); }
          @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mViewWidth = w; mViewHeight = h; //計(jì)算最小的多邊形的半徑 mRadius = (Math.min(mViewWidth, mViewHeight) / 2f) * 0.95f; //計(jì)算中心小圓的半徑 mSmallCircleRadius = (Math.min(mViewWidth, mViewHeight) / 2f) * 0.3f; }
          @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //將畫布中心移動(dòng)到中心點(diǎn) canvas.translate(mViewWidth / 2, mViewHeight / 2); //畫小圓 drawSmallCircle(canvas); //畫多邊形 drawPolygon(canvas); }
          /** * 畫小圓 */ private void drawSmallCircle(Canvas canvas) { canvas.drawCircle(0, 0, mSmallCircleRadius, mPaint); }
          /** * 畫多邊形 */ private void drawPolygon(Canvas canvas) { //多邊形邊角頂點(diǎn)的x坐標(biāo) float pointX; //多邊形邊角頂點(diǎn)的y坐標(biāo) float pointY; //總的圓的半徑,就是全部多邊形的半徑之和 Path path = new Path(); //畫前先重置路徑 path.reset(); for (int i = 1; i <= mNum; i++) { //cos三角函數(shù),中心角的鄰邊 / 斜邊,斜邊的值剛好就是半徑,cos值乘以斜邊,就能求出鄰邊,而這個(gè)鄰邊的長(zhǎng)度,就是點(diǎn)的x坐標(biāo) pointX = (float) (Math.cos(i * mCenterAngle) * mRadius); //sin三角函數(shù),中心角的對(duì)邊 / 斜邊,斜邊的值剛好就是半徑,sin值乘以斜邊,就能求出對(duì)邊,而這個(gè)對(duì)邊的長(zhǎng)度,就是點(diǎn)的y坐標(biāo) pointY = (float) (Math.sin(i * mCenterAngle) * mRadius); //如果是一個(gè)點(diǎn),則移動(dòng)到這個(gè)點(diǎn),作為起點(diǎn) if (i == 1) { path.moveTo(pointX, pointY); } else { //其他的點(diǎn),就可以連線了 path.lineTo(pointX, pointY); } } path.close(); canvas.drawPath(path, mPaint); }
          @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(handleMeasure(widthMeasureSpec), handleMeasure(heightMeasureSpec)); }
          /** * 處理MeasureSpec */ private int handleMeasure(int measureSpec) { int result = DEFAULT_MIN_WIDTH; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { //處理wrap_content的情況 if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; }
          public static int dip2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); }}


          簡(jiǎn)單使用


          android:layout_width="30dp"
          android:layout_height="30dp"
          android:layout_margin="10dp"
          app:psv_color="@android:color/black"
          app:psv_line_width="1.5dp"
          app:psv_num="6" />

          到這里就結(jié)束了。

          瀏覽 132
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  老女人日逼视频 | 亚洲国产欧美日韩在线 | 中国婬乱a一级毛片多女 | 日本三级电影片一区二区 | 日韩无码高清视频 |