Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 自定義ViewGroup打造微信朋友圈之九宮圖效果

自定義ViewGroup打造微信朋友圈之九宮圖效果

編輯:關於Android編程

本文參考了manymore13文章邏輯,在此基礎上做了改進:
1.可定義最大行數
2.定義每行顯示幾張
3.當圖片數量過多時設置更多圖片
由於個人較懶,去掉了xml配置屬性,所有屬性在java代碼中設置。
先看代碼:

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

import com.bumptech.glide.Glide;

/**
 * Desc:類似微信朋友圈圖片展示
 * Author:gcy
 * Date:2016/8/24
 */

public class MultiImageView extends ViewGroup {

    /**
     * 單行最多圖片數
     */
    public final static int LINE_MAX_COUNT = 3;

    /**
     * 這裡是九宮圖
     */
    public final static int MAX_IMG_COUNT = 9;

    /**
     * 每行最大圖片數
     */
    public int mLineMaxCount = LINE_MAX_COUNT;

    /**
     * 圖片地址
     */
    private String[] mImgUrls;

    /**
     * 圖片的數量
     */
    private int mImgCount;

    /**
     * 圖片之間的間距
     */
    private int mPicSpace = 5;

    /**
     * 子view邊長度
     */
    private int mChildEdgeSize;

    /**
     * 子view可見個數
     */
    private int mChildVisibleCount;

    /**
     * 這裡是九宮格 所以設置為數值9
     */
    private int mMaxChildCount = MAX_IMG_COUNT;

    /**
     * 是否截斷點擊事件
     */
    private boolean mIntercept = false;

    /**
     * 服務器上縮略圖最大尺寸
     */
    private static final int maxPicSize = 250;

    /**
     * 單張圖片寬度
     */
    private int mSingleSrcWidth;

    /**
     * 單張圖片高度
     */
    private int mSingleSrcHeight;

    /**
     * 單張圖片時控件期望的邊的最大的大小
     */
    private int mSingleExpectMaxViewSize;

    private float mSingleExpectMaxViewRatio = 0.8f;

    /**
     * 單張圖片時圖片縮放比例
     */
    private float mSingleScaleRatio;

    /**
     * 各個圖片點擊事件回調
     */
    private ClickCallback mClickCallback;


    private class OnClickListener implements View.OnClickListener {
        int index;

        public OnClickListener(int i) {
            index = i;
        }

        @Override
        public void onClick(View view) {
            if (mClickCallback != null) {
                mClickCallback.callback(index, mImgUrls);
            }
        }
    }


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

    public MultiImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPicSpace = 10;
        mSingleExpectMaxViewSize = 500;
        mSingleExpectMaxViewSize = 300;

    }

    /**
     * 初始化該控件
     *
     * @param len
     */
    public void setMaxChildCount(int len) {
        removeAllViews();
        mMaxChildCount = len;

        for (int i = 0; i < len; i++) {
            ImageView iv = new ImageView(getContext());
            LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.MATCH_PARENT);
            iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
            // iv.setOnClickListener(mClickListener);
            //iv.setTag(i);
            this.addView(iv, params);
        }
    }


    /**
     * 單張圖時調用 ,注意 這裡寬高需要服務器提供
     * 因為在你下載圖片時是不知道圖片大小的
     * 所以需要服務器告訴你
     *
     * @param imgUrl    圖片地址
     * @param srcWidth  圖片寬度
     * @param srcHeight 圖片高度
     */
    public void setSingleImg(String imgUrl, int srcWidth, int srcHeight) {
        mLineMaxCount = 1;
        int maxSize = Math.max(srcWidth, srcHeight);
        mSingleScaleRatio = 1f;
        if (maxSize > mSingleExpectMaxViewSize) {
            mSingleScaleRatio = maxSize * 1.0f / mSingleExpectMaxViewSize;
        }

        mSingleSrcWidth = (int) (srcWidth / mSingleScaleRatio);
        mSingleSrcHeight = (int) (srcHeight / mSingleScaleRatio);
        boolean request = false;
        mImgUrls = new String[]{imgUrl};
        if (mImgUrls != null && mImgUrls.length == 1) {
            request = true;
        }
        dealWithImgs(mImgUrls);
        if (request) {
            this.requestLayout();
        }
    }

    /**
     * 顯示多張圖片(兩張以上)圖片 傳圖片數組進去
     * 你在外部使用時需要把圖片傳進去
     *
     * @param imgs 圖片url數組
     */
    public void setImgs(String[] imgs, int lineImg) {
        mLineMaxCount = lineImg;

        mSingleSrcHeight = mSingleSrcWidth = 0;
        mSingleScaleRatio = 1;
        dealWithImgs(imgs);
    }

    private int moreResId ;
    public void setMoreImgBg(int resid){
        this.moreResId = resid ;
    }

    /**
     * 設置是否攔截事件
     *
     * @param intercept true 事件攔截
     */
    public void setIntercept(boolean intercept) {
        mIntercept = intercept;
    }

    /**
     * 設置圖片點擊回調
     *
     * @param callback 事件回調
     */
    public void setClickCallback(ClickCallback callback) {
        mClickCallback = callback;
    }

    /**
     * 點擊圖片回調
     */
    public interface ClickCallback {
        /**
         * 回調方法
         *
         * @param index 點擊的索引
         * @param str   圖片地址數組
         */
        void callback(int index, String[] str);
    }

    /**
     * 獲取圖片可能顯示多少行數
     *
     * @param imgSize 圖片個數
     * @return 行數
     */
    public int getMultyImgLines(int imgSize) {
        if (imgSize == 0) {
            return 1;
        }
        return (imgSize + mLineMaxCount - 1) / mLineMaxCount;
    }

    /**
     * 獲取當前圖片數量
     *
     * @return 數量
     */
    public int getImgCount() {
        return mImgCount;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mIntercept;
    }

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

        int lpadding = getPaddingLeft();
        int tpadding = getPaddingTop();
        int left = lpadding, top = tpadding;
        int childCount = getChildCount();
        int visibleChildCount = mChildVisibleCount;
        int breakLineC = 0; // 斷行
        if (visibleChildCount == 4) {
            // 當四張圖片時 兩張時換行
            breakLineC = 2;
        } else {
            // 每行三張圖片換行
            breakLineC = mLineMaxCount;
        }
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == View.GONE) {
                continue;
            }
            if (visibleChildCount == 1) {
                // 單張做特殊顯示
                if (mLineMaxCount == 1) {
//                    left = (getMeasuredWidth() - mSingleSrcWidth) / 2;// 居中
                    left = lpadding; // 居左
                }
                if (mSingleSrcWidth == 0 || mSingleSrcHeight == 0) {
                    child.layout(left, top, left + mChildEdgeSize,
                            top + mChildEdgeSize);
                } else {
                    child.layout(left, top, left + mSingleSrcWidth,
                            top + mSingleSrcHeight);
                }
            } else {
                child.layout(left, top, left + mChildEdgeSize,
                        top + mChildEdgeSize);
                left += (mPicSpace + mChildEdgeSize);
                if ((i + 1) % breakLineC == 0) {
                    top += mChildEdgeSize + mPicSpace;
                    left = lpadding;
                }
            }
        }
    }

    /**
     * 確定九宮圖控件自身的大小以及內部ImageView的大小
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        if (getChildCount() == 0) {
            setMaxChildCount(mMaxChildCount);
        }
        measureImgWidth(widthMeasureSpec);
        mChildVisibleCount = getVisibleChildCount();
        int lines = getMultyImgLines(mChildVisibleCount);
        int viewHeight = ((lines - 1) * mPicSpace + lines * mChildEdgeSize)
                + getPaddingTop() + getPaddingBottom();
        if (mChildVisibleCount == 1) {
            viewHeight = mSingleSrcHeight == 0 ? viewHeight : mSingleSrcHeight;
        }
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        setMeasuredDimension(widthSize, viewHeight);

        int heightSize = mChildEdgeSize;
        widthSize = heightSize;
        if (mChildVisibleCount == 1 && mSingleSrcWidth != 0) {
            widthSize = mSingleSrcWidth;
            heightSize = mSingleSrcHeight;
        }
        measureChildren(widthSize, heightSize);
    }

    /**
     * 計算圖片的大小
     *
     * @param widthMeasureSpec
     */
    protected void measureImgWidth(int widthMeasureSpec) {
        if (mChildEdgeSize == 0) {
            int measureSize = MeasureSpec.getSize(widthMeasureSpec);
            mChildEdgeSize = (measureSize - (mLineMaxCount - 1) * mPicSpace
                    - getPaddingLeft() - getPaddingRight()) / mLineMaxCount;
        }
    }

    /**
     * 獲取可見圖片數量
     */
    private int getVisibleChildCount() {
        int childCount = getChildCount();
        int count = 0;
        for (int i = 0; i < childCount; i++) {
            if (getChildAt(i).getVisibility() != View.GONE) {
                count++;
            }
        }
        return count;
    }

    /**
     * 處理圖片
     *
     * @param imgs 圖片地址列表
     */
    private void dealWithImgs(String[] imgs) {
        if (imgs == null || imgs.length == 0) {
            return;
        }
        mImgUrls = imgs;
        mImgCount = imgs.length;
        int imgLen = mImgCount;
        int maxChildCount = mMaxChildCount;
        for (int i = 0; i < maxChildCount; i++) {
            final int index = i;
            final ImageView chileIv = (ImageView) getChildAt(i);
            chileIv.setOnClickListener(new OnClickListener(index));
            if (i < imgLen) {
                if (i == maxChildCount - 1) {
                    if (mImgCount > maxChildCount) {
                        chileIv.setImageResource(this.moreResId);
                        continue;
                    }
                }
                chileIv.setVisibility(View.VISIBLE);
                String url = imgs[i];

                Glide.with(getContext()).load(url).into(chileIv);
            } else {
                chileIv.setVisibility(View.GONE);
            }
        }
    }

}

代碼中使用:

multiImageView.setMaxChildCount(12);
        multiImageView.setMoreImgBg(R.mipmap.ic_launcher);
        multiImageView.setImgs(urls, 4);
//如果只包含一張圖片     //multiImageView.setSingleImg("http://img4.duitang.com/uploads/item/201502/11/20150211005650_AEyUX.jpeg",400,300);
        multiImageView.setClickCallback(new MultiImageView.ClickCallback() {
            @Override
            public void callback(int index, String[] str) {
                Log.e("TAG", "dianjin le " + index);
            }
        });

效果圖:
這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved