安卓自定义控件:画一个正五边形

五边形最后的效果图:
正五边形

/**
 * 自定义一个五边型,定义5个固定点,然后相连
 * @author guotianhui
 */
public class PentagonView extends View {


    private Paint paint;
    private Context mContext;
    private int mLinesColor;
    private Path path, pathTwo;
    private int mFirstMarginTop; // 设置第一个矩形距离头部的高度
    private int mSecondMarginTop; //设置第二个矩形距离头部的高度00
    private int mFirstRecHeight;//设置第一个矩形的高
    private int mSecondRecHight; //设置第二个矩形的高
    private int mDebugTopTextMargin;
    private int mDebugTextLeftMargin; //根据文字的长度,适配左边文字位置
    private int mDebugTextRightMargin; //根据文字长度,适配右边文字的间距
    private boolean mIsSetPointColor;
    private int mDebugMargin =dp2px(8);
    private int mHeadLayoutTopMargin ;
    private FrameLayout mHeaderImageView;
    private int mExpainTextColor,mPentagonTextSize;
    private String mPointOneText,mPointTowText,mPointThereText,mPointFourText,mPointFiveText;


    public PentagonView(Context context) {
        super(context);
        this.mContext = context;
    }

    public PentagonView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
    }

    public PentagonView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //动态设置头像布局距离顶部的距离/
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(-2, -2);
        layoutParams.topMargin = mHeadLayoutTopMargin;
        layoutParams.gravity = Gravity.CENTER_HORIZONTAL;
        mHeaderImageView.setLayoutParams(layoutParams);

        //设置五边形距离顶部的高度,让头像始终在布局中间
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2, -2);
        params.topMargin =  mHeadLayoutTopMargin -dp2px(75);
        params.gravity = Gravity.CENTER_HORIZONTAL;
        setLayoutParams(params);

        //设置五边形的外形
        mFirstMarginTop = dp2px(25);
        mSecondMarginTop = mFirstMarginTop +dp2px(15);
        mFirstRecHeight = mHeaderImageView.getWidth()+dp2px( 60);
        mSecondRecHight = mHeaderImageView.getWidth()+dp2px(35);
        //创建一支画笔
        paint = new Paint();
        paint.setColor(mLinesColor);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(2);
        paint.setStyle(Paint.Style.STROKE);
        //获取屏幕的宽高
        WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        Display defaultDisplay = windowManager.getDefaultDisplay();
        DisplayMetrics displayMetrics = new DisplayMetrics();
        defaultDisplay.getMetrics(displayMetrics);
        int width = displayMetrics.widthPixels;


        //创建一个路径
        path = new Path();
        path.moveTo(width/2,mFirstMarginTop+mDebugMargin+dp2px(8)); // 第一个点
        path.lineTo((width/2)-(mFirstRecHeight/2),mFirstRecHeight/2+mFirstMarginTop);//第二个点
        path.lineTo(width/2 -(mFirstRecHeight/3),mFirstMarginTop+mFirstRecHeight+mDebugMargin);//第三个点
        path.lineTo(width/2+(mFirstRecHeight/3) ,mFirstMarginTop+mFirstRecHeight+mDebugMargin);//第四个点
        path.lineTo((width/2)+(mFirstRecHeight/2),mFirstRecHeight/2+mFirstMarginTop);//第五个点
        path.close();
        canvas.drawPath(path,paint);

        //画一个更大的五边形
        pathTwo = new Path();
        pathTwo.moveTo(width/2,mSecondMarginTop+mDebugMargin+dp2px(5)); // 第一个点
        pathTwo.lineTo((width/2)-(mSecondRecHight/2),mSecondRecHight/2+mSecondMarginTop);//第二个点
        pathTwo.lineTo(width/2 -(mSecondRecHight/3),mSecondMarginTop+mSecondRecHight+mDebugMargin);//第三个点
        pathTwo.lineTo(width/2+(mSecondRecHight/3) ,mSecondMarginTop+mSecondRecHight+mDebugMargin);//第四个点
        pathTwo.lineTo((width/2)+(mSecondRecHight/2),mSecondRecHight/2+mSecondMarginTop);//第五个点
        pathTwo.close();
        canvas.drawPath(pathTwo,paint);


        //画五个不同颜色的点
        paint.setStyle(Paint.Style.FILL);
        //是否设置点的不同颜色
        if(mIsSetPointColor) {
            paint.setColor(Color.parseColor("#C84D17"));
            canvas.drawCircle(width / 2, mFirstMarginTop+mDebugMargin+dp2px(8), dp2px(4), paint); // 第一个点
            paint.setAlpha(30);
            canvas.drawCircle(width / 2, mFirstMarginTop+mDebugMargin+dp2px(8), dp2px(8), paint); // 第一个点

            paint.setColor(Color.parseColor("#F9B89B"));
            canvas.drawCircle((width / 2) - (mFirstRecHeight / 2), mFirstRecHeight / 2 + mFirstMarginTop, dp2px(4), paint); //第二个点
            paint.setAlpha(30);
            canvas.drawCircle((width / 2) - (mFirstRecHeight / 2), mFirstRecHeight / 2 + mFirstMarginTop, dp2px(8), paint); //第二个点

            paint.setColor(Color.parseColor("#F19A74"));
            canvas.drawCircle(width / 2 - (mFirstRecHeight / 3), mFirstMarginTop + mFirstRecHeight+mDebugMargin, dp2px(4), paint);//第三个点
            paint.setAlpha(30);
            canvas.drawCircle(width / 2 - (mFirstRecHeight / 3), mFirstMarginTop + mFirstRecHeight+mDebugMargin, dp2px(8), paint);//第三个点

            paint.setColor(Color.parseColor("#E7865B"));
            canvas.drawCircle(width / 2 + (mFirstRecHeight / 3), mFirstMarginTop + mFirstRecHeight+mDebugMargin, dp2px(4), paint);//第四个点
            paint.setAlpha(30);
            canvas.drawCircle(width / 2 + (mFirstRecHeight / 3), mFirstMarginTop + mFirstRecHeight+mDebugMargin, dp2px(8), paint);//第四个点


            paint.setColor(Color.parseColor("#E07140"));
            canvas.drawCircle((width / 2) + (mFirstRecHeight / 2), mFirstRecHeight / 2 + mFirstMarginTop, dp2px(4), paint); //第五个点
            paint.setAlpha(30);
            canvas.drawCircle((width / 2) + (mFirstRecHeight / 2), mFirstRecHeight / 2 + mFirstMarginTop, dp2px(8), paint); //第五个点
        }else{
            paint.setColor(Color.WHITE);
            canvas.drawCircle(width / 2, mFirstMarginTop+mDebugMargin+dp2px(8), dp2px(4), paint); // 第一个点
            canvas.drawCircle((width / 2) - (mFirstRecHeight / 2), mFirstRecHeight / 2 + mFirstMarginTop, dp2px(4), paint); //第二个点
            canvas.drawCircle(width / 2 - (mFirstRecHeight / 3), mFirstMarginTop + mFirstRecHeight+mDebugMargin, dp2px(4), paint);//第三个点
            canvas.drawCircle(width / 2 + (mFirstRecHeight / 3), mFirstMarginTop + mFirstRecHeight+mDebugMargin, dp2px(4), paint);//第四个点
            canvas.drawCircle((width / 2) + (mFirstRecHeight / 2), mFirstRecHeight / 2 + mFirstMarginTop, dp2px(4), paint); //第五个点
        }



        //顶部文字和左边的文字之间的间距使用mDebugTextMargin参数来微调,文字从左往右逆时针设置的
        paint.setColor(mExpainTextColor); //设置文字颜色
        paint.setTextSize(mPentagonTextSize);//设置文字的大小,文字设置从左往右,逆时针设置
        if(!"".equals(mPointOneText) && mPointOneText != null) {
            getDebugMarginByTextLength(mPointOneText);
            canvas.drawText(mPointOneText, width / 2 -(dp2px(20)+mDebugTopTextMargin), mFirstMarginTop+dp2px(8)-dp2px(5), paint);//青少年
        }
        if(!"".equals(mPointTowText) && mPointTowText != null) {
            getDebugMarginByTextLength(mPointTowText);
            canvas.drawText(mPointTowText,(width / 2 - (mFirstRecHeight/ 2)-mDebugTextLeftMargin),mFirstRecHeight/2+mFirstMarginTop+dp2px(3),paint);//古人
        }
        if(!"".equals(mPointThereText) && mPointThereText != null) {
            getDebugMarginByTextLength(mPointThereText);
            canvas.drawText(mPointThereText,(width / 2 - (mFirstRecHeight/ 2)-mDebugTextLeftMargin)+dp2px(20),mFirstMarginTop+mFirstRecHeight+mDebugMargin+dp2px(3),paint);//绘画
        }

        //右边的文字设置间距使用@mDebugLeftTextMargin,来微调右边文字的间距
        if(!"".equals(mPointFourText) && mPointFourText != null) {
            getDebugMarginByTextLength(mPointFourText);
            canvas.drawText(mPointFourText,width/2+(mFirstRecHeight/3)+mDebugTextRightMargin,mFirstMarginTop+mFirstRecHeight+mDebugMargin+dp2px(3),paint);//物理
        }
        if(!"".equals(mPointFiveText) && mPointFiveText != null) {
            getDebugMarginByTextLength(mPointFiveText);
            canvas.drawText(mPointFiveText,(width/2)+(mFirstRecHeight/2)+mDebugTextRightMargin,mFirstRecHeight/2+mFirstMarginTop+dp2px(3),paint);//科学研究
        }
    }
    /**
     * 根据标签的长度,微调文字的绘制位置
     */
    private void getDebugMarginByTextLength(String textLength){
        switch (textLength.length()){
            case 2: //标签两个文字
                mDebugTopTextMargin = dp2px(-2);
                mDebugTextLeftMargin = dp2px(39);
                mDebugTextRightMargin = dp2px(10);
                break;
            case 3:
                mDebugTopTextMargin = dp2px(2);
                mDebugTextLeftMargin = dp2px(52);
                mDebugTextRightMargin = dp2px(10);
                break;
            case 4: //标签四个文字
                mDebugTopTextMargin = dp2px(5);
                mDebugTextLeftMargin = dp2px(68);
                mDebugTextRightMargin = dp2px(10);
                break;
                default:{
                    if(textLength.length() >4){
                        mDebugTopTextMargin = dp2px(30);
                        mDebugTextLeftMargin = dp2px(107);
                        mDebugTextRightMargin = dp2px(10);
                    }
                }
                    break;
        }
    }
    /**
     * dp转px
     * @param dpValue
     * @return
     */
    protected int dp2px(int dpValue){
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpValue,getResources().getDisplayMetrics());
    }
    /**
     * 提供一个方法,拿到中间的头像
     */
    public void getHeadPictureMarginTop(FrameLayout headImageView,int topMargin){
         this.mHeaderImageView = headImageView;
         this.mHeadLayoutTopMargin = topMargin;
    }
    /**
     * 定义一个方法,设置五边形连线的颜色
     */
    public void setPentagonLinesColor(int linesColor){
        this.mLinesColor = linesColor;
    }
    /**
     * 设置五边形说明文字
     * @param textString
     */
    public void setPentagonViewText(String[] textString){
        if(ObjectUtils.isNotEmpty(textString)) {
            if(textString.length >=1){
                this.mPointOneText = textString[0];
                if(textString.length >= 2){
                    this.mPointFiveText = textString[1];
                    if(textString.length >=3){
                        this.mPointFourText = textString[2];
                        if(textString.length >= 4){
                            this.mPointThereText = textString[3];
                            if(textString.length >=5){
                                this.mPointTowText = textString[4];
                            }
                        }
                    }
                }
            }
        }
    }
    /**
     * 设置五边形说明文字的字体大小和颜色
     */
    public void setPentagonTextColor(int textColor){
        this.mExpainTextColor = textColor;
    }
    /**
     * 设置五边形说明文字的大小
     */
    public void setPentagonTextSize(int textSize){
        this.mPentagonTextSize = textSize;
    }
    /**
     * 判断是否显示不同点的颜色
     */
    public void isSetFivePointDifferentColor(boolean isDiffColor){
        this.mIsSetPointColor = isDiffColor;
    }
}

实现的总体思路是,
1)画点、连线,主要是这五个点的选择非常重要,要注意观察,发现第一个点在屏幕的最中央,还有就是点二、五和三、四是项目对称的,然后可以根据屏幕的宽和高来确定点的位置,最后定义一个画笔,把线连起来,最后再各个端点画一个更大的圆点。
2)点旁边的文字也是画出来的,也不难,最主要的是需要调试,文字和点之间的间距。
最后的调用代码:

 if(ObjectUtils.isNotEmpty(label)){
                    String[] labels = label.split(",");
                    //测试数据
                  //  String[]  labelString = {"你好","地方","啥事","好的","近平"};
                    mPentagonView.setPentagonViewText(labels); //标签逆时针展示
                }

我好久没有写博客了,希望对大家有用,谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值