package com.cpm.demo.meilishuo.app.views.PhotoViewGroup;import java.io.InputStream;import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import com.cpm.demo.meilishuo.R;import com.cpm.demo.meilishuo.SimulateData;import com.cpm.demo.meilishuo.app.views.PhotoScrollView;import com.cpm.demo.meilishuo.app.views.eClass;import com.cpm.demo.meilishuo.app.views.gClass;import com.cpm.demo.meilishuo.app.views.iClass;import com.cpm.demo.meilishuo.app.views.q_Interface;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;/** * @作者:陈培敏 * @创建时间:2012-8-28 下午11:56:20 (1)四个方法中用到:Rect.intersects */public class PhotoViewGroup extends ViewGroup {//com.meilishuo.app.views.bprivate static boolean  isShowLog=false;String TAG = PhotoViewGroup.class.getName();String TAG2 = PhotoViewGroup.class.getName()+"2";String TAG3 = PhotoViewGroup.class.getName()+"3";private Context context;// aprivate int imageWidth;// 固定的图片宽度,bprivate ExecutorService executorService;// dprivate List<ImageInfo> list = new ArrayList();// e,要显示的ImageInfo列表,跟map的区别是,(1)list中数据可能有重复;(2)list直接放入内存中;(3)map采用软引用private Map<Integer, SoftReference> map = new HashMap();// f,private ReferenceQueue refQueue = new ReferenceQueue();/** 三张图片top位置 **/private int[] tops = new int[3];// h/** 三张图片left位置 **/private int[] lefts = new int[3];// iprivate PhotoScrollView photoScriollView;// jprivate Paint paint;// 作用是什么呢?kprivate final int imageSpace = 10;// 图片之间的间隔//  private int l;//  private final int m = 0;//  private final int n = 1;  private int o_datatype;//  private boolean p = false;//  private View.OnClickListener q;/**点击的效果**/private View.OnClickListener r = new ImageDataViewClickListener(this);/***   **/public PhotoViewGroup(Context context) {super(context);this.context = context;if(isShowLog)if(isShowLog) Log.d(TAG, "PhotoShowView=>宽度" + getWidth());}/*** 测试数据 **/public void test_SimulateData() {this.setBackgroundColor(Color.GREEN);ImageInfo pi = new ImageInfo();pi.rect = new Rect(10, 10, 100, 120);pi.width = 20;pi.height = 20;//ImageDataView imageData = new ImageDataView(context);imageData.setBitmap(SimulateData.getImageRefBitmap(context));imageData.setTag(pi);pi.imageData = imageData;/** 以下如果没有图片,讲通过http获取,所以才需要post线程获取 **/post(new ImageAddRunnable(this, pi));}/***   **/@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {if(isShowLog) if(isShowLog) Log.d(TAG, "=>onLayout=>getChildCount():" + getChildCount());for (int i = 0; i < getChildCount(); ++i) {View childView = getChildAt(i);Rect rect = ((ImageInfo) childView.getTag()).rect;childView.layout(rect.left, rect.top, rect.right, rect.bottom);}}/***   **/@Overrideprotected final void onMeasure(int paramInt1, int paramInt2) {if(isShowLog) if(isShowLog) Log.d(TAG,"onMeasure=>传递过参数:" + paramInt1 + "-" + paramInt2+ "=>getChildCount():" + getChildCount() + ";屏幕宽度"+ this.getWidth());super.onMeasure(paramInt1, paramInt2);for (int i2 = 0; i2 < getChildCount(); ++i2) {View localView = getChildAt(i2);ImageInfo localba = (ImageInfo) localView.getTag();localView.measure(View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.EXACTLY));System.out.println("onMeasure=>childView参数:" + localba.width + "-"+ localba.height);}int i4 = 0;//获取top最大值for (int i = 0; i < this.tops.length; ++i) {if (i4 < this.tops[i]) {i4 = this.tops[i];} else {}}System.out.println("onMeasure=>setMeasuredDimension参数:"+ View.MeasureSpec.getSize(paramInt1) + "-" + i4);// 指定该控件在屏幕上的大小super.setMeasuredDimension(View.MeasureSpec.getSize(paramInt1), i4);}/**初始化PhotoScriollView、list以及各个变量值<br/> * (1)在MainHotActivity的a()调用到<br/> * (2)在加入数据前,一定要执行此方法*/public final void intiDefaultData() {// public final void a()if(isShowLog) if(isShowLog) Log.d(TAG, "================================获取不到宽度,我手动添加!测试长高=>width:" + this.getWidth() + ",height:"+ this.getHeight());q_Interface localq = this.photoScriollView.a();this.photoScriollView.a(null);this.photoScriollView.scrollTo(0, 0);//this.list.clear();//if(isShowLog) if(isShowLog) Log.d(TAG3, "this.list.clear()");//initVariable(getWidth());//为什么获取不到widthinitVariable(540);if (this.executorService != null) {this.executorService.shutdownNow();this.executorService = Executors.newFixedThreadPool(5);}removeAllViews();// this.p = false;this.photoScriollView.a(localq);}private void initVariable(int screenWidth) {// private void b(int paramInt)this.imageWidth = ((screenWidth - imageSpace * 4) / 3);for (int i = 0; i < this.tops.length; ++i)this.tops[i] = 0;// 初始化,不固定的for (int i = 0; i < this.lefts.length; ++i)this.lefts[i] = (imageSpace * (i + 1) + i * this.imageWidth);// 初始化left位置,固定的if (true) {this.paint = new Paint();this.paint.setColor(-2236963);this.paint.setStyle(Paint.Style.STROKE);this.paint.setStrokeWidth(1.0F);return;}}/*** * (1)在滚动时候,要加载数据,会报错:java.util.ConcurrentModificationException * 如果方法加入synchronized,就不会报错,但view空出一个区域出来(滚动速度稍微快点)。 * (2) * @param imageInfos */public final  void loadList(List<ImageInfo> imageInfos) {// public final void  a(List paramList)if(isShowLog) if(isShowLog) Log.d(TAG, "loadList,start=>图片列表大小:" + imageInfos.size() + "=>getChildCount:"+ this.getChildCount() + "=>屏幕宽度:" + this.getWidth());this.o_datatype = 30020;// this.o = 30020;Iterator localIterator = imageInfos.iterator();ImageInfo imageInfo = null;while (localIterator.hasNext()) {imageInfo = (ImageInfo) localIterator.next();Rect localRect = new Rect();// 找出top最小值和位置int minTopValue = this.tops[0];int minPos = 0;for (int i3 = 1; i3 < this.tops.length; i3++) {if(isShowLog) if(isShowLog) Log.d(TAG, "loadList,比较tops:"+i3+"=>minTopValue:"+minTopValue+"=>tops["+i3+"]:"+this.tops[i3]);if (minTopValue <= this.tops[i3])continue;else {minTopValue = this.tops[i3];minPos = i3;}}if(isShowLog) if(isShowLog) Log.d(TAG, "loadList,最低位置:"+minPos+"=>对于的值:"+tops[minPos]);{// 自己添加的缩放比例;或放在加载时间时候判断;甚至也放在服务器上。imageInfo.height = this.imageWidth * imageInfo.height / imageInfo.width;imageInfo.width = this.imageWidth;}this.tops[minPos] = (imageSpace + this.tops[minPos]);//localRect.left = this.lefts[minPos];localRect.top = this.tops[minPos];localRect.right = (imageInfo.width + this.lefts[minPos]);localRect.bottom = (this.tops[minPos] + imageInfo.height);// 赋值布局区域imageInfo.rect = localRect;// 因为添加一张图片,所以tops[minPos]变高了this.tops[minPos] += imageInfo.height;// 加入列表this.list.add(imageInfo);if(isShowLog) if(isShowLog) Log.d(TAG3, "this.list.add(imageInfo);");if(isShowLog) if(isShowLog) Log.d(TAG, "loadList=>返回imageInfo.rect值:" + localRect.left + "-"+ localRect.top + "-" + localRect.right + "-"+ localRect.bottom);// 判断两个rect是否相交,有的话就显示处理// if// ((Rect.intersects(getCanLookRect(this.photoScriollView.getScrollY()),// imageInfo.rect))){// // 注意下反编译代码// loadImage(imageInfo, true);// //return; or continue;// }else{// if(isShowLog) if(isShowLog) Log.d(TAG, "loadList=>区域是没有交叉,未执行加载图片");// continue;// }loadImage(imageInfo, true);}}/** * 加载数据 * @param paramList * @param paramInt */public final void loadList(List paramList, int paramInt){//public final void a(List paramList, int paramInt)this.o_datatype = paramInt;loadList(paramList);}/*** * 在屏幕上能看到的区域<br/> * 终于搞懂了!!必须要知道: * (1)getTop的含义(相对父View) * (2)getScrollY()的含义 * (3)PhotoViewGroup放在PhotoScrollView里面,所以产生滚动条是PhotoScrollView。 *   滚动条在最下面的时候,会往PhotoViewGroup自动加入数据,所以PhotoViewGroup会变得原来越长了, *   而PhotoViewGroup看不到的数据,在PhotoScrollView最上面,那哪些数据能看到呢?此方法就是计算能看到的区域 * (4)通过允许,就可以看到区域left肯定0,right就是宽度,top通过_top判断的,bottom通过top和height判断的 * @param _top   意思是PhotoViewGroup头部距离PhotoScrollView头部的距离 * @return */private Rect getCanLookRect(int _top) {// private Rect c(int paramInt)// if(isShowLog) Log.d(TAG,// "了解getTop与getScrollY的=>getTop:"+this.getTop()+"--getScrollY:"+this.getScrollY());int height = this.photoScriollView.getHeight();// 注意这个是photoScriollView高度,而不是调用this.getHeight()int i3 = 0;;if (_top < getTop()) {// 这时候PhotoShowView头部都可以在屏幕上看到,出现这样子原因是photoScriollView还有其他view在PhotoShowView上面int i4 = height - (getTop() - _top);if(isShowLog) Log.d(TAG2, "getCanLookRect=>返回Rect值1:" + getLeft() + "-" + i3 + "-"+ getRight() + "-" + i4 + "=>宽度:" + this.getWidth()+ "=>高度:" + this.getHeight()+"=>"+_top);return new Rect(getLeft(), i3, getRight(), i4);// getLeft()、getRight()固定,所以只关心上和下} else {// 这时候PhotoShowView头部都在屏幕上看不到i3 = _top - getTop();int i4 = i3 + height;// 放在这边,还是上面那句呢?if(isShowLog) Log.d(TAG2, "getCanLookRect=>返回Rect值2:" + getLeft() + "-" + i3 + "-"+ getRight() + "-" + i4 + "=>宽度:" + this.getWidth()+ "=>高度:" + this.getHeight()+"=>"+_top);return new Rect(getLeft(), i3, getRight(), i4);}}private void loadImage(ImageInfo imageInfo, boolean isGetFromHttp) {// private void a(ba paramba, boolean paramBoolean)if(isShowLog) Log.d(TAG, "执行方法loadImage----------------开始------------");if (imageInfo.imageData == null) {// 首次运行的时候,每一张图片信息的imageData都为空的。则要实例下(没有图片数据呢,先占用图片空间,然后图片再从http下载或从SD中加载)if(isShowLog) Log.d(TAG, "执行方法loadImage,构建空的图片");ImageDataView imageData = new ImageDataView(this.context);imageData.setTag(imageInfo);imageInfo.imageData = imageData;imageData.setOnClickListener(this.r);// 点击的操作,暂时不设置吧post(new ImageAddRunnable(this, imageInfo));}if(!isGetFromHttp)return;imageInfo.hasLoaded=true;if (true) {Bitmap localBitmap1 = null;if (this.map.get(Integer.valueOf(imageInfo.id)) != null) {localBitmap1 = (Bitmap) ((SoftReference) this.map.get(Integer.valueOf(imageInfo.id))).get();if(isShowLog) Log.d(TAG, "执行方法loadImage,成功从map获取数据,这次没通过SD卡或HTTP获取数据");}if (localBitmap1 == null) {/** * 根据反编译信息,可以看出原理(设计太多类,不用了): (1)通过imageInfo.url获取MD5唯一数据标志 * =>e.java (2)定义图片的字节数组imgByte * (3)从缓存(其实是从SD卡获取之前保持的数据)中获取数据赋值给imgByte =>i.java * (4)获取没有缓存,则只能从http获取了 => 本类a(imageInfo)方法 **/String md5Url = null;// 获取MD5唯一数据标志byte[] arrayOfByte = null;// 从SD卡获取图片数据=>什么时候存储SD数据呢,答案是在下载的时候,存储SD卡中// if (iClass.a(md5Url)) {//如果文件存在// arrayOfByte = iClass.b(md5Url);//从SD卡获取之前保持的数据// if ((arrayOfByte == null) || (arrayOfByte.length ==// 0))//如果获取的数据位空// iClass.c(str);//删除该文件// }if ((arrayOfByte == null) || (arrayOfByte.length == 0)) {downImageByHttp(imageInfo);// 图片为空启动下载,第一次加载都会首先执行这个} else {// 没从SD卡获取,所以这里都还没执行Bitmap localBitmap2 = createScaledBitmapByByte(arrayOfByte,this.imageWidth);// 根据图片字节 伸缩图片if (localBitmap2 == null) {// i.c(new String(e.a(paramba.e.getBytes())));// //删除SD中的文件。paramba.e是ImageInfo.urldownImageByHttp(imageInfo);// 找不到图片,则启动下载}if(isShowLog) Log.d(TAG, "loadImage=>addMap=>" + localBitmap2);addMap(imageInfo.id, localBitmap2);imageInfo.imageData.setBitmap(localBitmap2);}} else {imageInfo.imageData.setBitmap(localBitmap1);}}}/** 通过字节转换Bitmap,且固定width高度自动伸缩。注意这个方法是static **/private static Bitmap createScaledBitmapByByte(byte[] paramArrayOfByte,int width) {// private static Bitmap b(byte[] paramArrayOfByte, int// paramInt)Bitmap localBitmap1 = BitmapFactory.decodeByteArray(paramArrayOfByte,0, paramArrayOfByte.length);if(isShowLog) Log.d("com.cpm.demo.meilishuo.myview.PhotoShowView","createBitmapByByte1=>要显示的width:" + width + "=>图片高度:"+ localBitmap1.getHeight() + "=>图片宽度:"+ localBitmap1.getWidth() + "=>" + localBitmap1);Bitmap localBitmap2 = null;if (localBitmap1 != null) {localBitmap2 = Bitmap.createScaledBitmap(localBitmap1, width, width* localBitmap1.getHeight() / localBitmap1.getWidth(), true);localBitmap1.recycle();}if(isShowLog) Log.d("com.cpm.demo.meilishuo.myview.PhotoShowView","createBitmapByByte2=>要显示的width:" + width + "=>图片高度:"+ localBitmap2.getHeight() + "=>图片宽度:"+ localBitmap2.getWidth() + "=>" + localBitmap2);return localBitmap2;}/** 往map加入图片源,map格式是SoftReference **/protected void addMap(int id, Bitmap bitmap) {// private void a(int// paramInt, Bitmap// paramBitmap)synchronized (this.map) {if (this.map.containsKey(Integer.valueOf(id))) {return;}this.map.put(Integer.valueOf(id), new SoftReference(bitmap,this.refQueue));checkMap();}}/** 通过http下载图片 **/private void downImageByHttp(ImageInfo paramba) {// private void a(ba// paramba)if(isShowLog) Log.d(TAG, "执行方法downImageByHttp");// 反编译认真看下if (paramba.httpCilent == null) {ImageDownloadRunnable localay = new ImageDownloadRunnable(this,paramba);if (this.executorService == null)this.executorService = Executors.newFixedThreadPool(5);this.executorService.execute(localay);}}/* 作用? */private void checkMap() {// b();/** * SoftReference localSoftReference = (SoftReference) * this.refQueue.poll(); Map.Entry localEntry = null; if * (localSoftReference != null) { Iterator iterator = * this.map.entrySet().iterator(); while(iterator.hasNext()){ localEntry * = (Map.Entry) iterator.next(); if (localEntry!=null ) { int value = * ((Integer) localEntry.getKey()).intValue(); if (value == -1) * this.map.remove(Integer.valueOf(value)); return; } } } **/label0: {if(isShowLog) Log.d(TAG, "checkMap()=>作用待确定");SoftReference localSoftReference = (SoftReference) this.refQueue.poll();Map.Entry localEntry = null;if (localSoftReference != null) {Iterator localIterator = this.map.entrySet().iterator();do {if (!(localIterator.hasNext()))break;localEntry = (Map.Entry) localIterator.next();} while (localEntry.getValue() != localSoftReference);}if (localEntry != null)for (int i1 = ((Integer) localEntry.getKey()).intValue();; i1 = -1) {if (i1 != -1);this.map.remove(Integer.valueOf(i1));break label0;}}}private Rect getRect(int paramInt) {return new Rect(getLeft(), 0, getRight(), 100);}public final void setPhotoScrollView(PhotoScrollView paramPhotoScrollView) {this.photoScriollView = paramPhotoScrollView;}/**  * 滚动条变化的时候,判断list * (1)滚动条是在PhotoScrollView产生的,所以这个方法专门给PhotoScrollView的onScrollChanged方法调用 */public final  void a_optimizeListData(int paramInt) {// bClass=> public final void a(int paramInt)if(isShowLog) Log.d(TAG2, "方法a(int)=>list大小:"+this.list.size()+"=>宽度:"+this.getWidth()+"=>参数:"+paramInt);Rect localRect = this.getCanLookRect(paramInt);Iterator localIterator = this.list.iterator();if(isShowLog) Log.d(TAG3, "this.list.iterator()");while (localIterator.hasNext()) {ImageInfo localba = (ImageInfo) localIterator.next();//会报错: java.util.ConcurrentModificationException,为什么呢?原因用iterator遍历集合时要注意的地方:不可以对iterator相关的地方做添加或删除操作。  但是我在哪里操作了呢?滚动条滚动时候,此方法未执行完,再执行一次了?if(isShowLog) Log.d(TAG2, "方法a(int)=>id:"+localba.id+"=>是否交叉:"+Rect.intersects(localRect, localba.rect)+"=>localba.是否已加载:"+localba.hasLoaded+"---------->"+(Rect.intersects(localRect, localba.rect)?"":"-----------------------有看不见了"));if (localba.hasLoaded && !Rect.intersects(localRect, localba.rect)) {//已加载,且没有交叉,图片设空,节约内存吧?localba.hasLoaded = false;//从list获取出来对象,再对对象修改属性,这个时候list对象也会修改的。if (localba.httpCilent != null) {ImageDownloadRunnable.HttpCilent(localba.httpCilent);//作用?localba.httpCilent = null;}localba.imageData.setBitmap(null);}//if ((localba.isGetFromHttp) || (!(Rect.intersects(localRect, localba.rect))))//continue;//this.loadImage(localba, true);//改成下面:if (!localba.hasLoaded && Rect.intersects(localRect, localba.rect) )this.loadImage(localba, true);}}/**给每一张图片,画边框。其实这里可以放在ImageDataView了,没必要在这里设置,因为ImageDataView已经有实现此功能=》红边**/protected final boolean drawChild(Canvas paramCanvas, View paramView,long paramLong) {Rect localRect = new Rect();paramView.getHitRect(localRect);int i1 = Math.max(0, 1);localRect.top -= i1;localRect.left -= i1;paramCanvas.drawRect(localRect, this.paint);return super.drawChild(paramCanvas, paramView, paramLong);}//  protected final void onSizeChanged(int paramInt1, int paramInt2, int paramInt3, int paramInt4)//  {//    super.onSizeChanged(paramInt1, paramInt2, paramInt3, paramInt4);//    if (paramInt1 == paramInt3)//      return;//    b(paramInt1);//  }}

更多相关文章

  1. 一句话锁定MySQL数据占用元凶
  2. 福利篇:学习编程视频免费领取
  3. 为何Android普通APP可以执行私有数据中的so文件,而system app却不
  4. Android(安卓)GifImageView加载Gif图片及原理
  5. 非985、211毕业,我是如何加入腾讯的?(附Android通关秘籍)
  6. Android(安卓)getIdentifier()使用
  7. Android官方MVP架构项目解析
  8. 在Android工程中,添加ICON资源
  9. Android范例编程一:获取地理位置

随机推荐

  1. Linux下配置NDK、JDK环境变量
  2. android在线源码地址
  3. android的小疑点:You need to use a Theme
  4. 在eclipse右键new菜单项中添加android ap
  5. 检测手机类型正则表达式
  6. android代码常识
  7. ArcGIS API for Android(安卓)案例教程 1
  8. Android requires compiler compliance l
  9. 学习网址
  10. Android 6.0 PowerManagerService 一