美文网首页
Android 自定义View--入门篇

Android 自定义View--入门篇

作者: 吴唐人 | 来源:发表于2016-10-24 16:27 被阅读25次

    概述

    自定义View是Android程序员在进阶阶段是必须经历的也是痛苦的,但是它也没有想象的那么麻烦,无非也就是一下几步:

    1. 自定义View属性
    2. 在构造方法中获得自定义的属性
    3. 重新ononDraw:用来绘制该控件的内容
    4. 重新onMeasure:用来确定该控件或子控件的大小
    5. 重新onLayout:用来确定该控件及子控件在父窗体中的位置
    

    并不是说每次都要重写这些方法,这个还要看实际情况。

    实现目标

    <img src="https://img.haomeiwen.com/i2260249/8c39124081a528a0.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/>

    实现方式

    1. 自定义View属性:res/values下新建attrs.xml,在里面声明需要的属性

    <?xml version="1.0" encoding="utf-8"?>
    <resources> 
       <declare-styleable name="FloatCricleView">    
             <attr name="viewText" format="string"></attr>     
             <attr name="viewTextSize" format="dimension"></attr>    
             <attr name="viewBackground" format="color"></attr>  
             <attr name="viewTextColor" format="color"></attr>   
     </declare-styleable>
    </resources>
    

    2. 那么我们如何实现这些属性呢?

    在View的构造方法中获得属性,首先我们有必要介绍一下这几个构造方法

    public int width;//布局宽
    public int height;//布局的高
    private Paint circlePaint;//圆画笔
    private Paint textPaint;//文字画笔
    private int textSize;
    private int colorBackground;
    private int textColor;
    private String text;
    public FloatCricleView(Context context) {
        this(context, null);
    }
    public FloatCricleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public FloatCricleView(Context context, AttributeSet attrs, int defStyleAttr) { 
        super(context, attrs, defStyleAttr);   
        TypedArray array = context.obtainStyledAttributes(attrs,    R.styleable.FloatCricleView, defStyleAttr, 0);  
        int size = array.getIndexCount(); 
        //设置一些默认参数  
        colorBackground = Color.GRAY;//背景色   
        textColor = Color.BLACK;//文字颜色  
        textSize = 20;//文字大小   
        text = "NULL";   
        for (int i = 0; i < size; i++) {    
          int attr = array.getIndex(i);    
          switch (attr) {         
          case R.styleable.FloatCricleView_viewText:     
               text = array.getString(attr); 
               break;        
          case R.styleable.FloatCricleView_viewTextColor:       
             textColor = array.getColor(attr, Color.BLACK);         
             break;         
          case R.styleable.FloatCricleView_viewTextSize:            
            textSize = array.getDimensionPixelSize(attr, 20);         
            break;        
          case R.styleable.FloatCricleView_viewBackground:        
            colorBackground = array.getColor(attr, Color.GRAY);   
            break;     
           default:          
           break;    
        }    
    }  
      initView();//初始化画笔
    }
    
    private void initView() { 
        circlePaint = new Paint();
        circlePaint.setColor(colorBackground); 
        circlePaint.setAntiAlias(true);  
        textPaint = new Paint(); 
        textPaint.setTextSize(textSize); 
        textPaint.setAntiAlias(true);  
        textPaint.setFakeBoldText(true); 
        textPaint.setColor(textColor);
    }
    

    我们重写了3个构造方法,默认的布局文件调用的是两个参数的构造方法,所以记得让所有的构造调用我们的三个参数的构造,我们在三个参数的构造中获得自定义属性。

    3. 重新onDraw,onMeasure

    QQ截图20161024160136.jpg
    @Overrideprotected void onDraw(Canvas canvas) { 
       super.onDraw(canvas);  
        canvas.drawCircle(width / 2, height / 2, width / 2, circlePaint);
        float textWidth = textPaint.measureText(text);
        float x = width / 2 - textWidth / 2;
        Paint.FontMetrics metrics = textPaint.getFontMetrics();
        float dy = -(metrics.ascent + metrics.descent) / 2; 
        float y = height / 2 + dy;
        canvas.drawText(text, x, y, textPaint);
    }
    
    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
      //设置宽度
        int specMode = View.MeasureSpec.getMode(widthMeasureSpec); 
        int specSize = View.MeasureSpec.getSize(widthMeasureSpec);
        switch (specMode) {     
          case View.MeasureSpec.EXACTLY://明确指定大小的,或者最大  
              width = getPaddingLeft() + getPaddingRight() + specSize;
              break; 
           case View.MeasureSpec.AT_MOST://一般为warp_content
                width = getPaddingLeft() + getPaddingRight() + dip2px(getContext(), 100);
                break;
        }  
      //设置高度  
       specMode = View.MeasureSpec.getMode(heightMeasureSpec); 
       specSize = View.MeasureSpec.getSize(heightMeasureSpec); 
       switch (specMode) {   
           case View.MeasureSpec.EXACTLY:     
                height = getPaddingTop() + getPaddingBottom() + specSize;  
                break;    
           case View.MeasureSpec.AT_MOST:  
                height = getPaddingTop() + getPaddingBottom() + dip2px(getContext(), 100);        
                break;  
      }  
      setMeasuredDimension(width, height);}
    

    4. 工具方法

    /**
     * dp 转 px
     * 
     * @param context 
     * @param value 
     * @return 
     */
    private static int dip2px(Context context, float value) { 
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (value * scale + 0.5f);
    }
    /**
     * px转dp 
     *
     * @param context
     * @param value
     * @return 
     */
    private static int px2dip(Context context, float value) {  
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (value / scale + 0.5f);
    }
    

    5. 使用

    <tangren.szxb.com.floatcrileview.FloatCricleView2         
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"    
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"     
        add:viewBackground="@color/colorAccent"   
        add:viewText="90%"  
        add:viewTextColor="@color/colorPrimary"  
        add:viewTextSize="20sp" />
    

    6. 结束语

    实现的效果也比较简单大神勿喷,至此我的第一篇简书文章也写完了,希望大家相互学习沟通交流,我的csdn地址:http://blog.csdn.net/wu996489865 。因为我是第一次在简书上发布自己的文章,我想问的是为什么代码不会自动换行,我都是手动回车换行的啊(泪崩)!还请大神们指点一二(抱拳)!

    相关文章

      网友评论

          本文标题:Android 自定义View--入门篇

          本文链接:https://www.haomeiwen.com/subject/wjsluttx.html