Android仿朋友圈的九宫格
仿朋友圈的九宫格功能,很常见,几乎每个app都有这个功能。
一、思路:
自定义控件NineGridLayout
二、效果图:
三、关键代码:
/**
* 九宫格布局显示图片
* 1 显示1张图片的时候可以按照自适应或者长宽比
* 2 显示2张及2张以上都是正方形
* 3 4张图片显示排列方式是 2*2
*/
public abstract class NineGridLayout extends ViewGroup {
private static final float DEFUALT_SPACING = 3f;
private float image_ratio = 1.7f;//默认图片长宽比例
private int oneImageWidth;//一张图的宽度
private int oneImageHeight;//一张图的高度
protected Context mContext;
private float mSpacing = DEFUALT_SPACING;
private int mColumns;
private int mRows;
private int mTotalWidth;
private int mSingleWidth;
private boolean isNeedClick = true ; // 是否需要item的点击处理
private boolean mIsShowAll = false;
private boolean mIsFirst = true;
private List<PhotoInfo> mUrlList = new ArrayList<>();
public NineGridLayout(Context context) {
this(context, null);
}
public NineGridLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NineGridLayout);
mSpacing = typedArray.getDimension(R.styleable.NineGridLayout_sapcing, DEFUALT_SPACING);
oneImageWidth = (int) typedArray.getDimension(R.styleable.NineGridLayout_oneImageWidth, 0);
oneImageHeight = (int) typedArray.getDimension(R.styleable.NineGridLayout_oneImageHeight, 0);
image_ratio = typedArray.getFloat(R.styleable.NineGridLayout_image_ratio, image_ratio);
typedArray.recycle();
init(context);
}
public void setItemIsNeedClick(boolean isNeedClick){
this.isNeedClick = isNeedClick;
}
private void init(Context context) {
mContext = context;
if (getListSize(mUrlList) == 0) {
setVisibility(GONE);
}else {
setVisibility(VISIBLE);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
mTotalWidth = right - left;
mSingleWidth = (int) ((mTotalWidth - mSpacing * (3 - 1)) / 3);
if (mIsFirst) {//只绘制一次
notifyDataSetChanged();
mIsFirst = false;
}
}
/**
* 设置间隔
*
* @param spacing
*/
public void setSpacing(float spacing) {
mSpacing = spacing;
}
/**
* 设置是否显示所有图片(超过最大数时)
*
* @param isShowAll
*/
public void setIsShowAll(boolean isShowAll) {
mIsShowAll = isShowAll;
}
public void setUrlList(List<PhotoInfo> urlList) {
if (getListSize(urlList) == 0) {
setVisibility(GONE);
return;
}
setVisibility(VISIBLE);
mUrlList.clear();
mUrlList.addAll(urlList);
if (!mIsFirst) {//由于使用在RecyclerView中牵扯到复用布局,所以需要判断当前布局是不是第一次使用,是的话就直接绘制,不是的话就移除掉恰他的布局再绘制
notifyDataSetChanged();
}
}
public void notifyDataSetChanged() {
post(new TimerTask() {
@Override
public void run() {
refresh();
}
});
}
private void refresh() {
removeAllViews();
int size = getListSize(mUrlList);
if (size > 0) {
setVisibility(VISIBLE);
} else {
setVisibility(GONE);
return;
}
if (size == 1) {
PhotoInfo photoInfo = mUrlList.get(0);
RatioImageView imageView = createImageView(0, photoInfo.getImg());
getRealOneImageSize();
imageView.layout(0, 0, oneImageWidth, oneImageHeight);
LayoutParams params = getLayoutParams();
params.height = oneImageHeight;
setLayoutParams(params);
addView(imageView);
displayImage(0,imageView, photoInfo.getImg());
return;
}
generateChildrenLayout(size);
layoutParams();
// for (int i = 0; i < size; i++) {
// PhotoInfo photoInfo = mUrlList.get(i);
// RatioImageView imageView = createImageView(i, photoInfo.getSmallImg());
// layoutImageView(imageView, i, photoInfo.getSmallImg());
// }
//demo简单起见,只用img。实际项目可以设多一个SmallImg
for (int i = 0; i < size; i++) {
PhotoInfo photoInfo = mUrlList.get(i);
RatioImageView imageView = createImageView(i, photoInfo.getImg());
layoutImageView(imageView, i, photoInfo.getImg());
}
}
private void getRealOneImageSize() {
if(oneImageWidth==0){
oneImageWidth = mSingleWidth;
}
if(oneImageHeight==0){
oneImageHeight = (int) (oneImageWidth * image_ratio);
}
}
private void layoutParams() {
int singleHeight = mSingleWidth;
//根据子view数量确定高度
LayoutParams params = getLayoutParams();
params.height = (int) (singleHeight * mRows + mSpacing * (mRows - 1));
setLayoutParams(params);
}
private RatioImageView createImageView(final int i, final String url) {
final RatioImageView imageView = new RatioImageView(mContext);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
if(isNeedClick){
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onClickImage(i, url, mUrlList,imageView);
}
});
}
return imageView;
}
/**
* @param imageView
* @param url
*/
private void layoutImageView(RatioImageView imageView, int i, String url) {
final int singleWidth = (int) ((mTotalWidth - mSpacing * (3 - 1)) / 3);
int singleHeight = singleWidth;
int[] position = findPosition(i);
int left = (int) ((singleWidth + mSpacing) * position[1]);
int top = (int) ((singleHeight + mSpacing) * position[0]);
int right = left + singleWidth;
int bottom = top + singleHeight;
imageView.layout(left, top, right, bottom);
addView(imageView);
displayImage(i,imageView, url);
}
private int[] findPosition(int childNum) {
int[] position = new int[2];
for (int i = 0; i < mRows; i++) {
for (int j = 0; j < mColumns; j++) {
if ((i * mColumns + j) == childNum) {
position[0] = i;//行
position[1] = j;//列
break;
}
}
}
return position;
}
四、项目demo源码结构图:
有问题或者需要完整源码demo的可以看简介联系我,也可以私信我,我每天都看私信的