Android自定義相冊(cè),查看手機(jī)圖片

最近因?yàn)楣拘枨笮枰鲆粋€(gè)自定義的相冊(cè),因?yàn)槭謾C(jī)自帶的相冊(cè)沒(méi)有這種可以選取多張圖片的功能,先上gif圖,看效果(功能可以看出來(lái),不知道為什么gif這么稀爛。。。)

GIF.gif

簡(jiǎn)單功能都實(shí)現(xiàn)了,主要點(diǎn)是對(duì)圖片的查詢(xún),然后設(shè)置了兩個(gè)popupWindow來(lái)顯示小相冊(cè)和點(diǎn)擊放大的效果,比較簡(jiǎn)單。(代碼里面會(huì)有一些簡(jiǎn)單的工具類(lèi),看名字可以看出來(lái)是干什么的)

查詢(xún)手機(jī)中的圖片路徑

步驟:
1.查詢(xún)圖片的path
2.由圖片path獲取其他信息(該圖片所在文件夾的路徑,文件夾的名字,文 件夾下的圖片個(gè)數(shù))
3.定義一個(gè)圖片Model,來(lái)保存及對(duì)圖片信息的傳遞,以便展示出來(lái)
4.通過(guò)文件夾的list()方法,可以獲取每一個(gè)小相冊(cè)下的圖片文件

上代碼。。。

//獲取圖片的路徑和父路徑 及 圖片size
   private void getImages() {
       if (!Environment.getExternalStorageState().equals(
               Environment.MEDIA_MOUNTED)) {
           ViewKit.shortToast("檢測(cè)到?jīng)]有內(nèi)存卡");
           return;
       }
       showLoading();
       new Thread(new Runnable() {
           @Override
           public void run() {
               Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
               ContentResolver mContentResolver = GalleryActivity.this.getContentResolver();

               Cursor mCursor = mContentResolver.query(mImageUri, null,
                       MediaStore.Images.Media.MIME_TYPE + "=? or "+
                       MediaStore.Images.Media.MIME_TYPE + "=? or "+
                       MediaStore.Images.Media.MIME_TYPE + "=?",
                       new String[]{"image/jpeg", "image/png","image/jpg"},
                       MediaStore.Images.Media.DATE_TAKEN +" DESC");//獲取圖片的cursor,按照時(shí)間倒序(發(fā)現(xiàn)沒(méi)卵用)

               while (mCursor.moveToNext()) {
                   String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));// 1.獲取圖片的路徑
                   File parentFile = new File(path).getParentFile();
                   if (parentFile == null)
                       continue;//不獲取sd卡根目錄下的圖片
                   String parentPath = parentFile.getAbsolutePath();//2.獲取圖片的文件夾信息
                   String parentName = parentFile.getName();
                   ImageFloder imageFloder ;//自定義一個(gè)model,來(lái)保存圖片的信息  

       //這個(gè)操作,可以提高查詢(xún)的效率,將查詢(xún)的每一個(gè)圖片的文件夾的路徑保存到集合中,  
       //如果存在,就直接查詢(xún)下一個(gè),避免對(duì)每一個(gè)文件夾進(jìn)行查詢(xún)操作  
                   if (mDirPaths.contains(parentPath)) {
                       continue;
                   } else {
                       mDirPaths.add(parentPath);//將父路徑添加到集合中
                       imageFloder = new ImageFloder();
                       imageFloder.setFirstImagePath(path);
                       imageFloder.setDir(parentPath);
                       imageFloder.setName(parentName);
                   }
                   List<String>  strings = null;
                   try {
                    strings =  Arrays.asList(parentFile.list(getFileterImage()));
                   } catch (Exception e) {
                       e.printStackTrace();
                   }
                   int  picSize = strings.size();//獲取每個(gè)文件夾下的圖片個(gè)數(shù)
                   imageFloder.setCount(picSize);//傳入每個(gè)相冊(cè)的圖片個(gè)數(shù)
                   mImageFloders.add(imageFloder);//添加每一個(gè)相冊(cè)
       //獲取圖片最多的文件夾信息(父目錄對(duì)象和個(gè)數(shù),使得剛開(kāi)始顯示的是最多圖片的相冊(cè)
                   if (picSize > mPicsSize) {  
                       mPicsSize = picSize;
                       mImgDir = parentFile;
                   }
               }
               mCursor.close();
               mDirPaths = null;
               mHandler.sendEmptyMessage(1);
           }
       }).start();
   }

這是Model類(lèi),貼出來(lái),方便觀看

public class ImageFloder {
    private int count;//文件夾下的圖片個(gè)數(shù)
    private String firstImagePath;//第一張圖片的路徑 傳這個(gè)給小相冊(cè)圖片顯示
    private String dir;//文件夾路徑
    private String name;//文件夾的名字

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public String getFirstImagePath() {
        return firstImagePath;
    }

    public void setFirstImagePath(String firstImagePath) {
        this.firstImagePath = firstImagePath;
    }

    public String getDir() {
        return dir;
    }

    public void setDir(String dir) {
        this.dir = dir;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

還記得上面的handler操作嗎,查詢(xún)圖片是一個(gè)耗時(shí)的操作,為了更新ui,也為了方便觀看,就使用了handler的方式,這樣代碼也比較整潔,下面這個(gè)小代碼,就是接下來(lái)的步驟了

Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            setAdapterData();//設(shè)置圖片的顯示
            cancelLoading();//取消加載框
            initListDirPopupWindw();//初始化小相冊(cè)的popupWindow
            initChekcBox();//初始化checkbox集合,防止checkBox的錯(cuò)亂
        }
    };

設(shè)置適配器(采用的RecycleVIew,自己做的封裝)

    //設(shè)置適配器數(shù)據(jù)
private void setAdapterData() {
    if (mImgDir == null) {
        ViewKit.shortToast("沒(méi)有查詢(xún)到圖片");
        return;
    }
    tv_pop_gallery.setText(mImgDir.getName());
    try {
        mImgs = Arrays.asList(mImgDir.list(getFileterImage()));//獲取文件夾下的圖片集合
    }catch (Exception e){
        e.printStackTrace();
    }
    //查詢(xún)出來(lái)的圖片是正序的,為了讓圖片按照時(shí)間倒序顯示,對(duì)其倒序操作
    Collections.sort(mImgs, new Comparator<String>() {
        @Override
        public int compare(String lhs, String rhs) {
            return -1;
        }
    });

    mAdapter = new GalleryAdapter(gallery_recycleView, mImgs, R.layout.item_gallery_camera);
    gallery_recycleView.setLayoutManager(new GridLayoutManager(this, 3));
    gallery_recycleView.addItemDecoration(new DividerGridItemDecoration(this));
    gallery_recycleView.setAdapter(mAdapter);
}

適配器:

//適配器
    private class GalleryAdapter extends BaseRecyclerAdapter<String> {
        List<String> datas;
        String picPath;
        ImageView iv_gallery;
        CheckBox cb_gallery;

        public GalleryAdapter(RecyclerView v, List<String> datas, int itemLayoutId) {
            super(v, datas, itemLayoutId);
            this.datas = datas;
        }

        @Override
        public void convert(final RecyclerHolder holder, String item, final int position) {
            iv_gallery = holder.getView(R.id.iv_gallery);
            cb_gallery = holder.getView(R.id.cb_gallery);
            iv_gallery.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, DensityKit.getScreenW() / 3));
            picPath = mImgDir.getAbsolutePath() + "/" + datas.get(position);
            BitmapKit.loadLocalImage(iv_gallery, picPath);//這里采用的是Glide為ImageVIew加載圖片,很方便,這里對(duì)Glide進(jìn)行了工具類(lèi)的封裝

            //顯示大圖
            iv_gallery.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    initBigPicPopupWindw(mImgDir.getAbsolutePath() + "/" + datas.get(position));
                }
            });

            //checkBox
            cb_gallery.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    CheckBox checkBox = (CheckBox) v;
                    if (realCount >= 9 && !selectList.get(position)) {
                        ViewKit.shortToast("最多可以選擇9張圖片");
                        selectList.put(position, false);
                    } else{
                        selectList.put(position, !selectList.get(position));
                    }

                    for (Map.Entry<Integer, Boolean> entry : selectList.entrySet()) {
                        entry.getKey();
                        Boolean value = entry.getValue();
                        if (value) {
                            checkCount++;
                        }
                    }
                    tv_count_gallery.setText("(" + checkCount + ")");
                    tv_confirm_gallery.setVisibility(checkCount>0?View.VISIBLE:View.GONE);
                    realCount = checkCount;
                    checkCount = 0;
                    checkBox.setChecked(selectList.get(position));
                }
            });
            if(selectList!=null)
                cb_gallery.setChecked(selectList.get(position));
        }
    }
}

左側(cè)popupWindow小相冊(cè)的定義

//設(shè)置相冊(cè)PopupWindow
   private void initListDirPopupWindw() {
       mListImageDirPopupWindow = new ListImageDirPopupWindow(this, mImageFloders);
       mListImageDirPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
           @Override
           public void onDismiss() {
               setToRightDrawable(R.drawable.arrow_bottom);
           }
       });
       mListImageDirPopupWindow.setOnImageDirSelected(new ListImageDirPopupWindow.OnImageDirSelected() {  
         //點(diǎn)擊item之后的回調(diào)
           @Override
           public void selected(ImageFloder floder) {
               mListImageDirPopupWindow.showAtDropDownCenter(tv_confirm_gallery);
               setToRightDrawable(R.drawable.arrow_bottom);
               realCount = 0;
               tv_pop_gallery.setText(floder.getName());
               tv_count_gallery.setText("(0)");
               tv_confirm_gallery.setVisibility(View.GONE);
               File file = new File(floder.getDir());
               List<String> picFileList = null;
               try {
                   picFileList =   Arrays.asList(file.list(getFileterImage()));
               } catch (Exception e) {
                   e.printStackTrace();
               }

               Collections.sort(picFileList, new Comparator<String>() {
                   @Override
                   public int compare(String lhs, String rhs) {
                       return -1;
                   }
               });
             //重新設(shè)置數(shù)據(jù)和checkBox初始化
               mImgDir = file;
               mImgs = picFileList;
               initChekcBox();
               mAdapter = new GalleryAdapter(gallery_recycleView, picFileList, R.layout.item_gallery_camera);
               gallery_recycleView.setAdapter(mAdapter);
           }
       });
   }

相冊(cè)PopupWIndow的代碼:

public class ListImageDirPopupWindow extends PopupWindow {
   RecyclerView recycl_camera_list;
   public ListImageDirPopupWindow(Context context, List<ImageFloder> mImageFloders) {
       View conentView = LayoutInflater.from(context).inflate(R.layout.view_dir_camera, null);
       recycl_camera_list = (RecyclerView) conentView.findViewById(R.id.recycl_camera_list);
       setContentView(conentView);

       ListAdapter listAdapter = new ListAdapter(recycl_camera_list, mImageFloders, R.layout.item_list_camera);
       recycl_camera_list.setLayoutManager(new LinearLayoutManager(context));//設(shè)置垂直
       recycl_camera_list.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
       recycl_camera_list.setAdapter(listAdapter);
       listAdapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
           @Override
           public void onItemClick(View view, Object data, int position) {
               if (data instanceof ImageFloder) {
                   ImageFloder imageFloder = (ImageFloder) data;
                   onImageDirSelected.selected(imageFloder);
               }
           }
       });
       setAnimationStyle(R.style.popup_camera);
       setFocusable(true);
       setTouchable(true);

       setOutsideTouchable(true);
       ColorDrawable background = new ColorDrawable(0xffffff);
       setBackgroundDrawable(background);
       setWidth((int) (DensityKit.getScreenW()/2));
       setHeight(DensityKit.getScreenH()/3);

   }


   class ListAdapter extends BaseRecyclerAdapter<ImageFloder> {

       public ListAdapter(RecyclerView v, List<ImageFloder> datas, int itemLayoutId) {
           super(v, datas, itemLayoutId);
       }

       @Override
       public void convert(RecyclerHolder holder, final ImageFloder imageFloder, int position) {
           ImageView iv_first_image = holder.getView(R.id.iv_first_image);
           TextView tv_count_list = holder.getView(R.id.tv_count_list);
           TextView tv_name_list = holder.getView(R.id.tv_name_list);

           BitmapKit.loadLocalImage(iv_first_image, imageFloder.getFirstImagePath());
           tv_count_list.setText("(" + imageFloder.getCount() + ")");
           tv_name_list.setText(imageFloder.getName());

       }
   }

   public void showAtDropDownCenter(View parent) {
       if (!isShowing()) {
           setAnimationStyle(R.style.popup_camera);
           int[] location = new int[2];
           parent.getLocationOnScreen(location);//獲取以屏幕為原點(diǎn)的位置
           showAtLocation(parent,Gravity.TOP|Gravity.LEFT,0,location[1]-getHeight());
//            showAtLocation(parent,Gravity.TOP,(location[0]-getWidth())/2, location[1]-getHeight());
//            showAtLocation(parent, Gravity.NO_GRAVITY, location[0], location[1]-getHeight()); 三種方式都可以 原理是一樣的
       } else {
           dismiss();
       }
   }
   //點(diǎn)擊之后的接口回調(diào)
   private OnImageDirSelected onImageDirSelected;
   public void setOnImageDirSelected(OnImageDirSelected onImageDirSelected) {
       this.onImageDirSelected = onImageDirSelected;
   }
   public interface OnImageDirSelected {
       void selected(ImageFloder floder);
   }
}

雜⑦雜⑧的代碼,懶的搞了,都貼出來(lái)(都有小注釋)

 //設(shè)置大圖片的PopupWindow
   private void initBigPicPopupWindw(String path) {
       BigImagePopup bigImagePopup = new BigImagePopup(this);
       bigImagePopup.setUrl(path);
       bigImagePopup.showAtDropDownCenter(tv_confirm_gallery);
   }


   //導(dǎo)航欄點(diǎn)擊事件
   @Override
   public void onClick(View v) {
       int i = v.getId();
       if (i == R.id.tv_pop_gallery) {
          setToRightDrawable(R.drawable.arrow_up);
           mListImageDirPopupWindow.showAtDropDownCenter(tv_confirm_gallery);
       } else if (i == R.id.tv_confirm_gallery) {

           ArrayList<String> pathList = new ArrayList<>();
           for (Map.Entry<Integer, Boolean> entry : selectList.entrySet()) {
               Boolean isChecked = entry.getValue();
               if (isChecked) {
                   Integer position = entry.getKey();
                   String checkPath = mImgDir.getAbsolutePath() + "/" + mImgs.get(position);
                   pathList.add(checkPath);
               }
           }
           backUrl(pathList);
       }
   }


   //intent
   public static Intent createIntent(Context context) {
       Intent intent = new Intent(context, GalleryActivity.class);
       intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
       return intent;
   }


   //返回的圖片路徑集合
   private void backUrl(ArrayList<String> pathList) {
       Intent intent = new Intent();
       intent.putStringArrayListExtra("imageUrl", pathList);
       setResult(RESULT_OK, intent);
       finish();
   }


   // 初始化 設(shè)置所有checkbox都為未選擇
   private void initChekcBox() {
       selectList = new HashMap<Integer, Boolean>();
       if (mImgs != null && mImgs.size() > 0) {
           for (int i = 0; i < mImgs.size(); i++) {
               selectList.put(i, false);
           }
       }
   }


   //動(dòng)態(tài)改變text的toRightDrawable
   private void setToRightDrawable(int drawalbeId){
       Drawable drawable= getResources().getDrawable(drawalbeId);
       drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
       tv_pop_gallery.setCompoundDrawables(null,null,drawable,null);
   }


   //設(shè)置popWindow的背景----不要設(shè)置  會(huì)透視。。。
   public void setBg_popup() {
       WindowManager.LayoutParams lp = getWindow().getAttributes();
       lp.alpha = 1.0f;
       getWindow().setAttributes(lp);
   }

   //圖片篩選器,過(guò)濾無(wú)效圖片
   private FilenameFilter getFileterImage(){
       FilenameFilter filenameFilter = new FilenameFilter() {
           @Override
           public boolean accept(File dir, String filename) {
               if (filename.endsWith(".jpg")
                       || filename.endsWith(".png")
                       || filename.endsWith(".jpeg"))
                   return true;
               return false;
           }
       };
       return filenameFilter;
   }

點(diǎn)擊放大的popupWIndow

public class BigImagePopup extends PopupWindow {
    ImageView iv_big_picture;

    public BigImagePopup(Activity context) {
        View conentView = LayoutInflater.from(context).inflate(R.layout.view_bigpic, null);
        setContentView(conentView);

        LinearLayout linearLayout = (LinearLayout) conentView.findViewById(R.id.ll_picture);
        iv_big_picture = (ImageView) conentView.findViewById(R.id.iv_big_picture);

        linearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
        iv_big_picture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
        setAnimationStyle(R.style.big_popup_camera);
        setFocusable(true);
        setTouchable(true);
        setOutsideTouchable(true);
        ColorDrawable background = new ColorDrawable(0xffffff);
        setBackgroundDrawable(background);
        setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
        setHeight(LinearLayout.LayoutParams.MATCH_PARENT);
    }

    public void setUrl(String url){
        BitmapKit.loadLocalImage(iv_big_picture, url);
    }

    public void showAtDropDownCenter(View parent) {
        if (!isShowing()) {
            setAnimationStyle(R.style.big_popup_camera);
            showAtLocation(parent, Gravity.BOTTOM, 0, 0);
        } else {
            dismiss();
        }
    }
}

寫(xiě)個(gè)這樣的博客都這么累。。。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,001評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,221評(píng)論 4 61
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程,因...
    小菜c閱讀 7,322評(píng)論 0 17
  • 離婚 少年 兄弟 媽媽
    鄺鑒萍閱讀 149評(píng)論 0 2
  • 人的這一生要經(jīng)歷很多的人很多的事,有時(shí)一個(gè)轉(zhuǎn)身無(wú)論是朋友還是某個(gè)機(jī)會(huì)錯(cuò)過(guò)了就真的錯(cuò)過(guò)了。 準(zhǔn)備考研之際,沒(méi)有座位于...
    萬(wàn)萬(wàn)是我閱讀 299評(píng)論 0 1

友情鏈接更多精彩內(nèi)容