android 实现图片加载效果
16lz
2021-12-04
先贴图:代码如下:
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;/** * 自定义组件实现新浪微博的图片加载效果。
* * * */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) {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();bitmapFg = createForegroundBitmap(width);//得到高度为1的红色前景色} else {// 不符合要求,自动设置为false。porterduffMode = false;}paint = new Paint();paint.setFilterBitmap(false);paint.setAntiAlias(true);paint.setTextSize(FONT_SIZE);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);}// 立即取消xfermodepaint.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 boolean isLoading() {return loading;}public void setLoading(boolean loading) {this.loading = loading;}public void setPorterDuffMode(boolean bool) {porterduffMode = bool;}}
//图片加载类
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 {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) { 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())); }}
//主activity
package com.android.activity;import android.app.Activity;import android.os.Bundle;public class ActAsyncTaskActivity extends Activity{ private PorterDuffView pViewA; 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); if (pViewA.isLoading() == false) { DownloadImgTask task = new DownloadImgTask(pViewA); task.execute(STRING_ARR[pViewA.getId() % STRING_ARR.length]); pViewA.setPorterDuffMode(true); pViewA.setLoading(true); pViewA.setProgress(0); pViewA.invalidate(); } }}
//main.xml
<?xml version="1.0" encoding="utf-8"?>
附上源码下载地址:
http://download.csdn.net/detail/duanyu218/5046973
更多相关文章
- Android(安卓)常用的ui(单选框 多选框 下拉列表框 拖动条)
- android开发常用小知识点整理
- 自定义进度条
- Android学习笔记_76_Android(安卓)ProgressBar 进度条
- 自定义实现圆形播放进度条(android,飞一般的感觉)
- Android中用AsyncTask简单实现多线程
- Android(安卓)中下载文件到sdcard和进度条小结
- 多线程实现Android更新进度条
- android中设置进度条读取