美文网首页
Android---自定义View

Android---自定义View

作者: this_is_for_u | 来源:发表于2017-06-23 19:25 被阅读41次

参考鸿洋大神博客:http://blog.csdn.net/lmj623565791/article/details/24300125

主要内容:
1.自定义view
2.自定义view的属性
3.在view的构造方法中获取自定义的属性
4.重写onMeasure()
5.重写onDraw()
效果:实现进度条效果

image.png

1.自定义View属性示例:

在values下新建attrs.xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
    <attr name="titleText" format="string"/>
    <attr name="titleTextColor" format="color"/>
    <attr name="titleTextSize" format="dimension"/>
    <attr name="firstColor" format="color"/>
    <attr name="secondColor" format="color"/>
    <attr name="circleWidth" format="dimension"/>
    <attr name="speed" format="integer"/>
    <declare-styleable name="CustomTitleView">
        <attr name="titleText"/>
        <attr name="titleTextColor"/>
        <attr name="titleTextSize"/>
    </declare-styleable>
    <declare-styleable name="CustomProgressBar">
        <attr name="firstColor"/>
        <attr name="secondColor"/>
        <attr name="circleWidth"/>
        <attr name="speed"/>
    </declare-styleable>

</resources>

布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
//此处特别注意:需添加如下声明
    xmlns:custom="http://schemas.android.megvii.customview"
    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="megvii.customview.MainActivity">
    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <megvii.customview.CustomTitleView
        android:id="@+id/custom"
//自定义的属性
        custom:titleTextColor="#ff0000"
        custom:titleTextSize="40sp"
        custom:titleText="nihaoahgagaga"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <megvii.customview.CustomProgressBar
        custom:circleWidth="60sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>

两个自定义View,不同效果进阶:
CustomTitleView:

public class CustomTitleView extends View {

   private String mTitleText = "ggaggagh";
   private int mTitleTextColor = Color.BLUE;
   private int mTitleTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics());

   private Rect mBound;
   private Paint mPaint = new Paint();


   public CustomTitleView(Context context) {
       this(context, null);
   }

   public CustomTitleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

       super(context, attrs, defStyleAttr);
       Log.i("hello", "gas");

       //获得自定义样式属性
       TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomTitleView);
       int n = ta.length();
       Log.i("hello", "gggggggg" + n);
       for (int i = 0; i < n; i++) {
           int attr = ta.getIndex(i);
           switch (attr) {
               case R.styleable.CustomTitleView_titleText:
                   //不知道为什么,这个函数就是不好使,运行就闪退
                   mTitleText = ta.getString(attr);
                   break;
               case R.styleable.CustomTitleView_titleTextColor:
                   //默认设置为蓝色
                   mTitleTextColor = ta.getColor(attr, Color.BLUE);
                   break;
               case R.styleable.CustomTitleView_titleTextSize:
                   //默认设置为16sp
                   mTitleTextSize = ta.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 26, getResources().getDisplayMetrics()));
                   break;
           }
       }
       ta.recycle();
       Log.wtf("nihao", mTitleText);
       //获得文本宽高
       mPaint.setTextSize(mTitleTextSize);
       mBound = new Rect();
       mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);

       this.setOnClickListener(new OnClickListener() {
           @Override
           public void onClick(View v) {
               mTitleText = randomText();
               postInvalidate();
           }
       });
   }

   public CustomTitleView(Context context, @Nullable AttributeSet attrs) {
       this(context, attrs, 0);
   }

   private String randomText(){
       Random random = new Random(System.currentTimeMillis());
       Set<Integer> si = new HashSet<Integer>();
       while(si.size() < 10){
           int rand = random.nextInt();
           si.add(rand);
       }
       StringBuffer sb = new StringBuffer();
       for(Integer i : si){
           sb.append("" + i);
       }
       return sb.toString();

   }

   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//通过重写onMeasure可以解决wrap_content与padding问题
       int widthMode = MeasureSpec.getMode(widthMeasureSpec);
       int widthSize = MeasureSpec.getSize(widthMeasureSpec);
       int heightMode = MeasureSpec.getMode(heightMeasureSpec);
       int heightSize = MeasureSpec.getSize(heightMeasureSpec);
       int width;
       int height;
       if (widthMode == MeasureSpec.EXACTLY) {
           width = widthSize;
       } else {
           mPaint.setTextSize(mTitleTextSize);
           mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
           float textWidth = mBound.width();
           int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());
           width = desired;
       }
       if (heightMode == MeasureSpec.EXACTLY) {
           height = heightSize;
       } else {
           mPaint.setTextSize(mTitleTextSize);
           mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
           float textheight = mBound.height();
           int desired = (int) (getPaddingTop() + textheight + getPaddingBottom());
           height = desired;
       }
       setMeasuredDimension(width, height);
   }

   @Override
   protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
       mPaint.setColor(Color.YELLOW);
       canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
       mPaint.setColor(mTitleTextColor);
       canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
   }
}

CustomProgressBar


public class CustomProgressBar extends View{

    private int mFirstColor;
    private int mSecondColor;
    private int mCircleWidth;
    private Paint mPaint;
    private int mProgress;
    private int mSpeed;
    private boolean isNext = false;

    public CustomProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomProgressBar);
        int n = a.length();
        for(int i = 0; i < n; i++){
            int attr = a.getIndex(i);
            switch (attr){
                case R.styleable.CustomProgressBar_firstColor:
                    mFirstColor = a.getColor(attr, Color.GREEN);
                    break;
                case R.styleable.CustomProgressBar_secondColor:
                    mSecondColor = a.getColor(attr, Color.RED);
                    break;
                case R.styleable.CustomProgressBar_circleWidth:
                    mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 140, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.CustomProgressBar_speed:
                    mSpeed = a.getInt(attr, 20);
                    break;
            }
        }
        a.recycle();
        mPaint = new Paint();
        new Thread(){
            @Override
            public void run() {
                while(true){
                    mProgress++;
                    if(mProgress == 360){
                        mProgress = 0;
                        if(!isNext)
                            isNext = true;
                        else
                            isNext = false;
                    }
                    postInvalidate();
                    try{
                        Thread.sleep(mSpeed);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            };
        }.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int center = getWidth() / 2;//获取圆心的x坐标
        int radius = center - mCircleWidth / 2 -60;//半径
        mPaint.setStrokeWidth(100);//设置圆环的宽度
        mPaint.setAntiAlias(true);//消除锯齿
        mPaint.setStyle(Paint.Style.STROKE);//设置空心
        RectF oval = new RectF(center-radius, center-radius, center+radius, center+radius);
        //定义圆弧的形状和大小的界限
        if(!isNext){
            mPaint.setColor(mFirstColor);//设置圆环颜色
            canvas.drawCircle(center, center, radius, mPaint);//画出圆圈
            mPaint.setColor(mSecondColor);//设置圆环颜色
            canvas.drawArc(oval, -90, mProgress, false, mPaint);//根据进度画圆弧
        }else{
            mPaint.setColor(mSecondColor);
            canvas.drawCircle(center, center, radius, mPaint);
            mPaint.setColor(mFirstColor);
            canvas.drawArc(oval, -90, mProgress, false, mPaint);
        }
    }

    public CustomProgressBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomProgressBar(Context context) {
        this(context, null);
    }
}

相关文章

  • Android---自定义View

    参考鸿洋大神博客:http://blog.csdn.net/lmj623565791/article/detail...

  • Android---初探自定义View(一)

    记得我的第一个项目是把师兄做好的一个原生app进行“加工”,所谓的加工其实就是去网上找一下别人做好的定义控件,然后...

  • Android---初探自定义View(二)

    在初探自定义View(一)里面,我们在原生TextView的基础上做了一点小修改,最后实现了想要的效果,今天的任务...

  • Android---初探自定义View(三)

    在初探自定义View(一)和初探自定义View(二)里面,我们都是针对系统现有的组件进行设计和修改,那万一碰到需要...

  • Android View(转)

    自定义View的原理自定义View基础 - 最易懂的自定义View原理系列自定义View Measure过程 - ...

  • 自定义View系列

    自定义View1---知识储备自定义View2---View Measure过程自定义View3---View L...

  • 自定义View5---完整的自定义View

    移步自定义View系列 1.自定义view的分类自定义单一view(不含子view)继承view继承特定view如...

  • 自定义View

    自定义View系列文章 自定义View view向上滚动

  • 自定义View(一) 自定义View的概述

    不怕跌倒,所以飞翔 自定义View概述 1.自定义View分类 自定义View 直接继承View主要是绘制 自定义...

  • Android自定义View

    Android自定义View 参考:从此再有不愁自定义View——Android自定义view详解android ...

网友评论

      本文标题:Android---自定义View

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