介绍一个QQ发送图片上传的控件

本文介绍如何创建一个自定义ImageView控件,用于显示图片加载过程中的进度条效果,包括实现思路、关键步骤及代码示例。

       如果你的应用中用到了发送图片这样的功能那么能够像QQ发图片那样有个类似进度条的效果是很不错的。现在就给大家介绍一个可以实现这样效果的控件。

       先说一下思路,首先显示图片我们一般用ImageView,这里也是继承ImageView,但是ImageView没有上传过程中的百分比显示,想要在ImageView加一个半透明的遮罩效果就需要自己绘制,所以,我们需要复写ImageView的onDraw方法,在这里是控件绘制的所有操作。还有,要实现动态效果,那么线程和重绘是必要的。

    现在来整理一下实现步骤

    1.继承一个ImageView控件

     2.复写onDraw方法,加上半透明效果和百分比显示

    3.加上线程控制,把上传进度发送给控件,显示出百分比并且重绘View

接下来上代码:

  

public class ProcessImageView extends ImageView {
	 
    private Paint mPaint;// 画笔
    int width = 0;
    int height = 0;
    Context context = null;
    int progress = 0;
 
    public ProcessImageView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
 
    public ProcessImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
 
    public ProcessImageView(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        mPaint = new Paint();
    }
 
    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setAntiAlias(true); // 消除锯齿
        mPaint.setStyle(Paint.Style.FILL);
         
 
        mPaint.setColor(Color.parseColor("#70000000"));// 半透明
        canvas.drawRect(0, 0, getWidth(), getHeight()- getHeight() * progress
                / 100, mPaint);
 
        mPaint.setColor(Color.parseColor("#00000000"));// 全透明
        canvas.drawRect(0, getHeight() - getHeight() * progress / 100,
                getWidth(), getHeight(), mPaint);
 
        mPaint.setTextSize(30);
        mPaint.setColor(Color.parseColor("#FFFFFF"));
        mPaint.setStrokeWidth(2);
        Rect rect = new Rect();
        mPaint.getTextBounds("100%", 0, "100%".length(), rect);// 确定文字的宽度
        canvas.drawText(progress + "%", getWidth() / 2 - rect.width() / 2,
                getHeight() / 2, mPaint);
 
    }
 
    public void setProgress(int progress) {
        this.progress = progress;
        postInvalidate();
    };
 
}

      首先声明了五个变量,实际上用到的只有三个,第一个是画笔mPaint用来绘制View,第二个是上下文Context不用多解释,第三个progress,进度这个必须有。其余两个暂时没用到,忽略不计


      接下来就是复写ImageVie w的OnDraw方法,所有View都是在这里绘制的,我们需要自己定义什么绘制内容的时候就需要在这里添加。      

      先是画笔的设置

     

        mPaint.setAntiAlias(true); // 消除锯齿
        mPaint.setStyle(Paint.Style.FILL);

       接下来就是最重要的半透明层的绘制

      

        mPaint.setColor(Color.parseColor("#70000000"));// 半透明
        canvas.drawRect(0, 0, getWidth(), getHeight()- getHeight() * progress
                / 100, mPaint);
 
        mPaint.setColor(Color.parseColor("#00000000"));// 全透明
        canvas.drawRect(0, getHeight() - getHeight() * progress / 100,
                getWidth(), getHeight(), mPaint);


      设置画笔的颜色,然后在画布canvas上指定绘制的范围按照左上右下四个参数分别传入,下部的位置就是整个View的高度减去下面已经透明的高度,通过progress除以100得出的百分比来设定。最后一个参数是画笔。

       绘制透明部分的逻辑也是一样。不多做解释

       最后,绘制文字,也就是显示出来的百分比

      

        mPaint.setTextSize(30);
        mPaint.setColor(Color.parseColor("#FFFFFF"));
        mPaint.setStrokeWidth(2);
        Rect rect = new Rect();
        mPaint.getTextBounds("100%", 0, "100%".length(), rect);// 确定文字的宽度
        canvas.drawText(progress + "%", getWidth() / 2 - rect.width() / 2,
                getHeight() / 2, mPaint);


       只要是绘制内容,必定先设置画笔属性。这里特别说明一下Rect的作用,Rect是一个矩形区域的意思,它作为获取文字宽度的一个参数,意思是将文字区域的一些属性放到rect里,有人会问文字不是可以直接获取长度等属性吗?抱歉,这里文字只能得到长度,但是这里我们不能把它认为成一个字符串,我们是要绘制的,所以要把它当成一个图片。把文字的一些信息放到rect里。同样指定绘制的位置

       现在我们会发现,这些都是静态的,怎么能让他显示出效果呢?这里就用到我们的线程了,这里需要复习一个方法,用来更新View

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


这里的progress就是用来更新的。需要配合Activity里的线程更新View,postInvalidate()就是通知更新View的方法

下面是Activity的内容

public class MainActivity extends Activity {
 
    ProcessImageView processImageView =null;
    private final int SUCCESS=0;
    int progress=0;
     
    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
            case SUCCESS:
                Toast.makeText(MainActivity.this, "图片上传完成", Toast.LENGTH_SHORT).show();
//                processImageView.setVisibility(View.GONE);
                break;
            }
        }
    };
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
      processImageView=(ProcessImageView) findViewById(R.id.image);
        //模拟图片上传进度
        new Thread(new Runnable() {
            @Override
            public void run() {
                 while (true){  
                     if(progress==100){//图片上传完成
                         handler.sendEmptyMessage(SUCCESS);
                         return;
                     }
                     progress++;
                     processImageView.setProgress(progress);
                    try{  
                        Thread.sleep(200);  //暂停0.2秒
                    } catch (InterruptedException e){  
                        e.printStackTrace();  
                    }  
                }  
            }
        }).start();
    }
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}


主要就是开一个线程不断的用set方法刷新VIew用Handler接收成功消息

使用方法跟普通自定义组件一样,还可以对其进行扩展,请发挥想象力吧。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值