仿新浪微博的图片加载

此文转载,非本人原创
package com.android.activity;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

public class ActAsyncTaskActivity extends Activity implements OnClickListener {
    private PorterDuffView pViewA, pViewB, pViewC, pViewD;
    public static final String[] STRING_ARR = {//
    "http://developer.android.com/images/home/android-jellybean.png",//
                    "http://developer.android.com/images/home/design.png",//
                    "http://developer.android.com/images/home/google-play.png",//
                    "http://developer.android.com/images/home/google-io.png" };

    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            pViewA = (PorterDuffView) findViewById(R.id.pViewA);
            pViewA.setOnClickListener(this);
            pViewB = (PorterDuffView) findViewById(R.id.pViewB);
            pViewB.setOnClickListener(this);
            pViewC = (PorterDuffView) findViewById(R.id.pViewC);
            pViewC.setOnClickListener(this);
            pViewD = (PorterDuffView) findViewById(R.id.pViewD);
            pViewD.setOnClickListener(this);
    }

    public void onClick(View v) {
            if (v instanceof PorterDuffView) {
                    PorterDuffView pdView = (PorterDuffView) v;
                    if (pdView.isLoading() == false) {
                            DownloadImgTask task = new DownloadImgTask(pdView);
                            task.execute(STRING_ARR[pdView.getId() % STRING_ARR.length]);
                            pdView.setPorterDuffMode(true);
                            pdView.setLoading(true);
                            pdView.setProgress(0);
                            pdView.invalidate();
                    }
            }
    }
}

package com.android.activity;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;


public class DownloadImgTask extends AsyncTask<String, Float, Bitmap> {
	private static final String TAG="DownloadImgTask";    
	private PorterDuffView pdView;
        

        public DownloadImgTask(PorterDuffView pdView) {
                this.pdView = pdView;
        }

        /** 下载准备工作。在UI线程中调用。 */
        protected void onPreExecute() {
        	Log.i(TAG, "onPreExecute");
        }

        /** 执行下载。在背景线程调用。 */
        protected Bitmap doInBackground(String... params) {
        	Log.i(TAG, "doInBackground:" + params[0]);
                HttpClient httpClient = new DefaultHttpClient();
                HttpGet httpGet = new HttpGet(params[0]);
                InputStream is = null;
                ByteArrayOutputStream baos = null;
                try {
                        HttpResponse httpResponse = httpClient.execute(httpGet);
                        printHttpResponse(httpResponse);
                        HttpEntity httpEntity = httpResponse.getEntity();
                        long length = httpEntity.getContentLength();
                        Log.i(TAG, "content length=" + length);
                        is = httpEntity.getContent();
                        if (is != null) {
                                baos = new ByteArrayOutputStream();
                                byte[] buf = new byte[128];
                                int read = -1;
                                int count = 0;
                                while ((read = is.read(buf)) != -1) {
                                        baos.write(buf, 0, read);
                                        count += read;
                                        publishProgress(count * 1.0f / length);
                                }
                                Log.i(TAG, "count=" + count + " length=" + length);
                                byte[] data = baos.toByteArray();
                                Bitmap bit = BitmapFactory.decodeByteArray(data, 0, data.length);
                                return bit;
                        }
                } catch (ClientProtocolException e) {
                        e.printStackTrace();
                } catch (IOException e) {
                        e.printStackTrace();
                } finally {
                        try {
                                if (baos != null) {
                                        baos.close();
                                }
                                if (is != null) {
                                        is.close();
                                }
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
                return null;
        }

        /** 更新下载进度。在UI线程调用。onProgressUpdate */
        protected void onProgressUpdate(Float... progress) {
                // LogOut.out(this, "onProgressUpdate");
                pdView.setProgress(progress[0]);
        }

        /** 通知下载任务完成。在UI线程调用。 */
        protected void onPostExecute(Bitmap bit) {
        		Log.i(TAG, "onPostExecute");
                pdView.setPorterDuffMode(false);
                pdView.setLoading(false);
                pdView.setImageBitmap(bit);
        }

        protected void onCancelled() {
        		Log.i(TAG, "DownloadImgTask cancel...");
                super.onCancelled();
        }

        private void printHttpResponse(HttpResponse httpResponse) {
                Header[] headerArr = httpResponse.getAllHeaders();
                for (int i = 0; i < headerArr.length; i++) {
                        Header header = headerArr[i];
                        Log.i(TAG, "name[" + header.getName() + "]value[" + header.getValue() + "]");
                }
                HttpParams params = httpResponse.getParams();
                Log.i(TAG, String.valueOf(params));
                Log.i(TAG, String.valueOf(httpResponse.getLocale()));
        }
}

package com.android.activity;



import java.text.DecimalFormat;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

/**
 * 自定义组件实现新浪微博的图片加载效果。<br/>
 * 
 * 
 * 
 */
public class PorterDuffView extends ImageView {
		private static final String TAG="PorterDuffView";
        /** 前景Bitmap高度为1像素。采用循环多次填充进度区域。 */
        public static final int FG_HEIGHT = 1;
        /** 下载进度前景色 */
        // public static final int FOREGROUND_COLOR = 0x77123456;
        public static final int FOREGROUND_COLOR = 0x77ff0000;
        /** 下载进度条的颜色。 */
        public static final int TEXT_COLOR = 0xff7fff00;
        /** 进度百分比字体大小。 */
        public static final int FONT_SIZE = 30;
        private Bitmap bitmapBg, bitmapFg;
        private Paint paint;
        /** 标识当前进度。 */
        private float progress;
        /** 标识进度图片的宽度与高度。 */
        private int width, height;
        /** 格式化输出百分比。 */
        private DecimalFormat decFormat;
        /** 进度百分比文本的锚定Y中心坐标值。 */
        private float txtBaseY;
        /** 标识是否使用PorterDuff模式重组界面。 */
        private boolean porterduffMode;
        /** 标识是否正在下载图片。 */
        private boolean loading;

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

        /** 生成一宽与背景图片等同高为1像素的Bitmap,。 */
        private static Bitmap createForegroundBitmap(int w) {
                Bitmap bm = Bitmap.createBitmap(w, FG_HEIGHT, Bitmap.Config.ARGB_8888);
                Canvas c = new Canvas(bm);
                Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
                p.setColor(FOREGROUND_COLOR);
                c.drawRect(0, 0, w, FG_HEIGHT, p);
                return bm;
        }

        private void init(Context context, AttributeSet attrs) {
                if (attrs != null) {
                        // //
                        // int count = attrs.getAttributeCount();
                        // for (int i = 0; i < count; i++) {
                        // LogOut.out(this, "attrNameRes:" +
                        // Integer.toHexString(attrs.getAttributeNameResource(i))//
                        // + " attrName:" + attrs.getAttributeName(i)//
                        // + " attrResValue:" + attrs.getAttributeResourceValue(i, -1)//
                        // + " attrValue:" + attrs.getAttributeValue(i)//
                        // );
                        // }
                        // //

                        TypedArray typedArr = context.obtainStyledAttributes(attrs, R.styleable.PorterDuffView);
                        porterduffMode = typedArr.getBoolean(R.styleable.PorterDuffView_porterduffMode, false);
                }
                Drawable drawable = getDrawable();
                if (porterduffMode && drawable != null && drawable instanceof BitmapDrawable) {
                        bitmapBg = ((BitmapDrawable) drawable).getBitmap();
                        width = bitmapBg.getWidth();
                        height = bitmapBg.getHeight();
                        // LogOut.out(this, "width=" + width + " height=" + height);
                        bitmapFg = createForegroundBitmap(width);
                } else {
                        // 不符合要求,自动设置为false。
                        porterduffMode = false;
                }

                paint = new Paint();
                paint.setFilterBitmap(false);
                paint.setAntiAlias(true);
                paint.setTextSize(FONT_SIZE);

                // 关于FontMetrics的详情介绍,可见:
                // <a href="\"http://xxxxxfsadf.iteye.com/blog/480454\"" target="\"_blank\"">http://xxxxxfsadf.iteye.com/blog/480454</a>
                Paint.FontMetrics fontMetrics = paint.getFontMetrics();
                // 注意观察本输出:
                // ascent:单个字符基线以上的推荐间距,为负数
                Log.i(TAG, "ascent:" + fontMetrics.ascent//
                                // descent:单个字符基线以下的推荐间距,为正数
                                + " descent:" + fontMetrics.descent //
                                // 单个字符基线以上的最大间距,为负数
                                + " top:" + fontMetrics.top //
                                // 单个字符基线以下的最大间距,为正数
                                + " bottom:" + fontMetrics.bottom//
                                // 文本行与行之间的推荐间距
                                + " leading:" + fontMetrics.leading);
                // 在此处直接计算出来,避免了在onDraw()处的重复计算
                txtBaseY = (height - fontMetrics.bottom - fontMetrics.top) / 2;

                decFormat = new DecimalFormat("0.0%");
        }

        public void onDraw(Canvas canvas) {
                if (porterduffMode) {
                        int tmpW = (getWidth() - width) / 2, tmpH = (getHeight() - height) / 2;
                        // 画出背景图
                        canvas.drawBitmap(bitmapBg, tmpW, tmpH, paint);
                        // 设置PorterDuff模式
                        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
                        // canvas.drawBitmap(bitmapFg, tmpW, tmpH - progress * height,
                        // paint);
                        int tH = height - (int) (progress * height);
                        for (int i = 0; i < tH; i++) {
                                canvas.drawBitmap(bitmapFg, tmpW, tmpH + i, paint);
                        }

                        // 立即取消xfermode
                        paint.setXfermode(null);
                        int oriColor = paint.getColor();
                        paint.setColor(TEXT_COLOR);
                        paint.setTextSize(FONT_SIZE);
                        String tmp = decFormat.format(progress);
                        float tmpWidth = paint.measureText(tmp);
                        canvas.drawText(decFormat.format(progress), tmpW + (width - tmpWidth) / 2, tmpH + txtBaseY, paint);
                        // 恢复为初始值时的颜色
                        paint.setColor(oriColor);
                } else {
                        Log.i(TAG, "onDraw super");
                        super.onDraw(canvas);
                }
        }

        public void setProgress(float progress) {
                if (porterduffMode) {
                        this.progress = progress;
                        // 刷新自身。
                        invalidate();
                }
        }

        public void setBitmap(Bitmap bg) {
                if (porterduffMode) {
                        bitmapBg = bg;
                        width = bitmapBg.getWidth();
                        height = bitmapBg.getHeight();

                        bitmapFg = createForegroundBitmap(width);

                        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
                        txtBaseY = (height - fontMetrics.bottom - fontMetrics.top) / 2;
                        
                        setImageBitmap(bg);
                        // 请求重新布局,将会再次调用onMeasure()
                        // requestLayout();
                }
        }

        public boolean isLoading() {
                return loading;
        }

        public void setLoading(boolean loading) {
                this.loading = loading;
        }

        public void setPorterDuffMode(boolean bool) {
                porterduffMode = bool;
        }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:porterduff="http://schemas.android.com/apk/res/com.android.activity"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
	<ScrollView 
	    android:layout_width="fill_parent"
	    android:layout_height="fill_parent"
	    android:orientation="vertical"
	    >
	    <LinearLayout 
	        android:layout_width="fill_parent"
		    android:layout_height="fill_parent"
		    android:orientation="vertical"
		    >
		    <TextView
		        android:layout_width="fill_parent"
		        android:layout_height="wrap_content"
		        android:text="点击loading开始下载..." />
		    <com.android.activity.PorterDuffView
				android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:id="@+id/pViewA"
		        android:src="@drawable/weibo1"
		        android:layout_gravity="center"
		        porterduff:porterduffMode="true"
			    />
		    <com.android.activity.PorterDuffView
				android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:id="@+id/pViewB"
		        android:src="@drawable/weibo1"
		        android:layout_gravity="center"
		        porterduff:porterduffMode="true"
			    />
		    <com.android.activity.PorterDuffView
				android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:id="@+id/pViewC"
		        android:src="@drawable/weibo1"
		        android:layout_gravity="center"
		        porterduff:porterduffMode="true"
			   />
		    <com.android.activity.PorterDuffView
				android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:id="@+id/pViewD"
		        android:src="@drawable/weibo1"
		        android:layout_gravity="center"
		        porterduff:porterduffMode="true"
			    >
		        
		    </com.android.activity.PorterDuffView>
		    
		</LinearLayout>
	</ScrollView>
</LinearLayout>
attrs.xml
<?xml version="1.0" encoding="UTF-8"?>
<resources>
	<!--请参阅
	[android_sdk]\platforms\android-n\data\res\values\attrs.xml
	-->
	<declare-styleable name="PorterDuffView">
	        <attr name="porterduffMode" format="boolean"></attr>
	</declare-styleable>
</resources>

http://download.csdn.net/detail/fuweiping/4742079

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值