am.widget.MaterialProgressImageView.java Source code

Java tutorial

Introduction

Here is the source code for am.widget.MaterialProgressImageView.java

Source

/*
 * Copyright (C) 2015 AlexMofer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package am.widget;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.AttributeSet;
import android.widget.ImageView;

import java.util.ArrayList;

import am.drawable.MaterialProgressDrawable;

/**
 * ImageView
 * <p>
 * android.support.v4.widget.CircleImageView
 * <p>
 * Created by Alex on 2016/12/27.
 */

public class MaterialProgressImageView extends ImageView implements Animatable {

    private static final int DEFAULT_COLOR = 0xFFFAFAFA;
    private static final int SHADOW_ELEVATION = 2;
    private boolean showShadowsCircle = false;
    private float mElevation;
    private MaterialProgressDrawable drawable;
    private ShapeDrawable background;

    public MaterialProgressImageView(Context context) {
        super(context);
        initView(context, null, 0, 0);
    }

    public MaterialProgressImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context, attrs, 0, 0);
    }

    public MaterialProgressImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs, defStyleAttr, 0);
    }

    @TargetApi(21)
    public MaterialProgressImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initView(context, attrs, defStyleAttr, defStyleRes);
    }

    private void initView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        final float density = getResources().getDisplayMetrics().density;
        ArrayList<Integer> colors = new ArrayList<>();
        TypedArray custom = context.obtainStyledAttributes(attrs, R.styleable.MaterialProgressImageView,
                defStyleAttr, defStyleRes);
        boolean autoStart = custom.getBoolean(R.styleable.MaterialProgressImageView_mpiAutoStart, true);
        int color = custom.getColor(R.styleable.MaterialProgressImageView_mpiShadowsCircleColor, DEFAULT_COLOR);
        float elevation = custom.getDimension(R.styleable.MaterialProgressImageView_mpiElevation,
                density * SHADOW_ELEVATION);
        if (custom.hasValue(R.styleable.MaterialProgressImageView_mpiSchemeColor1)) {
            colors.add(custom.getColor(R.styleable.MaterialProgressImageView_mpiSchemeColor1, Color.BLACK));
        }
        if (custom.hasValue(R.styleable.MaterialProgressImageView_mpiSchemeColor2)) {
            colors.add(custom.getColor(R.styleable.MaterialProgressImageView_mpiSchemeColor2, Color.BLACK));
        }
        if (custom.hasValue(R.styleable.MaterialProgressImageView_mpiSchemeColor3)) {
            colors.add(custom.getColor(R.styleable.MaterialProgressImageView_mpiSchemeColor3, Color.BLACK));
        }
        if (custom.hasValue(R.styleable.MaterialProgressImageView_mpiSchemeColor4)) {
            colors.add(custom.getColor(R.styleable.MaterialProgressImageView_mpiSchemeColor4, Color.BLACK));
        }
        if (custom.hasValue(R.styleable.MaterialProgressImageView_mpiSchemeColor5)) {
            colors.add(custom.getColor(R.styleable.MaterialProgressImageView_mpiSchemeColor5, Color.BLACK));
        }
        custom.recycle();
        setElevationCompat(elevation);
        Drawable background = getBackground();
        if (background == null)
            setShadowsCircleBackground(color);
        drawable = new MaterialProgressDrawable(density);
        drawable.setBackgroundColor(0x00000000);
        drawable.setAlpha(255);
        drawable.setCallback(this);
        final int size = colors.size();
        if (size > 0) {
            int[] colorArray = new int[size];
            for (int i = 0; i < size; i++) {
                colorArray[i] = colors.get(i);
            }
            drawable.setColorSchemeColors(colorArray);
        }
        setImageDrawable(drawable);
        if (autoStart)
            start();
    }

    /**
     * 
     *
     * @param color 
     */
    public void setShadowsCircleBackground(int color) {
        if (background == null) {
            if (elevationSupported()) {
                background = new ShapeDrawable(new OvalShape());
            } else {
                background = new ShapeDrawable(new OvalShadow());
            }
        }
        background.getPaint().setColor(color);
        showShadowsCircle = true;
        super.setBackgroundDrawable(background);
    }

    /**
     * Sets the base elevation of this view, in pixels.
     * {@link #setShadowsCircleBackground(int)}
     */
    public void setElevationCompat(float elevation) {
        if (elevationSupported()) {
            setElevation(elevation);
        } else {
            mElevation = elevation;
        }
    }

    private boolean elevationSupported() {
        return android.os.Build.VERSION.SDK_INT >= 21;
    }

    /**
     * 
     *
     * @param backgroundColor 
     */
    @SuppressWarnings("unused")
    public void setDrawableBackgroundColor(int backgroundColor) {
        drawable.setBackgroundColor(backgroundColor);
    }

    @Override
    public void setAlpha(float alpha) {
        super.setAlpha(alpha);
        drawable.setAlpha((int) (255 * alpha));
    }

    /**
     * ??
     *
     * @param schemeColors ??
     */
    public void setColorSchemeColors(int... schemeColors) {
        drawable.setColorSchemeColors(schemeColors);
    }

    @Override
    @TargetApi(16)
    public void setBackground(Drawable background) {
        showShadowsCircle = false;
        super.setBackground(background);
    }

    @Override
    public void setBackgroundColor(int color) {
        showShadowsCircle = false;
        super.setBackgroundColor(color);
    }

    @Override
    public void setBackgroundResource(int resId) {
        showShadowsCircle = false;
        super.setBackgroundResource(resId);
    }

    @Deprecated
    @Override
    public void setBackgroundDrawable(Drawable background) {
        showShadowsCircle = false;
        super.setBackgroundDrawable(background);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (showShadowsCircle && !elevationSupported()) {
            final int moreSize = Math.round(mElevation * 2);
            setMeasuredDimension(resolveSize(getMeasuredWidth() + moreSize, widthMeasureSpec),
                    resolveSize(getMeasuredHeight() + moreSize, heightMeasureSpec));

        }
    }

    @Override
    public void start() {
        if (!drawable.isRunning()) {
            drawable.start();
        }
    }

    @Override
    public void stop() {
        if (drawable.isRunning()) {
            drawable.stop();
        }
    }

    @Override
    public boolean isRunning() {
        return drawable.isRunning();
    }

    private class OvalShadow extends OvalShape {

        private static final int FILL_SHADOW_COLOR = 0x3D000000;
        private final Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private final RectF mOvalRectF = new RectF();
        private final Matrix mMatrix = new Matrix();
        private RadialGradient mRadialGradient;

        OvalShadow() {
            mRadialGradient = new RadialGradient(10, 10, 10,
                    new int[] { FILL_SHADOW_COLOR, FILL_SHADOW_COLOR, Color.TRANSPARENT },
                    new float[] { 0, 0.6f, 1f }, Shader.TileMode.CLAMP);
            mShadowPaint.setShader(mRadialGradient);
        }

        @Override
        public void draw(Canvas canvas, Paint paint) {
            final float elevation = mElevation;
            final RectF rect = rect();
            mMatrix.reset();
            mMatrix.setScale(rect.width() * 0.05f, rect.height() * 0.05f);
            mOvalRectF.left = rect.left + elevation;
            mOvalRectF.top = rect.top + elevation;
            mOvalRectF.right = rect.right - elevation;
            mOvalRectF.bottom = rect.bottom - elevation;
            mRadialGradient.setLocalMatrix(mMatrix);
            canvas.drawOval(rect, mShadowPaint);
            canvas.drawOval(mOvalRectF, paint);
        }
    }
}