下载文件使用子线程,更新到UI上使用handler,效果如图:

主要代码如下:

    public void downFile(final String httpUrl,final Handler handler) {        new Thread(new Runnable() {            @Override            public void run() {                try {                    File file = null;                    URL url = new URL(httpUrl);                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();                    connection.setRequestMethod("GET");                    connection.setConnectTimeout(5000);                    FileOutputStream fileOutputStream = null;                    InputStream inputStream;                    if (connection.getResponseCode() == 200) {                        inputStream = connection.getInputStream();                        if (inputStream != null) {                            file = getFile(httpUrl);                            delFile(file.getAbsolutePath());                            fileOutputStream = new FileOutputStream(file);                            byte[] buffer = new byte[1024];                            int length = 0;                            int total = 0;                            int max = connection.getContentLength();                            while ((length = inputStream.read(buffer)) != -1) {                                fileOutputStream.write(buffer, 0, length);                                total += length;                                Message msg = handler.obtainMessage();                                msg.what = LoadingActivity.DOWNLOADING;                                msg.arg1 = (int)(total*100/max);                                handler.sendMessage(msg);                            }                            fileOutputStream.close();                            fileOutputStream.flush();                        }                        inputStream.close();                    }                    Message message = handler.obtainMessage();                    message.what = LoadingActivity.DOWNLOAD_COMPLETE;                    handler.sendMessage(message);                    installApk(file);                } catch (MalformedURLException e) {                    e.printStackTrace();                } catch (IOException e) {                    e.printStackTrace();                }            }        }).start();    }    /**     * 根据传过来url创建文件     *      */    private  File getFile(String url) {        File files = new File(Environment.getExternalStorageDirectory().getAbsoluteFile(), getFilePath(url));        return files;    }    /**     * 截取出url后面的apk的文件名     *      * @param url     * @return     */    private  String getFilePath(String url) {        return url.substring(url.lastIndexOf("/"), url.length());    }    /***     * 删除临时存放的文件     *      * @param url     *            文件路径     */    private  void delFile(String url) {        File myFile = new File(url);        if (myFile.exists()) {            myFile.delete();        }    }    /**     * 安装APK     */    private void installApk(File file) {        Intent intent = new Intent(Intent.ACTION_VIEW);        intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");        context.startActivity(intent);        context.finish();    }

然后在handler中处理UI:

    private Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            int what = msg.what;            switch(what) {            case DOWNLOAD_COMPLETE:                break;            case DOWNLOADING:                int percent = (int)msg.arg1;                progressBar.setProgress(percent);                break;            }        };    };

下面重点说下自定义的进度条

    public RoundProgressBar(Context context) {        this(context, null);    }    public RoundProgressBar(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public RoundProgressBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        paint = new Paint();        TypedArray mTypedArray = context.obtainStyledAttributes(attrs,                R.styleable.RoundProgressBar);        roundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.RED);        roundProgressColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.GREEN);        textColor = mTypedArray.getColor(R.styleable.RoundProgressBar_textColor, Color.GREEN);        textSize = mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 15);        roundWidth = mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 5);        max = mTypedArray.getInteger(R.styleable.RoundProgressBar_max, 100);        textIsDisplayable = mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable, true);        style = mTypedArray.getInt(R.styleable.RoundProgressBar_style, 0);        mTypedArray.recycle();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int centre = getWidth()/2;         int radius = (int) (centre - roundWidth/2);         paint.setColor(roundColor);         paint.setStyle(Paint.Style.STROKE);         paint.setStrokeWidth(roundWidth);         paint.setAntiAlias(true);         canvas.drawCircle(centre, centre, radius, paint);        paint.setStrokeWidth(0);         paint.setColor(textColor);        paint.setTextSize(textSize);        paint.setTypeface(Typeface.DEFAULT_BOLD);         int percent = (int)(((float)progress / (float)max) * 100);          float textWidth = paint.measureText(percent + "%");          if(textIsDisplayable && percent != 0 && style == STROKE){            canvas.drawText(percent + "%", centre - textWidth / 2, centre + textSize/2, paint);         }        paint.setStrokeWidth(roundWidth);         paint.setColor(roundProgressColor);         RectF oval = new RectF(centre - radius, centre - radius, centre                + radius, centre + radius);          switch (style) {        case STROKE:{            paint.setStyle(Paint.Style.STROKE);            canvas.drawArc(oval, 0, 360 * progress / max, false, paint);            break;        }        case FILL:{            paint.setStyle(Paint.Style.FILL_AND_STROKE);            if(progress !=0)                canvas.drawArc(oval, 0, 360 * progress / max, true, paint);              break;        }        }    }    public synchronized int getMax() {        return max;    }    public synchronized void setMax(int max) {        if(max < 0){            throw new IllegalArgumentException("max not less than 0");        }        this.max = max;    }    public synchronized int getProgress() {        return progress;    }    public synchronized void setProgress(int progress) {        if(progress < 0){            throw new IllegalArgumentException("progress not less than 0");        }        if(progress > max){            progress = max;        }        if(progress <= max){            this.progress = progress;            postInvalidate();        }    }    public int getCricleColor() {        return roundColor;    }    public void setCricleColor(int cricleColor) {        this.roundColor = cricleColor;    }    public int getCricleProgressColor() {        return roundProgressColor;    }    public void setCricleProgressColor(int cricleProgressColor) {        this.roundProgressColor = cricleProgressColor;    }    public int getTextColor() {        return textColor;    }    public void setTextColor(int textColor) {        this.textColor = textColor;    }    public float getTextSize() {        return textSize;    }    public void setTextSize(float textSize) {        this.textSize = textSize;    }    public float getRoundWidth() {        return roundWidth;    }    public void setRoundWidth(float roundWidth) {        this.roundWidth = roundWidth;    }

类RoundProgressBar继承于view,基本属性在attr.xml中去定义,而我们需要关注的是setProgress(),因为封装的RoundProgressBar,我们都是通过调用setProgress()方法去刷新进度,在这个方法中也是不断调用postInvalidate()方法,即不断去draw,接下来就是我们的重头戏onDraw()了:
我们可以将此view分为三部分,
1. 圆形的圈(空心的);
2. 中间的文字加百分比符号,统一为字符串;
3. 弧形的圈。
通过这样分析,就简单啦~
自定义view少不了跟android的画笔paint和canvas打交道。

paint.setColor(roundColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(roundWidth); paint.setAntiAlias(true); canvas.drawCircle(centre, centre, radius, paint);

其中的canvas.drawCircle(float cx, float cy, float radius, Paint paint)表示以(cx,cy) 为中心,radius为半径画一个圆。paint.setStrokeWidth(roundWidth)表示画的圆的外围的宽度。
这样我们的空心圆就出来了~
接下来就是画中间的字符串:

paint.setStrokeWidth(0); paint.setColor(textColor);paint.setTextSize(textSize);paint.setTypeface(Typeface.DEFAULT_BOLD); int percent = (int)(((float)progress / (float)max) * 100);  float textWidth = paint.measureText(percent + "%"); canvas.drawText(percent + "%", centre - textWidth / 2, centre + textSize/2, paint);  

其中canvas.(String text, float x, float y, Paint paint)表示以坐标(x,y)为中心,画出文字text,这里我们使用paint.measureText(text)方法,使得画出的文字能居中。
最后就是画弧度了:

paint.setStrokeWidth(roundWidth); paint.setColor(roundProgressColor); RectF oval = new RectF(centre - radius, centre - radius, centre+radius, centre + radius);  paint.setStyle(Paint.Style.STROKE);canvas.drawArc(oval, 0, 360 * progress / max, false, paint);

canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)表示用长方形画出sweepAngle角度的弧度。这里我试了设置画笔Paint.Style.STROKE和Paint.Style.FILL_AND_STROKE效果一样的,然后就是长方形的四个坐标,找了半天没找到笔,只能口述了~假设有个中心点center,那左上角left的物理坐标就是centre-left,以此类推~

好了,自定义进度条下载apk并更新已讲解完,自己也对自定义view有更好的理解了,哈哈~

更多相关文章

  1. Android(安卓)jni 编程(参数的传递,成员,方法的)相互访问
  2. android JB2连拍降速原理介绍
  3. android 利用pull解析xml数据
  4. Android(安卓)获取View高度的4种方法
  5. Android系统源码导入到eclipse
  6. 安装APK文件的错误码定义
  7. android 开发 onRestart()未调用

随机推荐

  1. MySQL 5.7.19安装目录下创建my.ini文件的
  2. windows server2016安装MySQL5.7.19解压
  3. Mysql 5.7.19 免安装版遇到的坑(收藏)
  4. Mysql 5.7.19 免安装版配置方法教程详解(
  5. 关于mysql查询字符集不匹配问题的解决方
  6. Mysql数据库绿色版安装教程 解决系统错误
  7. sqlite迁移到mysql脚本的方法
  8. mysql分页时offset过大的Sql优化经验分享
  9. MySQL5.7.18主从复制搭建(一主一从)教程
  10. Mysql5.7.18的安装与主从复制图文详解