Android 自定义阴影进度实现仿QQ图片上传

首先上效果:
注意下面圆角哦
图片上传一半啦
上传马上结束啦

实现步骤:
一、首先attrs增加自定义属性:

<!-- ProgressImageView -->
    <declare-styleable name="ProgressImageView">
        <!--图片圆角大小-->
        <attr name="roundPixel" format="dimension|reference"></attr>
        <!--是否启用进度-->
        <attr name="useProgress" format="boolean"></attr>
        <!--进度影音色值-->
        <attr name="roundShadowColor" format="color|reference"></attr>
        <!--进度文字大小-->
        <attr name="roundProgressTextSize" format="dimension|reference"></attr>
        <!--进度文字大小-->
        <attr name="roundProgressTextColor" format="color|reference"></attr>
    </declare-styleable>

代码中使用该AttributeSet:

if (attrs != null) {
            TypedArray t = getResources().obtainAttributes(attrs, R.styleable.ProgressImageView);
            Log.e("getDimension:", t.getDimension(R.styleable.ProgressImageView_progressTextSize1, 1) + "");
            Log.e("getDimensionPixelOffset:", 
            t.recycle();
        }

这里需要注意的是:
1.getDimension(int index, int defValue)
如果xml中使用的是pixel,则返回结果结果为float pixel,如果xml中使用的是dp/dip,则返回的是转换之后(转换请查看TypedValue.applyDimension(int unit, float value,DisplayMetrics metrics))的float pixel值,如果xml中使用的是sp,则返回的是转换之后(转换请查看TypedValue.applyDimension(int unit, float value,DisplayMetrics metrics))的float pixel值,如果xml未使用该值且attrs不为null时返回的直接是float defValue(单位为像素)的值
2.getDimensionPixelOffset(int index, int defValue)
如果xml中使用的是pixel,则返回结果结果为int pixel,如果xml中使用的是dp/dip,则返回的是转换之后(转换请查看TypedValue.applyDimension(int unit, float value,DisplayMetrics metrics))的int pixel值,如果xml中使用的是sp,则返回的是转换之后(转换请查看TypedValue.applyDimension(int unit, float value,DisplayMetrics metrics))的float pixel值,如果xml未使用该值且attrs不为null时返回的直接是int defValue的值
3.getDimensionPixelSize(int index, int defValue)
如果xml中使用的是pixel,则返回结果结果为int pixel,如果xml中使用的是dp/dip,则返回的是转换之后(转换请查看TypedValue.applyDimension(int unit, float value,DisplayMetrics metrics))的int pixel值,如果xml中使用的是sp,则返回的是转换之后(转换请查看TypedValue.applyDimension(int unit, float value,DisplayMetrics metrics))的float pixel值,如果xml未使用该值且attrs不为null时返回的直接是int defValue的值。

二、自定义ProgressImageView实现圆角进度绘制:

/**
 * @author wzz
 * @lastModify wzz
 * @date 2016-12-13 11:35
 * @description ProgressImageView  TODO(实现图片上传进度绘制的ImageView)
 */
public class ProgressImageView extends ImageView {
    /***************** 外部可改变值 *****************/
    /**
     * 进度值
     */
    private float progress;
    /**
     * 圆角大小,单位pixel
     */
    private int roundPixel = 0;
    /**
     * 是否使用进度值蒙版
     */
    private boolean useProgress = false;
    /**
     * 阴影的颜色
     */
    private int roundShadowColor;
    /**
     * 进度文字大小
     */
    private float roundProgressTextSize;
    /**
     * 进度文字颜色
     */
    private int roundProgressTextColor;

    /***************** 内部使用值 *****************/
    /**
     * 画笔对象
     */
    private Paint paint;
    /**
     * 两张图片相交时的模式
     */
    private Xfermode xfermode;
    /**
     * 进度文字区域Rect
     */
    private Rect rect;
    /**
     * 圆角矩形所占RectF
     */
    private RectF rectF;
    /**
     * float格式化成99.99% String
     */
    private NumberFormat numberFormat;

    public ProgressImageView(Context context) {
        super(context);
        init(null);
    }

    public ProgressImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        if (attrs != null) {
            TypedArray t = getResources().obtainAttributes(attrs, R.styleable.ProgressImageView);
            roundPixel = t.getDimensionPixelSize(R.styleable.ProgressImageView_roundPixel, 0);
            useProgress = t.getBoolean(R.styleable.ProgressImageView_useProgress, false);
            roundShadowColor = t.getColor(R.styleable.ProgressImageView_roundShadowColor, Color.parseColor("#a6292929"));
            roundProgressTextSize = t.getDimensionPixelSize(R.styleable.ProgressImageView_roundProgressTextSize,
                    (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 17, getResources().getDisplayMetrics()));
            roundProgressTextColor = t.getColor(R.styleable.ProgressImageView_roundProgressTextColor, Color.WHITE);
            t.recycle();
        } else {
            roundShadowColor = Color.parseColor("#a6292929");
            roundProgressTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 17, getResources().getDisplayMetrics());
            roundProgressTextColor = Color.WHITE;
        }
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        rect = new Rect();
        numberFormat = NumberFormat.getPercentInstance();
        numberFormat.setMaximumFractionDigits(2);
    }

    public boolean isUseProgress() {
        return useProgress;
    }

    public void setUseProgress(boolean useProgress) {
        this.useProgress = useProgress;
    }

    public int getRoundPixel() {
        return roundPixel;
    }

    public void setRoundPixel(int roundPixel) {
        this.roundPixel = roundPixel;
    }

    public float getProgress() {
        return progress;
    }

    public void setProgress(float progress) {
        this.progress = progress;
        postInvalidate();
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (useProgress) {
            canvas.saveLayer(0, 0, getWidth(), getHeight(), paint, Canvas.ALL_SAVE_FLAG);
            //带阴影的圆角矩形框
            paint.setColor(roundShadowColor);
            if (null == rectF) {
                rectF = new RectF(0, 0, getWidth(), getHeight());
            }
            canvas.drawRoundRect(rectF, roundPixel, roundPixel, paint);
            //设置两张图片相交时的模式
            paint.setXfermode(xfermode);
            //上部分阴影
            paint.setColor(roundShadowColor);
            canvas.drawRect(0, 0, getWidth(), getHeight() * (1 - progress), paint);
            //下部分透明
            paint.setColor(Color.TRANSPARENT);
            canvas.drawRect(0, getHeight() * (1 - progress), getWidth(), getHeight(), paint);
            if (progress < 1f) {
                paint.setXfermode(null);
                paint.setTextSize(roundProgressTextSize);
                paint.setColor(roundProgressTextColor);
                paint.setStrokeWidth(2);
                String progressStr = numberFormat.format(progress);
                paint.getTextBounds(progressStr, 0, progressStr.length(), rect);
                Paint.FontMetricsInt metricsInt = paint.getFontMetricsInt();
                canvas.drawText(progressStr, getWidth() / 2 - rect.width() / 2, (getHeight() - metricsInt.bottom - metricsInt.top) / 2, paint);
            }
        }
    }
}

三、使用方法
1.布局引入

<com.test.widget.ProgressImageView
            android:id="@+id/uploadImageView"
            android:layout_width="191dp"
            android:layout_height="309dp"
            android:layout_gravity="center_horizontal"
            android:scaleType="fitXY"
            app:roundPixel="20dp"
            app:roundProgressTextColor="#00ff00"
            app:roundProgressTextSize="18sp"
            app:roundShadowColor="#a6292929"
            app:useProgress="true" />

2.界面代码实现

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.wzz_okhttp_test_activity);
        uploadImageView = (ProgressImageView) findViewById(R.id.uploadImageView);

        //注:由于ProgressView未加入圆角图片剪切,因此此处使用的Universal ImageLoader的加载圆角图片的功能
        DisplayImageOptions picture_container_options = new DisplayImageOptions.Builder()
                .considerExifParams(false) // 调整图片方向
                .bitmapConfig(Bitmap.Config.RGB_565)//设置图片的质量
                .imageScaleType(ImageScaleType.IN_SAMPLE_INT)// 设置图片的缩放类型,该方法可以有效减少内存的占用
                .resetViewBeforeLoading(false) // default 设置图片在加载前是否重置、复位
                .delayBeforeLoading(0) // 载入之前的延迟时间
                .cacheInMemory(true) // default 设置下载的图片是否缓存在内存中
                .cacheOnDisk(false) // default 设置下载的图片是否缓存在SD卡中
                .displayer(new RoundedBitmapDisplayer((int) SysUtils.convertDpToPixel(20))) // default
                .showImageOnLoading(R.mipmap.empty_photo) // 设置图片下载期间显示的图片
                .showImageForEmptyUri(R.mipmap.empty_photo) // 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.mipmap.empty_photo) // 设置图片加载或解码过程中发生错误显示的图片
                // 设置图片的解码类型
                // .decodingOptions(...) // 图片的解码设置
                // .handler(new Handler()) // default
                .build();
        ImageLoader.getInstance().displayImage("file://" + localImagePath, uploadImageView, picture_container_options);
    }
    private ProgressImageView uploadImageView;
    private float progress = 0f;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (progress >= 1) {
                progress = 1f;
                uploadImageView.setProgress(progress);
            } else {
                progress += 0.01f;
                uploadImageView.setProgress(progress);
                handler.sendEmptyMessageDelayed(123, 300);
            }
        }
    };


    public void startUpload(View view) {
        handler.sendEmptyMessageDelayed(123, 300);
    }

当然如果配置较好的话还可以实现圆形图片进度,不信你看:
底部阴影效果
顶部阴影效果

如发现问题请与我联系我 QQ:459985120

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值