1. 程式人生 > >介紹一個QQ傳送圖片上傳的控制元件

介紹一個QQ傳送圖片上傳的控制元件

       如果你的應用中用到了傳送圖片這樣的功能那麼能夠像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接收成功訊息

使用方法跟普通自定義元件一樣,還可以對其進行擴充套件,請發揮想象力吧。