el desarrollo de controles personalizados (b) de la [de Andrews Road Wang] "vestido de yema de huevo, el pelo suave y esponjosa, que quieren parecerse a lo que tengo."

Desarrollo de controles personalizados

Imagine un escenario en la serie:

  • el hombre principal: "Cariño, ya no se preocupan por su apariencia, su altura y peso no les importa, que sólo se preocupan por lo que eres, Te amo."
  • Dicho esto, hermosas mujeres controles hermanas eran astillas movido.
  • Cuidado de la casa: "555, Estoy profundamente conmovido, te amo."

Sin embargo, en la vida real:

  • Chicos: "Cariño, ya no se preocupan por su apariencia, su altura y peso no les importa, que sólo se preocupan por lo que eres, Te amo."
  • rabia niñas, un banquete de llamada
  • Niña: "Usted piensa que mira madre anciana fea no me ama, 555?"
  • Boy: "Me explico, @ #% # @ ¥ ¥ ¥ ...... @ # @"

O son:

  • Niños (hermana): "Pequeño hermano (hermana pequeña), que se ven muy bien, que pueda hacer sus amigos varones (mujeres)?"
  • Niñas (niños): "Ja ja ja Gracias, eres un hombre bueno, voy a tomar un baño, hablaremos más tarde"

Usted ve, la gente ahora mira lo que es, sin duda, el primero en ver de otra persona que tiene más probabilidades de dejar una buena impresión a los demás cosas, el teléfono es APP. Por ejemplo, un sonido, si la función como de costumbre, cualquier otra cosa es un botón sin botones nativos de modificación que, en comparación con personas que no serán muchos. Sin embargo, Google nos proporcionará tanto control, con el tiempo darse el caso de no encontrar un control adecuado. En el último artículo que he mencionado el uso en combinación para crear un control nuevo, esta vez yo venga y analizamos un nuevo truco:

nada

----- A partir de "lenguaje Guo · El primer capítulo"

¿Quieres un control personalizado, en primer lugar tenemos que ser claros, lo que necesito es:
Quiero ser un gradiente botones? O puede percibir color de la cáscara móvil del color de fondo? foto negro o de colores?

Así que ahora asumen que hay una demanda de este tipo: barra de progreso Andrews nativa difícil de leer, quiero personalizar la primera ronda, se moverá, y puede mostrar porcentajes.
En primer lugar, analizamos los buenos, los siguientes elementos gráficos:

  1. Es una barra de progreso
  2. ronda
  3. Puede mostrar el porcentaje
  4. Se va a mover

Arreglos! ! !

Se debe limpiar primero pasos para desarrollar controles personalizados:

  1. Los atributos personalizados y la declaración de acceso
  2. medida
  3. dibujar
  4. Almacenar y restaurar el estado

.
.
.

Paso a: definir atributos

Creamos una nueva clase llamada: RoundProgressBar, y por lo que hereda de la clase View, se puede redefinir su constructor

public class RoundProgressBar1 extends View {
    
    //一般情况下重写两个参数的构造函数就行
    public RoundProgressBar1(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
}

entonces se crea una nueva carpeta con el nombre del archivo de los valores attrs.xml archivo (si se utiliza directamente en la línea)
comenzó a definir las propiedades de este control:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RoundProgressBar"> //name要和我们的类名对应
        <attr name="color" format="color"/> //进度条的颜色
        <attr name="line_width" format="dimension"/>//进度条的宽度
        <attr name="radius" format="dimension"/>//圆形的半径
        <attr name="android:progress" />//进度(这里我们用了原生的属性)
        <attr name="android:textSize" />//显示百分比的字体大小
    </declare-styleable>
</resources>

A continuación, definir las propiedades de la clase para registrar estas variables

    private int mColor;
    private int mRadius;
    private int mLineWidth;
    private int mTextSize;
    private int mProgress ;

A continuación, en el constructor, obtenemos estas propiedades:

 public RoundProgressBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        //获取TypedArray 对象
        TypedArray ta  = context.obtainStyledAttributes(attrs,R.styleable.RoundProgressBar);
        //获取半径,默认值为dp2px(30)
        mRadius = (int) ta.getDimension(R.styleable.RoundProgressBar_radius,dp2px(30));
        //获取颜色,默认值为红色
        mColor = ta.getColor(R.styleable.RoundProgressBar_color,0xffff0000);
        //获取线的宽度
        mLineWidth = (int) ta.getDimension(R.styleable.RoundProgressBar_line_width,dp2px(3));
        //获取字体大小
        mTextSize = (int)ta.getDimension(R.styleable.RoundProgressBar_android_textSize,dp2px(16));
        //获取进度
        mProgress = ta.getInt(R.styleable.RoundProgressBar_android_progress,0);
        //回收TypedArray 对象
        ta.recycle();
    }

Método un largo camino por donde dp2px ():

 private float dp2px(int i) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,i,getResources().getDisplayMetrics());
    }

A continuación, el archivo de diseño que se puede utilizar este control a la propiedad:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:wang="http://schemas.android.com/apk/res-auto" ///这个命名控件是一定要写的,前面的wang可以随意替换
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

<com.example.customviewtest.RoundProgressBar
    android:id="@+id/progressbar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    wang:radius="60dp"
    android:progress="10"
    wang:line_width="3dp"
    android:padding="10dp"/>

</RelativeLayout>

Podemos tratar de golpear un tronco en el proceso de construcción, ver si se puede llegar a los atributos normales de nuestra tarea.

Paso Dos: Medición

Aquí empezó a escribir un artículo medido directamente, no sé Vista proceso de renderizado puede echar un vistazo a mí antes: el conocimiento relevante Andrews Opinión dibujada
con nosotros directamente en RoundProgressBar esta clase de anulación del onMeasure () Este método

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int with_mode = MeasureSpec.getMode(widthMeasureSpec);//获取测量模式
        int width_size = MeasureSpec.getSize(widthMeasureSpec);//获取父控件测量出来的宽度值

        //测量宽度
        int width = 0;
        if(with_mode == MeasureSpec.EXACTLY)
        {
        //如果测量模式是EXACTLY,那宽度就取决于xml里写的值
            width = width_size;
        }
        else
        {
            int width_measure = meaasureWidth() + getPaddingLeft() + getPaddingRight();

            if (width == MeasureSpec.AT_MOST)
            {
            //如果测量模式是AT_MOST,就选取较小的
                width = Math.min(width_size,width_measure);
            }
            else
            {
            //如果测量模式是UNSPECIFICED,则是需要你自己测量
                width = width_measure;
            }

        }

        //测量高度

        int height_mode = MeasureSpec.getMode(heightMeasureSpec);
        int height_size = MeasureSpec.getSize(heightMeasureSpec);

        int height = 0;
        if(height_mode == MeasureSpec.EXACTLY)
        {
            height = height_size;
        }
        else
        {
            int height_measure = meaasureHeight() +getPaddingTop() + getPaddingBottom();

            if (height_mode == MeasureSpec.AT_MOST)
            {
                height = Math.min(height_size,height_measure);
            }
            else
            {
                height  = height_measure;
            }
        }

        setMeasuredDimension(width,height);
    }

//因为我们测量的是一个圆,所以宽度和高度都是圆的半径*2
    private int meaasureHeight() {

        return mRadius*2;
    }
      private int meaasureWidth() {
        return mRadius*2;
    }

La mayor control de la medición es tal que, en circunstancias normales sólo necesitamos para cambiar el método meaasureWidth () meaasureHeight () y puede ser.

Paso tres: Dibuje

En primer lugar, necesitamos una pluma,

private Paint mPaint;

A continuación, en el constructor, después de la recuperación de la AR, pluma inicializado:


    private void initPaint() {
        mPaint = new Paint();
        mPaint.setColor(mColor);
        mPaint.setAntiAlias(true);//设置抗锯齿
    }

Reescribir método onDraw ():

  @Override
    protected void onDraw(Canvas canvas) {

        mPaint.setStyle(Paint.Style.STROKE);//设置笔的空心/实心
        mPaint.setStrokeWidth(mLineWidth/4);//设置笔的宽度

        int width = getWidth();//获取控件宽度
        int height = getHeight();//获取控件高度

//先画一个比较细的圆
        canvas.drawCircle(width/2,height/2,width/2-getPaddingLeft()-mPaint.getStrokeWidth()/2,mPaint);

//画一个粗一些的圆
        mPaint.setStrokeWidth(mLineWidth);
        canvas.save();
        //移动画笔的中心点
        canvas.translate(getPaddingLeft(),getPaddingTop());

        float angle =  mProgress*1.0f/100*360;//计算绘制的弧度
        //绘制弧线
        canvas.drawArc(new RectF(0,0,width-getPaddingLeft()*2,height-getPaddingLeft()*2),0,angle,false,mPaint);
        canvas.restore();


        mPaint.setStrokeWidth(0);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextSize(mTextSize);
        String text = mProgress+"%";
        mPaint.setTextAlign(Paint.Align.CENTER);
        int y = getHeight()/2;
        Rect bound = new Rect();
        mPaint.getTextBounds(text,0,text.length(),bound);
        int textHeight = bound.height();
        //绘制字体
        canvas.drawText(text,0,text.length(),getWidth()/2,y+textHeight/2-mPaint.descent()/2,mPaint);
    }

En el método onDraw (), lo más importante es la lona API relacionada y pintura objeto objetos, no importa qué pasos son los mismos controles de dibujo.

Almacenamiento y restauración de estado: Paso cuatro

Vuelva a escribir estos dos métodos en la línea:



    public static final String KEY_PROGRESS = "progress";
    public static final String KEY_INSTANCE = "instance";

 @Nullable
    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putInt(KEY_PROGRESS,mProgress);
        bundle.putParcelable(KEY_INSTANCE,super.onSaveInstanceState());
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle)
        {
            Bundle bundle = (Bundle) state;
            mProgress = bundle.getInt(KEY_PROGRESS);
            Parcelable parcelable = bundle.getParcelable(KEY_INSTANCE);
            super.onRestoreInstanceState(parcelable);
            return;
        }

        super.onRestoreInstanceState(state);
    }
   


Por último, añadir a este método de control para obtener y establecer el calendario:

 public void setProgress(int progress)
    {
        mProgress = progress;
        invalidate();//重新绘制
    }
    public int getProgress()
    {
        return mProgress;
    }

Actividad a continuación, sólo tiene que conseguir el control y, a continuación, establezca la propiedad de animación le puede dar:

 final View progress = findViewById(R.id.progressbar);
 ObjectAnimator.ofInt(progress,"progress",0,100).setDuration(3000).start();

El efecto neto es la siguiente:
Aquí Insertar imagen Descripción
pequeños consejos:
No vaya a un nuevo objetivo en el método onDraw causará desbordamiento de memoria.

Publicado 47 artículos originales · elogios ganado 15 · Vistas a 10000 +

Supongo que te gusta

Origin blog.csdn.net/qq_41525021/article/details/98756793
Recomendado
Clasificación