私人訂制Android本地圖片選擇器

auxo2010 8年前發布 | 7K 次閱讀 Git 安卓開發 Android開發 移動開發

效果圖

需求分析

  • 網格布局顯示本地圖片
  • 支持圖片多選
  • 支持選中的圖片預覽
  • 未選擇圖片時不可預覽
  • 由已選多圖變為無圖時可退出圖片選擇頁面
  • 圖片已選達到上限后依然可以跳轉圖片選擇頁面

第三方框架使用

史上最強的安卓圖片選擇器—— GalleryFinal ;

實現目標

應用并修改第三方框架GalleryFinal源碼,實現效果圖的樣式。

具體實現

  • 導入GalleryFinal源碼

    從GalleryFinal的Github倉庫中拷貝倉庫地址,使用git指令cloneGalleryFinal源代碼到本地:

    git clone https://github.com/pengjianbo/GalleryFinal.git

    選擇Android Studio菜單欄File->New->import Module...,導入GalleryFinal源代碼到Android Studio:

 

導入GalleryFinal源碼

  • 寫一個GridView

    這里聲明一下,選擇圖片的Activity是GalleryFinal自帶的,所以我們這里要寫的GridView是用來顯示選中并返回的圖片,這里的代碼就不放出來了,效果圖如下:

    未選擇時

    選擇圖片時

    本人實現的可支持最大圖片數量是5,在圖片選滿的時候依然顯示“+”,用以跳轉圖片選擇頁面選擇其他圖片。

  • 初始化GalleryFinal配置

    為防止代碼分開查看導致邏輯的混亂,將上述配置代碼一齊貼上,下面的代碼可放在跳轉圖片選擇界面的按鈕點擊事件中。 這里強調一下 :mThemeConfig = new ThemeConfig.Builder() .setTitleBarBgColor等方法傳參是整型,但是其傳入的是顏色值而非資源文件的id。

    代碼注釋較詳細,其他不做過多講解:

    // ------- 聲明 -------
    // 主題配置
    private ThemeConfig mThemeConfig;
    // 圖片加載器
    private cn.finalteam.galleryfinal.ImageLoader mGlidImgLoader;
    // 滾動監聽事件
    private PauseOnScrollListener mPauseOnScrollListener;
    // 功能配置
    private FunctionConfig mFunctionConfig;
    // 核心配置
    private CoreConfig mCoreConfig;
    // ------- 實現 -------
    // 獲取標題欄背景顏色
    int colorTitleBarBg = ContextCompat.getColor(Activity.this, R.color.titleBarBgColor);
    // 標題欄文字顏色
    int colorTitleBarText = ContextCompat.getColor(Activity.this, R.color.titleBarTextColor);
    // 浮動按鈕常規顏色
    int colorFabNormal = ContextCompat.getColor(Activity.this, R.color.color_ffaa2a);
    // 浮動按鈕點擊顏色
    int colorFabPressed = ContextCompat.getColor(Activity.this, R.color.color_e29428);
    // 標題欄按鈕顏色
    int colorTitleBarIcon = ContextCompat.getColor(MainActivity.this, R.color.colorTitleBarIcon);
    // 設置主題
    mThemeConfig = new ThemeConfig.Builder()
          .setTitleBarBgColor(colorTitleBarBg) // 設置標題欄背景顏色
          .setTitleBarTextColor(colorTitleBarText)    // 設置標題欄文字顏色
          .setFabNormalColor(colorFabNormal)  // 設置浮動按鈕常規顏色
          .setFabPressedColor(colorFabPressed)    // 設置浮動按鈕點擊顏色
          .setCheckSelectedColor(colorFabNormal)  // 設置選中標記(對勾)的顏色和按鈕的顏色相同
          .setTitleBarIconColor(colorTitleBarIcon) // 設置標題欄按鈕顏色
          .setIconBack(R.drawable.ic_back) // 設置返回按鈕
          .build();
    // 初始化圖片加載器
    mGlidImgLoader = new GlideImageLoader();
    // 初始化監聽事件
    mPauseOnScrollListener = new GlidePauseOnScrollListener(false, true);
    // 初始化功能配置
    FunctionConfig.Builder funConBuilder = new FunctionConfig.Builder();
    // 設置最多可選擇5張照圖片
    funConBuilder.setMutiSelectMaxSize(5);
    // 設置圖片不可編輯
    funConBuilder.setEnableEdit(false);
    // 設置圖片不可旋轉
    funConBuilder.setEnableRotate(false);
    // 設置圖片不可裁剪
    funConBuilder.setEnableCrop(false);
    // 設置不可通過照相選擇照片
    funConBuilder.setEnableCamera(false);
    // 設置添加過濾集合,過濾掉之前選中的圖片
    //        funConBuilder.setFilter(mPhotoList);
    // 不過濾圖片,而是將之前選中的圖片設置為選中狀態
    funConBuilder.setSelected(mPhotoList);
    // 設置可預覽
    funConBuilder.setEnablePreview(true);
    // 功能配置
    mFunctionConfig = funConBuilder.build();
    // 初始化核心配置
    mCoreConfig = new CoreConfig.Builder(ReportActivity.this, mGlidImgLoader, mThemeConfig)
          .setFunctionConfig(mFunctionConfig) // 添加功能配置
          .setPauseOnScrollListener(mPauseOnScrollListener) // 滑動停止加載事件
          .setNoAnimcation(true) // 無特效動畫
          .build();
    // 實例化
    GalleryFinalGalleryFinal.init(mCoreConfig);
    // 多圖片選擇打開相冊
    GalleryFinal.openGalleryMuti(Constants.REQUEST_CODE_GALLERY, mFunctionConfig,
          mOnHandlerResultCallback);
    // 初始化圖片加載器
    initImageLoader(ReportActivity.this);
    /**

    • 初始化圖片加載器 *
    • @param context / private void initImageLoader(Context context) { // 圖片加載器配置 ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(this); // 設置線程優先級 config.threadPriority(Thread.NORM_PRIORITY - 2); // 禁止內存緩存 config.denyCacheImageMultipleSizesInMemory(); // 設置磁盤緩存文件名生成器 config.diskCacheFileNameGenerator(new Md5FileNameGenerator()); // 設置磁盤緩存大小 config.diskCacheSize(20 1024 * 1024); // 設置任務進程執行順序:先進后出 config.tasksProcessingOrder(QueueProcessingType.LIFO); // 調試使用,若是發布版,需要移除代碼 config.writeDebugLogs(); // 初始化圖片加載器 ImageLoader.getInstance().init(config.build()); }</code></pre>
      • 通過代碼設置圖片選擇器的標題欄背景顏色,標題文本顏色,浮動按鈕顏色;
      • 通過監聽事件,達到滾動時不加載圖片,停下來時加載圖片,實現優化;
      • 初始化功能配置;
      </li>
    • 選擇圖片返回的回調實現

      /**
    • 回調處理 */ private GalleryFinal.OnHanlderResultCallback mOnHandlerResultCallback = new GalleryFinal.OnHanlderResultCallback() { @Override public void onHanlderSuccess(int reqeustCode, List<PhotoInfo> resultList) {
      // 清除原來列表中的圖片
      mPhotoList.clear();
      // 返回圖片列表
      mPhotoList.addAll(resultList);
      // 刷新頁面
      mPhotoAdapter.notifyDataSetChanged();
      
      } @Override public void onHanlderFailure(int requestCode, String errorMsg) {
      // 錯誤提示
      Toast.makeText(Activity.this, errorMsg, Toast.LENGTH_SHORT).show();
      
      } };</code></pre> </li> </ul>

      基于上述代碼,可得到效果圖如下:

      初步效果圖

      修改源碼

      通過運行調試,發現框架中有些功能與需求不一致,因此我產生了修改源碼的想法,總結需要更改的原功能點如下:

      選擇完達到上限數量的圖片后,無法重新回到圖片選擇頁面

      選擇圖片數量達到上限時無法進入圖片選擇頁面

      • 無圖片選擇時,無法點擊浮動按鈕進行返回


      無圖片時無法返回

      • 無圖片選擇時,預覽按鈕依然存在


      無圖片選擇時預覽按鈕依然存在并可以點擊

      針對以上需要修改的功能,源碼修改如下:

      選擇圖片到達上限依然可以返回圖片選擇頁面

      因圖片選擇頁面的跳轉在openGalleryMuti方法里實現:

      // 多圖片選擇打開相冊
      GalleryFinal.openGalleryMuti(Constants.REQUEST_CODE_GALLERY, mFunctionConfig, 
         mOnHandlerResultCallback);

      所以我們來看看openGalleryMuti方法的源碼:

      openGalleryMuti方法源碼

      可以發現,源碼中有這么一個判斷邏輯:

      if (config.getSelectedList() != null && config.getSelectedList().size() > config.getMaxSize()) {
      if(callback != null){
          callback.onHanlderFailure(requestCode, mCoreConfig.getContext().getString(R.string.select_max_tips));
      }
      return;
      }

      其作用是當選中的圖片數量超過最大值時,返回打開本地圖片選擇器失敗的提示信息。之前我們提到,需求中我們實際多顯示了一張圖片:

      “添加”圖片

      且在配置的時候傳入的是添加了一張圖片以后的圖片列表:

      // 不過濾圖片,而是將之前選中的圖片設置為選中狀態
      funConBuilder.setSelected(mPhotoList);

      所以會導致界面無法跳轉,我們有三個策略:

      1.將多添加的圖片放到adapter里面處理,adapter外部保持選中圖片數量與選擇頁面傳入圖片的數量一致

      2.setSelected傳入圖片列表之前將mPhotoList移除多出的圖片

      3.注釋掉源碼中對圖片數量上限的判斷

      無圖選擇時,點擊浮動按鈕可以返回

      可能有人不解,為何不點擊標題欄的返回按鈕返回而要點擊浮動按鈕返回?其原因是,若之前我選擇好圖片,但是想想,現在我不想要選擇的圖片了,這時候我們想把圖片清空掉,這時候需要點擊浮動按鈕,來更新選中圖片的列表。

      想到這是浮動按鈕的點擊事件,所以我們到源碼的GallerySelectActivity中浮動按鈕的事件回調方法中:

      浮動按鈕點擊事件

      這段代碼僅僅在選中圖片的數量大于0的時候才執行操作,所以我們添加一個條件,修改后的代碼如下:

      if (mSelectPhotoList.size() > 0) {
      if (!GalleryFinal.getFunctionConfig().isEditPhoto()) {
          resultData(mSelectPhotoList);
      } else {
          toPhotoEdit();
      }
      } else {
      // 添加的代碼,使未選中圖片時也可返回
      resultData(mSelectPhotoList);
      }

      mSelectPhotoList初始化

      考慮到選中圖片的列表在聲明時已經初始化,所以不用擔心圖片返回的回調事件傳入空指針對象。

      • 未選擇圖片時不顯示預覽按鈕

        通過布局的id—— iv_preview 在PhotoSelectActivity中查找,在refreshSelectCount方法里找到了對預覽按鈕可見性的設置:

        refreshSelectCount方法源碼

        從源碼中可以看到,預覽按鈕的可見性判斷邏輯僅僅與isEnablePreview有關,而沒有和選中的圖片數量進行關聯,所以我們修改代碼如下:

        public void refreshSelectCount() {
        mTvChooseCount.setText(getString(R.string.selected, mSelectPhotoList.size(), GalleryFinal.getFunctionConfig().getMaxSize()));
        if (mSelectPhotoList.size() > 0 && GalleryFinal.getFunctionConfig().isMutiSelect()) {
            mIvClear.setVisibility(View.VISIBLE);
            if (GalleryFinal.getFunctionConfig().isEnablePreview()) {
                mIvPreView.setVisibility(View.VISIBLE);
            }
        } else {
            mIvClear.setVisibility(View.GONE);
            mIvPreView.setVisibility(View.GONE);
        }
        }

        當選中圖片列表大小為0的時候,隱藏預覽按鈕;大于0的時候再根據isEnablePreview()來判斷是否顯示預覽按鈕。

      修改布局和代碼邏輯

      布局和代碼邏輯的修改,其思路與上一節 修改源碼 一樣,因需求的效果圖功能與GalleryFinal的功能基本一致,邏輯上并不需要做很多的修改,而布局的修改僅涉及到ImageButton變成Button,ImageView變成TextView以及控件位置的調整,在關聯控件上和點擊事件根據id來判斷事件處理上做相應修改即可,在此不做贅述。

      總結

      使用GalleryFinal訂制屬于自己的圖片選擇器并不難,只需要循著需求的功能點,按照代碼的邏輯一點點追蹤源碼并進行修改訂制即可。誠懇地說,GalleryFinal框架的可移植性確實很強,在此推薦大家了解一下!

       

      來自:http://www.jianshu.com/p/fd5ebfc4725e

       

 本文由用戶 auxo2010 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!