自定义视图的简单应用

来源:互联网 发布:广东人吃福建人 知乎 编辑:程序博客网 时间:2024/05/19 17:06

1、在res/values目录下新建attrs.xml文件:


<resources>    <declare-styleable name="myStyleable">        <attr name="max" format="integer"/>        <attr name="progress" format="integer"/>        <attr name="textSize" format="dimension"/>        <attr name="smallBgColor" format="color"/>        <attr name="progressColor" format="color"/>    </declare-styleable></resources>


format(自定义属性的格式)可选内容有integer、dimension(尺寸)、color、boolean、enum(枚举值)、flag(位或运算)、float、fraction(百分数)、reference(参考某一ID、默认)、string.


<declare-styleable name ="名称">
      <attr name = "background" format = "reference" />
</declare-styleable>

eg:

<ImageView
     android:layout_width = "42dip"
     android:layout_height = "42dip"
     android:background = "@drawable/图片ID"
                     />

2、自定义视图:

public class XykjProgressBar extends View {    //进度条的半径    private int radius;    //圆心    private int cx, cy;    //画笔    private Paint paint;    //进度的最大值    private int max = 100;    //进度值    private int progress;    //文本大小    private int textSize;    //内部小圆的背景色    private int smallBgColor = 0xff3F51B5;    //进度条的颜色    private int progressColor = 0xffFF4081;    public XykjProgressBar(Context context) {        super(context);        init();    }    public XykjProgressBar(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        //解析自定义属性        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.myStyleable);        textSize = ta.getDimensionPixelSize(R.styleable.myStyleable_textSize, 0);  //sp dp dip        max = ta.getInteger(R.styleable.myStyleable_max,100);        progress = ta.getInteger(R.styleable.myStyleable_progress,0);        smallBgColor = ta.getColor(R.styleable.myStyleable_smallBgColor,0xff3F51B5);        progressColor = ta.getColor(R.styleable.myStyleable_progressColor,0xffFF4081);        //释放资源        ta.recycle();        init();    }    private void init() {        paint = new Paint();        paint.setAntiAlias(true);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        paint.setStyle(Paint.Style.FILL);        paint.setColor(smallBgColor);        //画中间的小圆        canvas.drawCircle(cx, cy, radius - 10, paint);        //文本        int num = 100 * progress / max;  //50 100 -->50%        String str = num + "%";        //获取文本的边框        Rect bound = new Rect();        paint.setTextSize(textSize);        paint.getTextBounds(str, 0, str.length(), bound);        int x = cx - bound.centerX();        int y = cy - bound.centerY();        paint.setColor(Color.WHITE);        //画进度文本        canvas.drawText(str, x, y, paint);        //进度的弧线        paint.setStyle(Paint.Style.STROKE);        paint.setStrokeWidth(10);        paint.setColor(progressColor);        //计算所跨越的弧度        int degree = 360 * progress / max;        RectF rect = new RectF(cx - radius, cy - radius, cx + radius, cy + radius);        //画弧线        canvas.drawArc(rect, -90, degree, false, paint);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int width = getSize(widthMeasureSpec);        int height = getSize(heightMeasureSpec);        //初始化圆心        cx = width / 2;        cy = height / 2;        //取最短的边的一半作为进度半径        radius = width < height ? cx : cy;        radius -= 10;        //如果没有默认值则,初始化文本大小        if (textSize == 0) {            textSize = radius / 2;        }        setMeasuredDimension(width, height);    }    //获取尺寸方法(自定义的根据模式获取,wrap_content时设置默认值为80    private int getSize(int measureSpec) {        //获取测量模式        int mode = MeasureSpec.getMode(measureSpec);        int size = 80;        if (mode == MeasureSpec.EXACTLY) {            //精确的,固定的值,match_parent或者100  200            size = MeasureSpec.getSize(measureSpec);        }/*else if(mode == MeasureSpec.AT_MOST){            //不确定,如wrap_content            size = 80;        }*/        return size;    }    public int getMax() {        return max;    }    public void setMax(int max) {        this.max = max;    }    public int getProgress() {        return progress;    }    public void setProgress(int progress) {        if (this.progress != progress && progress <= max) {            this.progress = progress;            invalidate();        }    }    public int getTextSize() {        return textSize;    }    public void setTextSize(int textSize) {        this.textSize = textSize;    }    public int getSmallBgColor() {        return smallBgColor;    }    public void setSmallBgColor(int smallBgColor) {        this.smallBgColor = smallBgColor;    }    public int getProgressColor() {        return progressColor;    }    public void setProgressColor(int progressColor) {        this.progressColor = progressColor;    }}


3、在主界面中引用:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.xykj.myprogressbar.MainActivity">    <com.xykj.myprogressbar.XykjProgressBar        android:id="@+id/progress_bar"        android:layout_width="200dp"        android:layout_height="200dp"        app:textSize="30sp"        app:smallBgColor="#ff000000"/>    <Button        android:id="@+id/btn"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Click" /></LinearLayout>

java代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{    XykjProgressBar pBar;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        pBar = (XykjProgressBar) findViewById(R.id.progress_bar);        pBar.setMax(100);        pBar.setProgress(10);        pBar.setTextSize(50);        findViewById(R.id.btn).setOnClickListener(this);    }    @Override    public void onClick(View v) {        int p = pBar.getProgress();        p+=5;        pBar.setProgress(p);    }}

结果如下图:


面试题:介绍下实现一个自定义View的基本流程:

1、自定义view属性,编写attrs.xml文件

2、在layout布局中引用,同时引用命名空间

3、在view的构造方法中获得我们自定义的属性,在自定义的控件中进行读取

4、重写onMeasure()方法

5、重写onDraw()方法







原创粉丝点击