自定义view 图片展示 九宫格 完美适配

本文介绍了一种自定义的九宫格图片布局方案,该方案可根据图片数量自动调整布局形式,支持多图展示,并提供了图片点击事件回调。文中详细展示了自定义ViewGroup的实现过程,包括计算子视图的位置、大小及图片加载方式。
摘要由CSDN通过智能技术生成

 有一段时间没有写了,一直在赶项目,没有办法。   

项目中有一个需求 相信很多项目都会有 多图上传 然后展示多图 相信百度很多这样的开源控件。下面简单介绍我使用的这个控件


先直接上代码(包含其中所有代码)

package com.mly.view;

import java.util.List;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.mly.entity.Image;
import com.mly.util.ScreenTools;

/**
 * 
 */
public class NineGridlayout extends ViewGroup {

	/**
	 * 图片之间的间隔
	 */
	private int gap = 5;
	private int columns;//
	private int rows;//
	private List<Image> listData; //图片数量
	private int totalWidth;
	private ItemClick itemClick;

	public ItemClick getItemClick() {
		return itemClick;
	}

	public void setItemClick(ItemClick itemClick) {
		this.itemClick = itemClick;
	}

	public NineGridlayout(Context context) {
		super(context);
	}

	public NineGridlayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		ScreenTools screenTools = ScreenTools.instance(getContext());
		totalWidth = screenTools.getScreenWidth() - screenTools.dip2px(80);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {

	}

	int x = 0;

	private void layoutChildrenView() {
		int childrenCount = listData.size();
		int singleWidth;
		if (listData.size() == 1) {
			singleWidth = totalWidth;
		} else {
			singleWidth = (totalWidth - gap * (3 - 1)) / 3;
		}
		int singleHeight = singleWidth;

		// 根据子view数量确定高度
		ViewGroup.LayoutParams params = getLayoutParams();
		params.height = singleHeight * rows + gap * (rows - 1);
		setLayoutParams(params);

		for (int i = 0; i < childrenCount; i++) {
			x = i;
			// CustomImageView childrenView = (CustomImageView) getChildAt(i);
			QPImageView childrenView = (QPImageView) getChildAt(i);
			// childrenView.setImageUrl(((Image) listData.get(i)).getUrl());
			childrenView.setImageUrl(listData.get(i).getUrl());
			// 查看大图
			childrenView.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					for (int j = 0; j < getChildCount(); j++) {
						if(v==getChildAt(j)){
							if(itemClick!=null)
								itemClick.itemClick(j);
							break;
						}
					}
				}
			});

			int[] position = findPosition(i);
			int left = (singleWidth + gap) * position[1];
			int top = (singleHeight + gap) * position[0];
			int right = left + singleWidth;
			int bottom = top + singleHeight;

			childrenView.layout(left, top, right, bottom);
		}

	}

	private int[] findPosition(int childNum) {
		int[] position = new int[2];
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				if ((i * columns + j) == childNum) {
					position[0] = i;// 行
					position[1] = j;// 列
					break;
				}
			}
		}
		return position;
	}

	public int getGap() {
		return gap;
	}

	public void setGap(int gap) {
		this.gap = gap;
	}

	public void setImagesData(List<Image> lists) {
		if (lists == null || lists.isEmpty()) {
			return;
		}
		// 初始化布局
		generateChildrenLayout(lists.size());
		// 这里做一个重用view的处理
		if (listData == null) {
			int i = 0;
			while (i < lists.size()) {
				ImageView iv = generateImageView();
				addView(iv, generateDefaultLayoutParams());
				i++;
			}
		} else {
			int oldViewCount = listData.size();
			int newViewCount = lists.size();
			if (oldViewCount > newViewCount) {
				removeViews(newViewCount - 1, oldViewCount - newViewCount);
			} else if (oldViewCount < newViewCount) {
				for (int i = 0; i < newViewCount - oldViewCount; i++) {
					ImageView iv = generateImageView();
					addView(iv, generateDefaultLayoutParams());
				}
			}
		}
		listData = lists;
		layoutChildrenView();
	}
	
	

	/**
	 * 根据图片个数确定行列数量 对应关系如下 num(数量) row(行) column(列)
	 *  1 1 1        	 1 1 1 0
	 *  2 1 2 		  2 1 2 0
	 *  3 1 3 		  3 1 3 0
	 *  4 2 2        	  4 1 4 0
	 *  5 2 3 		  5 2 4
	 *  6 2 3 		  6 2 4
	 *  7 3 3		  7 2 4	
	 *  8 3 3		  8 2 4 
	 *  9 3 3		  9 3 4
	 *  			 10 3 4
	 *  			 11 3 4
	 *              	 12 4 4
	 * 
	 * @param length  //按图片数量计算行数和列数
	 */
	private void generateChildrenLayout(int length) {
		if (length <= 3) {
			rows = 1;
			columns = length;
		} else if (length <= 6) {
			rows = 2;
			columns = 3;
			if (length == 4) {
				columns = 2;
			}
		} else {
			rows = 3;
			columns = 3;
		}
	}

	private ImageView generateImageView() {   //java代码实现控件和属性 不用xml实现
		QPImageView iv = new QPImageView(getContext());
		iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
		iv.setBackgroundColor(Color.parseColor("#f5f5f5"));
		return iv;
	}
	public static interface ItemClick{
	 public void itemClick(int index);  //自定义条目点击接口
	}
}


QPImageView (自定义 可加载网络图片 使用image load)

package com.mly.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.frame.util.XHLog;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.qxp.R;

public class QPImageView extends ImageView {
	private final static String TAG="com.qpp.view.QPImageView";
	private String url;
	private ImageLoader loader = ImageLoader.getInstance();

	public QPImageView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	public QPImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	public QPImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public void setImageUrl(String url) {
		if (url.equals(this.url))
			return;
		XHLog.e(TAG, url);
		this.url = url;
		loader.displayImage(url, this);
	}
	

	public static DisplayImageOptions MyDisplayImageOptions() {  
        DisplayImageOptions options = new DisplayImageOptions.Builder()    
        .showImageOnLoading(R.drawable.loading_pic) //设置图片在下载期间显示的图片    
        .showImageForEmptyUri(R.drawable.loading_pic)//设置图片Uri为空或是错误的时候显示的图片    
        .showImageOnFail(R.drawable.loading_pic)  //设置图片加载/解码过程中错误时候显示的图片  
        .cacheInMemory(true)//设置下载的图片是否缓存在内存中    
        .cacheOnDisk(true)  
        .considerExifParams(true)  //是否考虑JPEG图像EXIF参数(旋转,翻转)  
        .imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示    
        .bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型//    
        .displayer(new RoundedBitmapDisplayer(10))//是否设置为圆角,弧度为多少    
//      .displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间    
        .build();//构建完成    
          
        return options;  
    }

	
	
}


ScreenTools(dp px 互转工具)

package com.mly.util;

import android.content.Context;

public class ScreenTools {

    private static ScreenTools mScreenTools;
    private Context context;

    private ScreenTools(Context context) {
        this.context = context.getApplicationContext();
    }

    public static ScreenTools instance(Context context) {
        if (mScreenTools == null)
            mScreenTools = new ScreenTools(context);
        return mScreenTools;
    }

    public int dip2px(float f) {
        return (int) (0.5D + (double) (f * getDensity(context)));
    }

    public int dip2px(int i) {
        return (int) (0.5D + (double) (getDensity(context) * (float) i));
    }

    public int get480Height(int i) {
        return (i * getScreenWidth()) / 480;
    }

    public float getDensity(Context context) {
        return context.getResources().getDisplayMetrics().density;
    }

    public int getScal() {
        return (100 * getScreenWidth()) / 480;
    }

    public int getScreenDensityDpi() {
        return context.getResources().getDisplayMetrics().densityDpi;
    }

    public int getScreenHeight() {
        return context.getResources().getDisplayMetrics().heightPixels;
    }

    public int getScreenWidth() {
        return context.getResources().getDisplayMetrics().widthPixels;
    }


    public float getXdpi() {
        return context.getResources().getDisplayMetrics().xdpi;
    }

    public float getYdpi() {
        return context.getResources().getDisplayMetrics().ydpi;
    }

    public int px2dip(float f) {
        float f1 = getDensity(context);
        return (int) (((double) f - 0.5D) / (double) f1);
    }

    public int px2dip(int i) {
        float f = getDensity(context);
        return (int) (((double) i - 0.5D) / (double) f);
    }

}

Image 实体类

package com.mly.entity;

/**
 * Created by Pan_ on 2015/2/3.
 */
public class Image {
    private String url;
    private int width;
    private int height;

    public Image(String url, int width, int height) {
        this.url = url;
        this.width = width;
        this.height = height;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    @Override
    public String toString() {

        return "image---->>url="+url+"width="+width+"height"+height;
    }
}

使用方法: xml 中 直接使用  包类名    高 可固定  宽不要固定


由于网络图片都是String 类型,我们解析数据得到的也是List<String>  pic   

所以我们需要转成 List<Image> data  才能被控件接受 其实很简单 new 一个  List<Image> data  for循环调用 Image.seturl(); 既可以完成。






评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值