《第二行代碼進階》 朋友圈九宮格顯示圖片

先看下效果圖:

關鍵類:NineGridLayout
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());
    }
}

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;
}

/**
 * 根據圖片個數確定行列數量
 *
 * @param length
 */
private void generateChildrenLayout(int length) {
    if (length <= 3) {
        mRows = 1;
        mColumns = length;
    } else if (length <= 6) {
        mRows = 2;
        mColumns = 3;
        if (length == 4) {
            mColumns = 2;
        }
    } else {
        mColumns = 3;
        if (mIsShowAll) {
            mRows = length / 3;
            int b = length % 3;
            if (b > 0) {
                mRows++;
            }
        } else {
            mRows = 3;
        }
    }

}

private int getListSize(List<PhotoInfo> list) {
    if (list == null || list.size() == 0) {
        return 0;
    }
    return list.size();
}



protected abstract void displayImage(int position,RatioImageView imageView, String url);

protected abstract void onClickImage(int position, String url, List<PhotoInfo> urlList, ImageView imageView);
}

牽扯到的類
RatioImageView

public class RatioImageView extends AppCompatImageView {

/**
 * 寬高比例
 */
private float mRatio = 0f;

public RatioImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

public RatioImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatioImageView);

    mRatio = typedArray.getFloat(R.styleable.RatioImageView_ratio, 0f);
    typedArray.recycle();
}

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

/**
 * 設置ImageView的寬高比
 *
 * @param ratio
 */
public void setRatio(float ratio) {
    mRatio = ratio;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int width = MeasureSpec.getSize(widthMeasureSpec);
    if (mRatio != 0) {
        float height = width / mRatio;
        heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) height, MeasureSpec.EXACTLY);
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            
            break;
        case MotionEvent.ACTION_MOVE:
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:


            break;
    }

    return super.onTouchEvent(event);
}
}

PhotoInfo

public class PhotoInfo implements Serializable {

private String img;
private int id;
private String smallImg;

public String getImg() {
    return img;
}

public void setImg(String img) {
    this.img = img;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getSmallImg() {
    return smallImg;
}

public void setSmallImg(String smallImg) {
    this.smallImg = smallImg;
}

private int photoId;
private String photoPath;
//private String thumbPath;
private int width;
private int height;
//視頻信息
private String videoId;
private String coverURL;
private String playAuth;
private int  zoneVideoId;

public PhotoInfo() {
}

public int getZoneVideoId() {
    return zoneVideoId;
}

public void setZoneVideoId(int zoneVideoId) {
    this.zoneVideoId = zoneVideoId;
}

public String getVideoId() {
    return videoId;
}

public void setVideoId(String videoId) {
    this.videoId = videoId;
}

public String getCoverURL() {
    return coverURL;
}

public void setCoverURL(String coverURL) {
    this.coverURL = coverURL;
}

public String getPlayAuth() {
    return playAuth;
}

public void setPlayAuth(String playAuth) {
    this.playAuth = playAuth;
}

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;
}

public String getPhotoPath() {
    return photoPath;
}

public void setPhotoPath(String photoPath) {
    this.photoPath = photoPath;
}

public int getPhotoId() {
    return photoId;
}

public void setPhotoId(int photoId) {
    this.photoId = photoId;
}
//
//public String getThumbPath() {
//    return thumbPath;
//}
//
//public void setThumbPath(String thumbPath) {
//    this.thumbPath = thumbPath;
//}


@Override
public boolean equals(Object o) {
    if (o == null || !(o instanceof PhotoInfo)) {
        return false;
    }
    PhotoInfo info = (PhotoInfo) o;
    if (info == null) {
        return false;
    }

    return TextUtils.equals(info.getPhotoPath(), getPhotoPath());
}
}  

注:NineGridLayout和RatioImageView非原創,在別人基礎上修改的

使用示例
MyNineGridLayout mngl = helper.getView(R.id.ngl_mood);
mngl.setUrlList(item.getZoneImgList());

//注:
public List<PhotoInfo> getZoneImgList() {
            return zoneImgList;
        }

注:MyNineGridLayout是我寫的子類,你只要同樣寫個子類,然後在重寫圖片加載顯示和點擊跳轉即可

有問題請評論或者私信我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章