• Register
110,660 points
12 7 5

Why are there custom controls?  
1. Specific display style
2. Handle unique user interactions
3. Optimize layout (eg via custom control in list to achieve complex custom layout and reduce clutter)
4. Packaging, etc.

How to customize controls 
1. Declaration and acquisition of custom attributes.
2. Measure to measure
3. Layout onLayout (ViewGroup)
4. Draw onDraw
5 、 onTouchEvent 
6 、 onInterceptTouchEnvent (ViewGroup) 
7. Restore and save progress status (Here you can directly inherit Progress instead of View, you don't need to start from 0 )

Start implementing below

1.1 Statement of style and acquisition

1.1 New style (the purpose is to set the attribute value directly in xml when using a Custom View)
attr.xml

 
<? xml version = "1.0" encoding = "utf-8"?>
<resources>
    <attr name = "HorizontalProgresUnReachColor" format = "color"> </attr>
    <attr name = "HorizontalProgresUnReachHeight" format = "dimension"> </attr>
    <attr name = "HorizontalProgresReachColor" format = "color"> </attr>
    <attr name = "HorizontalProgresReachHeight" format = "dimension"> </attr>
    <attr name = "HorizontalProgresTextColor" format = "color"> </attr>
    <attr name = "HorizontalProgresTextSize" format = "dimension"> </attr>
    <attr name = "HorizontalProgresTextOffset" format = "dimension"> </attr>
 
 
    <declare-styleable name = "CustomHorizontalProgresStyle">
        <attr name = "HorizontalProgresUnReachColor"> </attr>
        <attr name = "HorizontalProgresUnReachHeight"> </attr>
        <attr name = "HorizontalProgresReachColor"> </attr>
        <attr name = "HorizontalProgresReachHeight"> </attr>
        <attr name = "HorizontalProgresTextColor"> </attr>
        <attr name = "HorizontalProgresTextSize"> </attr>
        <attr name = "HorizontalProgresTextOffset"> </attr>
 
    </declare-styleable>
 
</resources>

1.2 Getting Style

Get custom attributes in the constructor

/ **
           * Get custom attributes
     * /
    private void geStyleabletAttr (AttributeSet attrs) {
        TypedArray typedArray = getContext (). ObtainStyledAttributes (attrs, R.styleable.CustomHorizontalProgresStyle);
        HorizontalProgresUnReachColor = typedArray.getColor (R.styleable.CustomHorizontalProgresStyle_HorizontalProgresUnReachColor, DEAFUALT_PROGRESS_UNREACH_CORLOR);
        HorizontalProgresReachColor = typedArray.getColor (R.styleable.CustomHorizontalProgresStyle_HorizontalProgresUnReachColor, DEAFUALT_PROGRESS_REACH_CORLOR);
                 // Convert sp and dp to sp
        HorizontalProgresReachHeight = typedArray.getColor (R.styleable.CustomHorizontalProgresStyle_HorizontalProgresReachHeight, dp2px (getContext (), DEAFUALT_PROGRESS_REACH_HEIGHH));
        HorizontalProgresUnReachHeight = typedArray.getColor (R.styleable.CustomHorizontalProgresStyle_HorizontalProgresUnReachHeight, dp2px (getContext (), DEAFUALT_PROGRESS_UNREACH_HEIGHH));
        HorizontalProgresTextColor = typedArray.getColor (R.styleable.CustomHorizontalProgresStyle_HorizontalProgresTextColor, DEAFUALT_PROGRESS_TEXT_CORLOR);
        HorizontalProgresTextSize = typedArray.getColor (R.styleable.CustomHorizontalProgresStyle_HorizontalProgresTextSize, DEAFUALT_PROGRESS_TEXT_SIZE);
        HorizontalProgresTextOffset = typedArray.getColor (R.styleable.CustomHorizontalProgresStyle_HorizontalProgresTextOffset, DEAFUALT_PROGRESS_TEXT_OFFSET);
        typedArray.recycle (); // Remember to add this sentence
    }

2.2.1 Measure Rewrite

/ **
      * Determine the width of this view
      * @param measureSpec A measureSpec packed into an int
      * @return The width of the view, honoring constraints from measureSpec
      * /
     private int measureWidth (int measureSpec) {
         int result = 0;
         int specMode = MeasureSpec.getMode (measureSpec);
         int specSize = MeasureSpec.getSize (measureSpec);
 
         if (specMode == MeasureSpec.EXACTLY) {
             // We were told how big to be
             result = specSize;
         } else {
             // Measure the text
             result = dp2px (getContext (), DEAFUALT_PROGRESS_VIEW_WIDTH); //
             if (specMode == MeasureSpec.AT_MOST) {
                 // Respect AT_MOST value if that was what is called for by measureSpec
                 result = Math.min (result, specSize);
             }
         }
 
         return result;
     }

2.2.2 Calculated width

/ **
      * Determine the width of this view
      * @param measureSpec A measureSpec packed into an int
      * @return The width of the view, honoring constraints from measureSpec
      * /
     private int measureWidth (int measureSpec) {
         int result = 0;
         int specMode = MeasureSpec.getMode (measureSpec);
         int specSize = MeasureSpec.getSize (measureSpec);
 
         if (specMode == MeasureSpec.EXACTLY) {
             // We were told how big to be
             result = specSize;
         } else {
             // Measure the text
             result = dp2px (getContext (), DEAFUALT_PROGRESS_VIEW_WIDTH); //
             if (specMode == MeasureSpec.AT_MOST) {
                 // Respect AT_MOST value if that was what is called for by measureSpec
                 result = Math.min (result, specSize);
             }
         }
 
         return result;
     }

2.2.3 Calculated height

/ **
     * Determine the height of this view
     * @param measureSpec A measureSpec packed into an int
     * @return The height of the view, honoring constraints from measureSpec
     * /
    private int measureHeight (int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode (measureSpec);
        int specSize = MeasureSpec.getSize (measureSpec);
 
        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else {
            // Measure the text (beware: ascent is a negative number)
            // The height here is the maximum value of the height of the completed progress and the incomplete machine size and the height of the text
            int textHeight = (int) (mPaint.descent () - mPaint.ascent ()); // There are two ways to get the height of the word, the first is React, the second is this
            result = Math.max (textHeight, Math.max (HorizontalProgresReachHeight, HorizontalProgresUnReachHeight)) + getPaddingTop ()
                    + getPaddingBottom ();
            if (specMode == MeasureSpec.AT_MOST) {
                // Respect AT_MOST value if that was what is called for by measureSpec
                result = Math.min (result, specSize);
            }
        }
        return result;
    }

2.2.4 Rewriting in drawing

@Override
    protected synchronized void onDraw (Canvas canvas) {
        super.onDraw (canvas);
 
        canvas.save (); // Save and restore the methods related to saving layers and reverting. See http://blog.csdn.net/tianjian4592/article/details/45234419 for more details.
        canvas.translate (0, getHeight () / 2); // Move the layer to the vertical center position
        float radio = getProgress () * 1.0f / getMax ();
        int textWidth = (int) mPaint.measureText (getProgress () + "%"); // The width of the text
        float realWidth = getWidth () - getPaddingLeft () - getPaddingRight () - textWidth - HorizontalProgresTextOffset; // real width minus text width
        float progressX = radius * realWidth;
        // Draw the finished progress line
        mPaint.setColor (HorizontalProgresReachColor);
        mPaint.setStrokeWidth (HorizontalProgresReachHeight);
        //canvas.drawLine(getPaddingLeft(),getPaddingTop(),progressX,getPaddingTop(),mPaint);// Vertical right angle at the same height float startY, float stopY the same
        RectF mRectF = new RectF (getPaddingLeft (), getPaddingTop () - HorizontalProgresReachHeight / 2, (int) progressX, HorizontalProgresReachHeight / 2); // Rounded corners int left, int top, int bottom
        canvas.drawRoundRect (mRectF, 15,15, mPaint); // rounded rectangle
        // Draw the progress
        mPaint.setColor (HorizontalProgresTextColor);
        mPaint.setTextSize (HorizontalProgresTextSize);
        int y = (int) - ((mPaint.descent () + mPaint.ascent ()) / 2); // The text is centered
        canvas.drawText (getProgress () + "%", progressX + HorizontalProgresTextOffset / 2, getPaddingTop () + y, mPaint);
        // Draw the unfinished progress
        if (progressX + HorizontalProgresTextOffset + textWidth <getWidth () - getPaddingLeft () - getPaddingRight ()) {// Progress has finished, unfinished ones are no longer drawn
            mPaint.setColor (HorizontalProgresUnReachColor);
            mPaint.setStrokeWidth (HorizontalProgresUnReachHeight);
            //canvas.drawLine(getPaddingLeft()+progressX + HorizontalProgresTextOffset + textWidth, getPaddingTop (), getWidth () -getPaddingLeft () -getPaddingRight (), getPaddingTop (), mPaint); // Float startY, floating vertically at the same height Same
            RectF mRectF2 = new RectF (getPaddingLeft () + progressX + HorizontalProgresTextOffset + textWidth, getPaddingTop () - HorizontalProgresUnReachHeight / 2, getWidth () - getPaddingLeft () - getPaddingRight (), Horizontal intProgresUnReachHeight left / horizontal intProgresUnReachHeight 2 rounded corners / left) , int right, int down
            canvas.drawRoundRect (mRectF2,15,15, mPaint); // rounded rectangle
        }
        canvas.restore ();
    }
110,660 points
12 7 5