Android custom View Series Dynamic Button

Source: Internet
Author: User
Tags getcolor

Android custom View Series Dynamic Button

My public account:

If you like my article, please follow my public account.

Today we will introduce a button that can be dynamically changed. For example, the rectangle changes to a circle, the circle changes to a rectangle, and the rectangle changes to a progress bar and then to a circle. Let's take a look at it first.
Vce + signature + cP30rvPwqOs0Ke5 + 8q1z9bO0tXiwO + signature + tMu/2Lz + signature/Signature + signature + zazR + signature + Signature =" brush: java; ">

Each attribute has the following meanings:

Dybtn_color: the normal background color of the button.
Dybtn_corner_radius: corner radian of the button
Dybtn_stroke_color: edge color of the button
Dybtn_stroke_width: edge width of the button
Dybtn_pressed_color: The color when the button is pressed.
Pbtn_progresscolor: The color of the progress bar button
Pbtn_maxvalue: maximum value of the progress bar
Pbtn_minvalue: minimum value of the progress bar
Pbtn_progress: current progress of the progress bar

Since attributes are defined, Custom Attributes must be parsed. Custom Attributes are usually carried out in constructors. Therefore, the common practice is to define a method to call in all constructors:

public void initView(Context mContext, AttributeSet attrs, int defStyleAttr) {        TypedArray array = mContext.obtainStyledAttributes(attrs, R.styleable.DynamicButton, defStyleAttr, 0);        mColor = array.getColor(R.styleable.DynamicButton_dybtn_color, DEFUALT_DYB_COLOR);        mPressedColor = array.getColor(R.styleable.DynamicButton_dybtn_pressed_color, DEFAULT_DYB_PRESSED_COLOR);        mCornerRadius = array.getDimensionPixelOffset(R.styleable.DynamicButton_dybtn_corner_radius, dp2px(DEFUALT_DYB_CORNER_RADIUS));        mStrokeColor = array.getColor(R.styleable.DynamicButton_dybtn_stroke_color, DEFAULT_DYB_STROKE_COLOR);        mStrokeWidth = array.getDimensionPixelOffset(R.styleable.DynamicButton_dybtn_stroke_width, dp2px(DEFAULT_DYB_STROKE_WIDTH));        mNormalDrawable = createDrawable(mColor, mCornerRadius, mStrokeWidth, mStrokeColor);        mPressedDrawable = createDrawable(mPressedColor, mCornerRadius, mStrokeWidth, mStrokeColor);        StateListDrawable mListDrawable = new StateListDrawable();        mListDrawable.addState(new int[]{android.R.attr.state_pressed}, mPressedDrawable);        mListDrawable.addState(new int[]{android.R.attr.state_focused}, mPressedDrawable);        mListDrawable.addState(new int[]{android.R.attr.state_selected}, mPressedDrawable);        mListDrawable.addState(new int[]{}, mNormalDrawable);        setBackground(mListDrawable);        array.recycle();    }

Here I just want to explain thatStateListDrawableIn general, if we want to implement a control that has different background colors when pressed and normal, it is implemented through selecter. Here we useStateListDrawableIn fact, selecter is also implemented through this class. The normal status, the focus, and the background color of the pressed status are defined respectively.

We entercreateDrawable()Method:

    public CustomGradientDrawable createDrawable(int mColor, float mCornerRadius, int mStrokeWidth, int mStrokeColor) {        CustomGradientDrawable drawable = new CustomGradientDrawable();        drawable.setShape(GradientDrawable.RECTANGLE);        drawable.setStrokeColor(mStrokeColor);        drawable.setStrokeWidth(mStrokeWidth);        drawable.setColor(mColor);        drawable.setRadius(mCornerRadius);        return drawable;    }

We did not directly useGradientDrawableThis class defines its own subclass, and only adds some attributes in the subclass, and some attributes exist in the parent class. Why? Attribute animation is required here. Attribute animation requires a condition that the property must have a corresponding get/set method, such as attribute color, you must have setColor and getColor to use the property animation to complete the gradient of the color attribute.

As mentioned above, there are too many attributes involved here, so you can use the Builder mode to manage attributes.

/*** Use Build mode to Build the properties of this button */public static class PropertyParam {public int mHeight; public int mWidth; public int mColor; public int mPressedColor; public float mCornerRadius; public int mStrokeWidth; public int mStrokeColor; public long duration; public String text; public Drawable icon; public static PropertyParam build () {return new PropertyParam ();} public PropertyParam setHeight (int mHeight) {this. mHeight = mHeight; return this;} public PropertyParam setWidth (int mWidth) {this. mWidth = mWidth; return this;} public PropertyParam setColor (int mColor) {this. mColor = mColor; return this;} public PropertyParam setCornerRadius (int mCornerRadius) {this. mCornerRadius = mCornerRadius; return this;} public PropertyParam setStrokeWidth (int mStrokeWidth) {this. mStrokeWidth = mStrokeWidth; return this;} public PropertyParam setStrokeColor (int mStrokeColor) {this. mStrokeColor = mStrokeColor; return this;} public PropertyParam setPressedColor (int mPressedColor) {this. mPressedColor = mPressedColor; return this;} public PropertyParam duration (long duration) {this. duration = duration; return this;} public PropertyParam text (String text) {this. text = text; return this;} public PropertyParam icon (Drawable icon) {this. icon = icon; return this ;}}

If you have been familiar with the Builder mode, this code is very easy to understand. If you do not know it, you can check the Build mode online first. I will not explain it here.

We usePropertyParamThis class stores the attributes of the button to be converted into a shape. We can easily obtain the corresponding attributes of the button's current shape. We assemble the data into another data structure.AnimatorParamsThis class stores the attributes of the current shape and the corresponding attributes of the shape to be changed. For example, if we are a rectangle and want to become a circle, thenAnimatorParamsIt stores the height, width, corner radians, and background color of two shapes.

 public static class AnimatorParams{        private float fromCornerRadius;        private float toCornerRadius;        private int fromHeight;        private int toHeight;        private int fromWidth;        private int toWidth;        private int fromColor;        private int toColor;        private int fromStrokeWidth;        private int toStrokeWidth;        private int fromStrokeColor;        private int toStrokeColor;        private long duration;        private DynamicButton mButton;        private AnimatorBuilder.AnimatorListener mListener;        public AnimatorParams(DynamicButton mButton){            this.mButton=mButton;        }        public static AnimatorParams build(DynamicButton mButton){            return new AnimatorParams(mButton);        }        public AnimatorParams height(int fromHeight,int toHeight) {            this.fromHeight = fromHeight;            this.toHeight = toHeight;            return this;        }        public AnimatorParams cornerRadius(float fromCornerRadius,float toCornerRadius){            this.fromCornerRadius=fromCornerRadius;            this.toCornerRadius=toCornerRadius;            return this;        }        public AnimatorParams width(int fromWidth,int toWidth){            this.fromWidth=fromWidth;            this.toWidth=toWidth;            return this;        }        public AnimatorParams strokeWidth(int fromStrokeWidth,int toStrokeWidth){            this.fromStrokeWidth=fromStrokeWidth;            this.toStrokeWidth=toStrokeWidth;            return this;        }        public AnimatorParams strokeColor(int fromStrokeColor,int toStrokeColor){            this.fromStrokeColor=fromStrokeColor;            this.toStrokeColor=toStrokeColor;            return this;        }        public AnimatorParams duration(long duration){            this.duration=duration;            return this;        }        public AnimatorParams listener(AnimatorListener listener){            this.mListener=listener;            return this;        }        public AnimatorParams color(int fromColor,int toColor){            this.fromColor=fromColor;            this.toColor=toColor;            return this;        }    }

With this object, I believe that those who are familiar with property animation will know how to achieve the animation effect:

    public static void startAnimator(final AnimatorParams params){        ValueAnimator heightAnimator= ValueAnimator.ofInt(params.fromHeight,params.toHeight);        heightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                ViewGroup.LayoutParams lp=params.mButton.getLayoutParams();                lp.height=(Integer)animation.getAnimatedValue();                params.mButton.setLayoutParams(lp);            }        });        ValueAnimator widthAnimator=ValueAnimator.ofInt(params.fromWidth,params.toWidth);        widthAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                ViewGroup.LayoutParams lp=params.mButton.getLayoutParams();                lp.width=(Integer)animation.getAnimatedValue();                params.mButton.setLayoutParams(lp);            }        });        CustomGradientDrawable drawable= (CustomGradientDrawable) params.mButton.getNormalDrawable();        ObjectAnimator radiusAnimator=ObjectAnimator.ofFloat(drawable,radius,params.fromCornerRadius,params.toCornerRadius);        ObjectAnimator strokeWidthAnimator=ObjectAnimator.ofInt(drawable, strokeWidth, params.fromStrokeWidth, params.toStrokeWidth);        ObjectAnimator strokeColorAnimator=ObjectAnimator.ofInt(drawable,strokeColor,params.fromStrokeColor,params.toStrokeColor);        ObjectAnimator colorAnimaor=ObjectAnimator.ofInt(drawable,color,params.fromColor,params.toColor);        colorAnimaor.setEvaluator(new ArgbEvaluator());        AnimatorSet animators=new AnimatorSet();        animators.setDuration(params.duration);        animators.play(radiusAnimator).with(strokeColorAnimator).with(strokeWidthAnimator).with(widthAnimator).with(heightAnimator).with(colorAnimaor);        animators.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                super.onAnimationEnd(animation);                params.mListener.onAnimatorEnd();            }        });        animators.start();    }

Now, the core idea of this deformed Buttom is introduced. Because the amount of code is still complicated, it is not good to paste all the code.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.