要完成自定义加载图片的九宫格的步骤
1:写一个类继承ViewGroup,同时实现他的构造方法,当然自己使用实现两个就完全可以了,不要忘了ViewGroup还有一个必须实现的方法onLaout
public classSudokuextendsViewGroup
publicSudoku(Context context) {this(context,null);}
publicSudoku(Context context, AttributeSet attrs) {this(context, attrs,0);}
publicSudoku(Context context, AttributeSet attrs,intdefStyleAttr)
{super(context, attrs, defStyleAttr); init(context,attrs);}
//这个方法是用来控制子view摆放的位置的这里我们不做处理
@Overrideprotected voidonLayout(booleanchanged,intl,intt,intr,intb) {}
//init方法是用来初始化属性的
private voidinit(Context context, AttributeSet attrs) {
this.context= context;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SudokulayoutStyle);//设置自定义属性
space= typedArray.getDimensionPixelSize(R.styleable.SudokulayoutStyle_space,10);//图片的间距
imColumn= typedArray.getInteger(R.styleable.SudokulayoutStyle_column_image,3);//一列有几张图
width=typedArray.getDimensionPixelSize(R.styleable.SudokulayoutStyle_total_width,720);//layout的宽度
maxheight=typedArray.getDimensionPixelSize(R.styleable.SudokulayoutStyle_oneimage_maxheight,810);//单张图片最大的高度
maxwidth=typedArray.getDimensionPixelSize(R.styleable.SudokulayoutStyle_oneimage_maxwidth,810);//单张图片最大的宽度
typedArray.recycle();}
//在这里我们看到了自定义属性。怎么设置自定义属性呢?需要在res文件中的values文件夹里创建atts.xml文件,已有的就不用创建了
//自定义属性设置完了那我们就需要对外放开一个方法加载图片
public voidsetImageData(int[] image){ //这里我传的参数是一个数组,因为我把图片放到资源文件里了,实际中我们传的会是一个集合或bean里面有图片的地址
if(image.length==0){//如果数组的长度为0则证明,没有图片,实际中可能是集合没有图片宽高为0
itemW=0;itemH=0; }e
lse if(image.length==1){//处理图片大小不能过界
if(getImgaeWidth(this.image[0])==0|| getImgaeHeight(this.image[0])==0){ //因为我的图片在res里所以我不知道宽和高,因此我创建了两个方法获得宽高,实际中集合的bean里应该已经包含宽和高了
itemW=(width-(imColumn+1)*space)/imColumn;
itemH=(width-(imColumn+1)*space)/imColumn; }
else{
float scaleWidth=(float) getImgaeWidth(this.image[0])/maxwidth;
float scaleHeight=(float) getImgaeHeight(this.image[0])/maxheight;
if(scaleHeight<1&& scaleWidth<1) {itemW=getImgaeWidth(this.image[0])-space*2;
itemH=getImgaeHeight(this.image[0])-space*2; }
else{
itemW= (int) (getImgaeWidth(this.image[0])/(scaleHeight>scaleWidth?scaleHeight:scaleWidth))-space*2;
itemH= (int) (getImgaeHeight(this.image[0])/(scaleHeight>scaleWidth?scaleHeight:scaleWidth))-space*2; } } }
else{
itemW=(width-(imColumn+1)*space)/imColumn;itemH=(width-(imColumn+1)*space)/imColumn; }//设置视图宽高
if(image.length==0) { setLayoutParams(newLinearLayout.LayoutParams(0,0)); }else if(image.length==1) { LinearLayout.LayoutParams params=newLinearLayout.LayoutParams(itemW,itemH); params.leftMargin= CommonUtils.dp2px(context,45); params.topMargin=CommonUtils.dp2px(context,10); setLayoutParams(params); }else{//总行数introw=(image.length-1)/imColumn+1;//最大列数intcolumn=0;if(imColumn> image.length) { column= image.length; }else{ column=imColumn; }//通过每个item的宽高计算出layout整体宽高 这里要注意因为这里new的是linearLayout所以使用时布局一定要是linearlayout,否则会报错LinearLayout.LayoutParams params=newLinearLayout.LayoutParams(space*(column+1)+column*itemW,space*(row+1)+row*itemH); params.leftMargin= CommonUtils.dp2px(context,45); params.topMargin=CommonUtils.dp2px(context,10); setLayoutParams(params); }//添加视图
if(image.length!=0) {//从来没有创建过
if(oldNum==0) { //oldnum是判断是否复用过
for(inti : image) {
ImageView imageView =newImageView(context);//这里我用的是imageview,实际中可以用自己的加载图片的方法以实现各种效果如背景默认加载什么的
addView(imageView); } }
else{//新创建的比之前的要少,则减去多余的部分
if(oldNum> image.length) {
removeViews(image.length-1,oldNum-this.image.length); }//新创建的比之前的要少,则添加缺少的部分
else if(oldNum< image.length) {
for(inti =0; i < image.length-oldNum; i++) {
ImageView imageView =newImageView(context);
addView(imageView);
} } }
oldNum= image.length; }
else{ removeAllViews();oldNum=0; }//设置每一个图片的宽高
for(inti =0; i < getChildCount(); i++) {
final inti_=i; ImageView imageView= (ImageView) getChildAt(i); imageView.setImageResource(image[i]); imageView.setOnClickListener(newOnClickListener() {@Override
public voidonClick(View v) {if(listener!=null) {listener.click(i_); } } });
introw=i/imColumn+1;intcolumn=i%imColumn+1;intleft=space*column +itemW*(column-1);
inttop=space*row +itemH*(row-1);intright=left+itemW;intbottom=top+itemH; imageView.layout(left, top, right, bottom); }
}
//获取宽和高的方法
private intgetImgaeWidth(intid){ Bitmap bitmap = BitmapFactory.decodeResource(this.getContext().getResources(), id);intwidth = bitmap.getWidth();returnwidth;}
private intgetImgaeHeight(intid){ Bitmap bitmap = BitmapFactory.decodeResource(this.getContext().getResources(), id);intheight = bitmap.getWidth();returnheight;}
以上就是自定义的所有方法了剩下的就剩在布局中使用了