Android開源:SImageView - 方便實用的圖片控件
控件介紹
這是一個簡單到 sImageView.setImageUrls; 設置一個網址即可顯示圖片的控件
相對 ImageView 功能的擴展的控件, 但是沒有繼承 ImageView 直接繼承的 View . 比如 QQ群組頭像 , 微信群組頭像 , 設置描邊 , 設置圓角矩形頭像 , 圓形頭像 等. 幾個參數搞定. 對于 多個圖片的排列 和 圖片的具體顯示 進行了接口分離. 可以自定義實現任何排列效果和顯示效果.
網絡圖片的下載會原圖緩存磁盤, 并根據控件的大小加載到到內存并使用顯示.
效果展示
圖片可能比較大, 如果不出現, 刷新頁面試試或者多等一會.
可以實現的樣式
使用說明
引用方式
rootDir/app/build.gradle文件
dependencies {
// ...
compile 'com.szysky.customize:simageview:2.2';
}
xml聲明方式
<LinearLayout xmlns:android="
<!--簡單的配置, 默認為圓形圖像,無描邊-->
// 直接設置一個圖片URL即可, 根據控件大小進行內存緩存, 保存原圖到本地磁盤緩存
sImageView.setImageUrls("關于群組頭像
// 如果你想實現QQ群組效果, 很簡單因為默認是圓形類型顯示, 不需要多余設置
// 直接傳入多個URL, 最多支持5張. 例如
sImageView.setImageUrls(
"
// 需要微信的樣式, 那么改一下 布局管理器 , 并設置顯示圖片類型為 矩形,
// 最多支持9張. 如下
sImageView.setDisplayShape(SImageView.TYPE_RECT)
.setLayoutManager(new WeChatLayoutManager(getApplicationContext()))
.setImageUrls(
"以下是常用方法
SImageView sImageView = (SImageView) itemView.findViewById(R.id.siv);
// 設置描邊顏色
sImageView.setBorderColor(Color.GREEN);
// 設置描邊寬度 單位dp值
sImageView.setBorderWidth(1);
// 設置圖片顯示類型
// 可設置類型: SImageView.TYPE_CIRCLE(默認), SImageView.TYPE_OVAL,
// SImageView.TYPE_RECT, SImageView.TYPE_ROUND_RECT,
// SImageView.TYPE_FIVE_POINTED_STAR
sImageView.setDisplayShape(SImageView.TYPE_ROUND_RECT);
// 設置圖片的縮放類型, 只有顯示類型為矩形, 并且描邊寬度為0. 才有效果. 區別在xml中有說明
// 可選類型3種:SCALE_TYPE_CENTER_INSIDE(默認),
// SCALE_TYPE_FIX_XY ,SCALE_TYPE_CENTER_CROP
mSImageView.setScaleType(SImageView.SCALE_TYPE_CENTER_INSIDE);
// 設置微信群組樣式顯示. (可以自定義measure測量排列規則)替換measure測量策略如下:
// 默認為qq群組的測量策略. 只要設置圖片時傳入多張圖片的集合即可.
sImageView.setLayoutManager(new WeChatLayoutManager(context));
// 不僅可以設置url數組, 還支持其他設置圖片方式
sImageView.setImages(List<Bitmap>); // 接收一個bitmap集合, 實現qq群組或者微信群組效果
sImageView.setIdRes(id); // 接收圖片資源id
sImageView.setDrawable(Drawable); // 接收一個Drawable對象
sImageView.setBitmap(Bitmap); // 接收一個圖片的bitmap</code></pre>
加載中的圖片和加載失敗的圖片設置
對于網絡下載圖片. 會有 下載失敗 和 下載中 的圖片顯示. 默認圖片加載類 ImageLoad 類中會內置兩張系統兩個對應圖片來顯示. ImageLoad 類中的 加載中 和 加載失敗 圖片會作用于全局的 SImageView 控件. 也可以給 SImageView 控件實例設置. 如果控件設置了. 那么優先級會比全局 ImageLoad 中的圖片使用優先. 如果控件沒有, 那么就使用全局.
代碼設置如下:
// 設置當前控件的場景圖片, 優先級高于全局
sImageView.setErrPicResID(R.mipmap.ic_launcher) // 設置加載錯誤圖片
.setLoadingResID(R.mipmap.icon_test) // 設置加載中圖片
.setImageUrls("
// 對于圖片網址滿足條件 判斷正則為: "https?://.*?.(jpg|png|bmp|jpeg|gif)"
//如果不滿足, 那么會認為是一個錯誤地址, 可動態配置, 后面說明
// 設置全局控件場景圖片, (有默認圖片可以不設置)
ImageLoader.getInstance(getApplicationContext()).setLoadErrResId(R.mipmap.icon_test); ImageLoader.getInstance(getApplicationContext()).setLoadingResId(R.mipmap.ic_launcher);</code></pre>
控件其他的方法
方法名稱
參數說明
方法作用
setCloseNormalOnePicLoad()
布爾值
設置 true 可以強制關閉一張圖片時候的默認單張圖片處理規則, 而由 測量接口 , 繪制顯示接口 處理.
setOvalRatio()
float類型, 橢圓的寬高比值(必須大于0)
在 單張圖片 并且 橢圓類型 顯示時, 設置橢圓的顯示的寬高比例
setRectRoundRadius()
float類型, 設置范圍0~2,默認1
在 單張圖片 并且 圓角矩形類型 顯示時, 設置圓角的弧度大小
setDrawStrategy()
可參考下面的擴展實現, 用來設置自定義圖片實現策略
setLayoutManager()
可參考下面的擴展實現, 用來設置自定義或替換 圖片的排列分布規則
對應的 getter() 方法省略.
設置圖片網址匹配
上面提到過默認過濾圖片鏈接的正則判斷為 "https?://.*?.(jpg|png|bmp|jpeg|gif)"
如果需要實現其他的地址規則. 可重定義過濾策略
ImageLoader.getInstance(getApplicationContext()).setPicUrlRegex("RegexStr");
// 如果設置自定義正則之后需要恢復, 那么直接設置空串即可
ImageLoader.getInstance(getApplicationContext()).setPicUrlRegex("");</code></pre>
輸出log開關
默認類庫 log 是不輸出的, 如果需要打開如下:
LogUtil.GlobalLogPrint = true; // 輸出類庫相關log信息
擴展實現
控件實現了 measure測量布局 和 draw具體繪圖實現 的功能分離. 你可以任意實現排列規則, 和具體的繪圖顯示的規則.
自定義measure測量布局
布局測量接口 ILayoutManager . 相當于 RecyclerView 設置布局管理器. 或者 View#onMeasure() 的作用.
目前內置了2種布局來實現多張圖片的排列.
-
QQLayoutManager : 控件默認排列規則, 效果類似于 qq群組頭像 ,最大支持 5 張圖片
-
WeChatLayoutManager : 效果類似于 微信群組頭像 , 最大支持 9 張圖片
通過 setLayoutManager(ILayoutManager) 來進行測量規則的具體實現類.
默認情況下, 如果控件只設置了一張圖片是不會走 測量的流程 . 如果需要一張圖片時也需要不規則的排布. 那么通過 SImageView#setCloseNormalOnePicLoad(true) . 強制關閉.
自定義實現: 實現 ILayoutManager 接口并在 calculate() 實現具體的排列效果. 并返回一個子圖片的位置信息集合. 接口如下. 可參考已經實現的兩個類.
public interface ILayoutManager {
/**
* 布局measure排列計算方法, 具體規則由子類實現
*
* @param viewWidth 控件的寬
* @param viewHeight 控件的高
* @param viewNum 控件圖片的數量
* @return 返回一個信息集合, 提供 {@link com.szysky.customize.siv.effect.IDrawingStrategy#algorithm(Canvas, int, int, Bitmap, SImageView.ConfigInfo)}使用
*/
ArrayList<LayoutInfoGroup> calculate(int viewWidth, int viewHeight, int viewNum);
/**
* 封裝控件內部單個元素顯示的布局信息
*/
class LayoutInfoGroup implements Cloneable{
/**
* 組合頭像時, 每個單獨元素可分配的最大寬高
*/
public int innerWidth;
public int innerHeight;
/**
* 每個單獨元素,左上點和右下點. 可規劃區域
*/
public Point leftTopPoint = new Point();
public Point rightBottomPoint = new Point();
@Override
protected Object clone() throws CloneNotSupportedException {
LayoutInfoGroup clone = (LayoutInfoGroup) super.clone();
clone.leftTopPoint.set(leftTopPoint.x, leftTopPoint.y);
clone.rightBottomPoint.set(rightBottomPoint.x, rightBottomPoint.y);
return clone;
}
}
}</code></pre>
自定義的圖片顯示
控件內置了兩種圖片顯示. 例如: 橢圓, 圓角矩形, 描邊, 五角星等. 相當于 View#onDraw() 和 Adapter#getView() 作用. 具體顯示分離.
繪制顯示接口 IDrawingStrategy
內置實現:
-
NormalOnePicStrategy : 當控件設置單張圖片時, 默認都是正中間(矩形除外, 保留了 ImageView 三種常用的縮放). 所以無需進行測量步驟. 直接通過配置的形狀屬性等進行相對應的配置實現效果.
-
ConcreteDrawingStrategy : 當控件圖片為多張的時被觸發. 接收 ILayoutManager#calculate() 測量布局返回的子圖片的信息集合, 進行具體的繪制工作. 可通過 SImageView#setCloseNormalOnePicLoad(true) 強制關閉控件單張圖片執行 NormalOnePicStrategy 的邏輯. 全權由 測量布局 , 繪制顯示 兩個邏輯實現所有圖片數量的處理.
通過 setDrawStrategy(IDrawingStrategy) 來進行圖片繪制顯示的具體策略類.
自定義繪制策略類. 實現 IDrawingStrategy 接口并實現對應方法, 方法里面有圖片對應的畫布,和需要顯示的寬高信息等. 接口如下:
public interface IDrawingStrategy {
/**
* 根據提供的畫布, 和可繪制的位置實現具體效果
*
* @param canvas {@link SImageView#onDraw(Canvas)} 中的畫布
* @param childTotal 圖片的總個數
* @param curChild 當前圖片是第幾張圖片
* @param opeBitmap 需要操作的圖片
* @param info 每個內部元素應該擺放的位置信息類
*/
void algorithm(Canvas canvas, int childTotal, int curChild, Bitmap opeBitmap, SImageView.ConfigInfo info);
}</code></pre>
緩存策略自定義
這部分寫的自己不是很滿意, 寫著寫著就有點耦合了, 最后精力不夠... 好吧這是借口. 反正也能將就自定義, 用默認的就行.... [捂臉]
建議
-
盡量使控件作為頭像控件顯示, 如果大小低于 100dp , 內部稍微做了一些特別處理. 性能可以好一些.
-
由于內置樣式較多, 導致了 cpu密集處理 . 和一些對象的開銷. 如果項目性能要求較高那么可通過自定義繪圖策略注入控件來優化. 這樣項目中常用的效果就可以得到性能提升.
-
類庫需要 寫外部存儲的權限 , 對于新版本的 動態權限 , 一定要先進行權限判斷, 再對 ImageLoad 進行初始化(控件的網絡圖片設置). 否則可能導致, 磁盤緩存無效只有內存緩存.
如果發現什么問題, 請提 issue . 作者會抽時間去修補 ^*^.