├── app
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ └── styles.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── image_add_nor.png
│ │ │ └── image_add_sel.png
│ │ ├── drawable
│ │ │ └── selector_image_add.xml
│ │ └── layout
│ │ │ ├── list_item_image.xml
│ │ │ ├── video_item.xml
│ │ │ └── activity_wxdemo.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── pbq
│ │ └── imagepickerdemo
│ │ ├── imageloader
│ │ ├── UILImageLoader.java
│ │ ├── PicassoImageLoader.java
│ │ ├── GlideImageLoader.java
│ │ └── XUtils3ImageLoader.java
│ │ ├── GApp.java
│ │ └── wxdemo
│ │ ├── ImagePickerAdapter.java
│ │ └── WxDemoActivity.java
├── proguard-rules.pro
└── build.gradle
├── imagepicker
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── mipmap-xxhdpi
│ │ │ ├── play.png
│ │ │ ├── ic_back.png
│ │ │ ├── ic_del.png
│ │ │ ├── default_image.png
│ │ │ ├── grid_camera.png
│ │ │ ├── grid_record.png
│ │ │ ├── list_selected.png
│ │ │ ├── checkbox_normal.png
│ │ │ ├── text_indicator.png
│ │ │ ├── checkbox_checked.png
│ │ │ └── grid_record_white.png
│ │ ├── drawable-xxhdpi
│ │ │ ├── bg_btn_dis.9.png
│ │ │ ├── bg_btn_nor.9.png
│ │ │ └── bg_btn_pre.9.png
│ │ ├── anim
│ │ │ ├── top_in.xml
│ │ │ ├── show_from_bottom.xml
│ │ │ ├── hide_to_bottom.xml
│ │ │ ├── fade_in.xml
│ │ │ ├── fade_out.xml
│ │ │ ├── left_out.xml
│ │ │ ├── right_out.xml
│ │ │ ├── bottom_in.xml
│ │ │ ├── bottom_out.xml
│ │ │ ├── top_out.xml
│ │ │ ├── left_in.xml
│ │ │ ├── right_in.xml
│ │ │ ├── scale_in.xml
│ │ │ └── scale_out.xml
│ │ ├── drawable
│ │ │ ├── selector_grid_camera_bg.xml
│ │ │ ├── selector_item_checked.xml
│ │ │ ├── selector_back_press.xml
│ │ │ └── selector_top_ok.xml
│ │ ├── values
│ │ │ ├── colors.xml
│ │ │ ├── attrs.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── layout
│ │ │ ├── viewpager_video_item.xml
│ │ │ ├── adapter_camera_item.xml
│ │ │ ├── adapter_record_item.xml
│ │ │ ├── pop_folder.xml
│ │ │ ├── adapter_image_item.xml
│ │ │ ├── activity_image_crop.xml
│ │ │ ├── adapter_folder_image_item.xml
│ │ │ ├── activity_image_preview.xml
│ │ │ ├── activity_video_preview.xml
│ │ │ ├── adapter_video_item.xml
│ │ │ ├── adapter_folder_video_item.xml
│ │ │ ├── include_top_bar.xml
│ │ │ ├── activity_image_grid.xml
│ │ │ └── activity_video_grid.xml
│ │ ├── java
│ │ └── com
│ │ │ └── pbq
│ │ │ └── imagepicker
│ │ │ ├── loader
│ │ │ └── ImageLoader.java
│ │ │ ├── bean
│ │ │ ├── VideoFolder.java
│ │ │ ├── ImageFolder.java
│ │ │ ├── ImageItem.java
│ │ │ └── VideoItem.java
│ │ │ ├── view
│ │ │ ├── SuperCheckBox.java
│ │ │ ├── ViewPagerFixed.java
│ │ │ └── FolderPopUpWindow.java
│ │ │ ├── ui
│ │ │ ├── image
│ │ │ │ ├── ImageBaseActivity.java
│ │ │ │ ├── ImagePreviewBaseActivity.java
│ │ │ │ ├── ImagePreviewDelActivity.java
│ │ │ │ ├── ImageCropActivity.java
│ │ │ │ └── ImagePreviewActivity.java
│ │ │ └── video
│ │ │ │ ├── VideoPreviewBaseActivity.java
│ │ │ │ └── VideoPreviewActivity.java
│ │ │ ├── Utils.java
│ │ │ ├── adapter
│ │ │ ├── image
│ │ │ │ ├── ImagePageAdapter.java
│ │ │ │ ├── ImageFolderAdapter.java
│ │ │ │ └── ImageGridAdapter.java
│ │ │ └── video
│ │ │ │ ├── VideoFolderAdapter.java
│ │ │ │ ├── VideoPageAdapter.java
│ │ │ │ └── VideoGridAdapter.java
│ │ │ ├── ImageDataSource.java
│ │ │ ├── VideoDataSource.java
│ │ │ ├── VideoPicker.java
│ │ │ └── ImagePicker.java
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── README.md
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/imagepicker/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':imagepicker'
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ImagePicker
2 | ###Android自定义相册,完全仿微信UI,实现了拍照、图片、录像、视频选择(单选/多选)、 裁剪 、旋转、等功能。
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | .idea
4 | /local.properties
5 | .DS_Store
6 | /build
7 | /captures
8 | /screenshots
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ImagePicker
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/image_add_nor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/app/src/main/res/mipmap-hdpi/image_add_nor.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/image_add_sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/app/src/main/res/mipmap-hdpi/image_add_sel.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/play.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/ic_back.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/ic_del.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/ic_del.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/default_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/default_image.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/grid_camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/grid_camera.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/grid_record.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/grid_record.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/list_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/list_selected.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/drawable-xxhdpi/bg_btn_dis.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/drawable-xxhdpi/bg_btn_dis.9.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/drawable-xxhdpi/bg_btn_nor.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/drawable-xxhdpi/bg_btn_nor.9.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/drawable-xxhdpi/bg_btn_pre.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/drawable-xxhdpi/bg_btn_pre.9.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/checkbox_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/checkbox_normal.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/text_indicator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/text_indicator.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/checkbox_checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/checkbox_checked.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/mipmap-xxhdpi/grid_record_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yolanda0628/ImagePicker-master/HEAD/imagepicker/src/main/res/mipmap-xxhdpi/grid_record_white.png
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/top_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Oct 07 00:32:14 CST 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/drawable/selector_grid_camera_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #cc22292c
4 | #000000
5 | #303135
6 | #9f556061
7 | #00000000
8 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/drawable/selector_item_checked.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/show_from_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/hide_to_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_image_add.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/drawable/selector_back_press.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/drawable/selector_top_ok.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/loader/ImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.loader;
2 |
3 | import android.app.Activity;
4 | import android.widget.ImageView;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * ImageLoader抽象类,外部需要实现这个类去加载图片, 尽力减少对第三方库的依赖,所以这么干了
10 | */
11 | public interface ImageLoader extends Serializable {
12 |
13 | void displayImage(Activity activity, String path, ImageView imageView, int width, int height);
14 |
15 | void clearMemoryCache(Activity activity);
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
15 |
16 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 全部图片
3 | 共%1$d张
4 | %1$s/%2$s
5 | 最多选择%1$s张图片
6 | 最多选择%1$s个视频
7 | 完成
8 | 完成(%1$s/%2$s)
9 | 预览(%1$s)
10 | 图片裁剪
11 | 原图
12 | 原图(%1$s)
13 |
14 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in E:\Android\SDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/imagepicker/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in E:\Android\SDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/video_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
19 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/viewpager_video_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
19 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/adapter_camera_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
20 |
21 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/adapter_record_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
20 |
21 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/bean/VideoFolder.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.bean;
2 |
3 | /**
4 | * Created by pengbangqin on 2016/12/27.
5 | * 视频文件夹
6 | */
7 |
8 | import java.io.Serializable;
9 | import java.util.ArrayList;
10 |
11 | public class VideoFolder implements Serializable {
12 |
13 | public String name; //当前文件夹的名字
14 | public String path; //当前文件夹的路径
15 | public VideoItem cover; //当前文件夹需要要显示的缩略图,默认为最近的一次视频
16 | public ArrayList videos; //当前文件夹下所有视频的集合
17 |
18 | /** 只要文件夹的路径和名字相同,就认为是相同的文件夹 */
19 | @Override
20 | public boolean equals(Object o) {
21 | try {
22 | VideoFolder other = (VideoFolder) o;
23 | return this.path.equalsIgnoreCase(other.path) && this.name.equalsIgnoreCase(other.name);
24 | } catch (ClassCastException e) {
25 | e.printStackTrace();
26 | }
27 | return super.equals(o);
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/fade_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/fade_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/left_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/right_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/bottom_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/bottom_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/top_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
11 |
12 |
13 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/left_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/right_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_wxdemo.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
22 |
23 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/scale_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/anim/scale_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/pop_folder.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
18 |
19 |
24 |
25 |
26 |
31 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.lzy.imagepickerdemo"
9 | minSdkVersion 14
10 | targetSdkVersion 24
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | compile 'com.android.support:appcompat-v7:24.2.1'
25 | compile 'com.android.support:recyclerview-v7:24.2.1'
26 |
27 | compile 'com.squareup.picasso:picasso:2.5.2'
28 | compile 'org.xutils:xutils:3.3.36'
29 | compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
30 | // compile 'com.pbq:imagepicker:1.1.0'
31 | compile 'com.lzy.widget:view-core:0.2.1'
32 | // compile 'com.lzy.widget:imagepicker:+'
33 | compile project(':imagepicker')
34 | }
35 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/bean/ImageFolder.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.bean;
2 |
3 | import java.io.Serializable;
4 | import java.util.ArrayList;
5 |
6 | /**
7 | * ================================================
8 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
9 | * 版 本:1.0
10 | * 创建日期:2016/5/19
11 | * 描 述:图片文件夹
12 | * 修订历史:
13 | * ================================================
14 | */
15 | public class ImageFolder implements Serializable {
16 |
17 | public String name; //当前文件夹的名字
18 | public String path; //当前文件夹的路径
19 | public ImageItem cover; //当前文件夹需要要显示的缩略图,默认为最近的一次图片
20 | public ArrayList images; //当前文件夹下所有图片的集合
21 |
22 | /** 只要文件夹的路径和名字相同,就认为是相同的文件夹 */
23 | @Override
24 | public boolean equals(Object o) {
25 | try {
26 | ImageFolder other = (ImageFolder) o;
27 | return this.path.equalsIgnoreCase(other.path) && this.name.equalsIgnoreCase(other.name);
28 | } catch (ClassCastException e) {
29 | e.printStackTrace();
30 | }
31 | return super.equals(o);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/pbq/imagepickerdemo/imageloader/UILImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepickerdemo.imageloader;
2 |
3 | /**
4 | * ================================================
5 | * 作 者:jeasonlzy(廖子尧)
6 | * 版 本:1.0
7 | * 创建日期:2016/3/28
8 | * 描 述:我的Github地址 https://github.com/jeasonlzy0216
9 | * 修订历史:
10 | * ================================================
11 | */
12 |
13 | import android.app.Activity;
14 | import android.net.Uri;
15 | import android.widget.ImageView;
16 |
17 | import com.pbq.imagepicker.loader.ImageLoader;
18 | import com.nostra13.universalimageloader.core.assist.ImageSize;
19 |
20 | import java.io.File;
21 |
22 | public class UILImageLoader implements ImageLoader {
23 |
24 | @Override
25 | public void displayImage(Activity activity, String path, ImageView imageView, int width, int height) {
26 | ImageSize size = new ImageSize(width, height);
27 | com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(Uri.fromFile(new File(path)).toString(), imageView, size);
28 | }
29 |
30 | @Override
31 | public void clearMemoryCache(Activity activity) {
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/adapter_image_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
20 |
21 |
29 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/bean/ImageItem.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.bean;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * ================================================
7 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
8 | * 版 本:1.0
9 | * 创建日期:2016/5/19
10 | * 描 述:图片信息
11 | * 修订历史:
12 | * ================================================
13 | */
14 | public class ImageItem implements Serializable {
15 |
16 | public String name; //图片的名字
17 | public String path; //图片的路径
18 | public long size; //图片的大小
19 | public int width; //图片的宽度
20 | public int height; //图片的高度
21 | public String mimeType; //图片的类型
22 | public long addTime; //图片的创建时间
23 |
24 | /** 图片的路径和创建时间相同就认为是同一张图片 */
25 | @Override
26 | public boolean equals(Object o) {
27 | try {
28 | ImageItem other = (ImageItem) o;
29 | return this.path.equalsIgnoreCase(other.path) && this.addTime == other.addTime;
30 | } catch (ClassCastException e) {
31 | e.printStackTrace();
32 | }
33 | return super.equals(o);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/bean/VideoItem.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.bean;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * ================================================
7 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
8 | * 版 本:1.0
9 | * 创建日期:2016/5/19
10 | * 描 述:视频信息
11 | * 修订历史:
12 | * ================================================
13 | */
14 | public class VideoItem implements Serializable {
15 |
16 | public String name; //视频的名字
17 | public String path; //视频的路径
18 | public long size; //视频的大小
19 | public int width; //视频的宽度
20 | public int height; //视频的高度
21 | public String mimeType; //视频的类型
22 | public long addTime; //视频的创建时间
23 | public long timeLong; //视频的时长
24 |
25 | /** 视频的路径和创建时间相同就认为是同一个视频 */
26 | @Override
27 | public boolean equals(Object o) {
28 | try {
29 | VideoItem other = (VideoItem) o;
30 | return this.path.equalsIgnoreCase(other.path) && this.addTime == other.addTime;
31 | } catch (ClassCastException e) {
32 | e.printStackTrace();
33 | }
34 | return super.equals(o);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/view/SuperCheckBox.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.SoundEffectConstants;
6 | import android.widget.CheckBox;
7 |
8 | /**
9 | * ================================================
10 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
11 | * 版 本:1.0
12 | * 创建日期:2016/5/19
13 | * 描 述:带声音的CheckBox
14 | * 修订历史:
15 | * ================================================
16 | */
17 | public class SuperCheckBox extends CheckBox {
18 |
19 | public SuperCheckBox(Context context) {
20 | super(context);
21 | }
22 |
23 | public SuperCheckBox(Context context, AttributeSet attrs) {
24 | super(context, attrs);
25 | }
26 |
27 | public SuperCheckBox(Context context, AttributeSet attrs, int defStyle) {
28 | super(context, attrs, defStyle);
29 | }
30 |
31 | @Override
32 | public boolean performClick() {
33 | final boolean handled = super.performClick();
34 | if (!handled) {
35 | // View only makes a sound effect if the onClickListener was
36 | // called, so we'll need to make one here instead.
37 | playSoundEffect(SoundEffectConstants.CLICK);
38 | }
39 | return handled;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/pbq/imagepickerdemo/imageloader/PicassoImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepickerdemo.imageloader;
2 |
3 | /**
4 | * ================================================
5 | * 作 者:jeasonlzy(廖子尧)
6 | * 版 本:1.0
7 | * 创建日期:2016/3/28
8 | * 描 述:我的Github地址 https://github.com/jeasonlzy0216
9 | * 修订历史:
10 | * ================================================
11 | */
12 |
13 | import android.app.Activity;
14 | import android.widget.ImageView;
15 |
16 | import com.pbq.imagepicker.loader.ImageLoader;
17 | import com.pbq.imagepickerdemo.R;
18 | import com.squareup.picasso.MemoryPolicy;
19 | import com.squareup.picasso.Picasso;
20 |
21 | import java.io.File;
22 |
23 | public class PicassoImageLoader implements ImageLoader {
24 |
25 | @Override
26 | public void displayImage(Activity activity, String path, ImageView imageView, int width, int height) {
27 | Picasso.with(activity)//
28 | .load(new File(path))//
29 | .placeholder(R.mipmap.default_image)//
30 | .error(R.mipmap.default_image)//
31 | .resize(width, height)//
32 | .centerInside()//
33 | .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)//
34 | .into(imageView);
35 | }
36 |
37 | @Override
38 | public void clearMemoryCache(Activity activity) {
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/view/ViewPagerFixed.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.view;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 |
8 | /**
9 | * ================================================
10 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
11 | * 版 本:1.0
12 | * 创建日期:2016/5/19
13 | * 描 述:修复图片在ViewPager控件中缩放报错的BUG
14 | * 修订历史:
15 | * ================================================
16 | */
17 | public class ViewPagerFixed extends ViewPager {
18 |
19 | public ViewPagerFixed(Context context) {
20 | super(context);
21 | }
22 |
23 | public ViewPagerFixed(Context context, AttributeSet attrs) {
24 | super(context, attrs);
25 | }
26 |
27 | @Override
28 | public boolean onTouchEvent(MotionEvent ev) {
29 | try {
30 | return super.onTouchEvent(ev);
31 | } catch (IllegalArgumentException ex) {
32 | ex.printStackTrace();
33 | }
34 | return false;
35 | }
36 |
37 | @Override
38 | public boolean onInterceptTouchEvent(MotionEvent ev) {
39 | try {
40 | return super.onInterceptTouchEvent(ev);
41 | } catch (IllegalArgumentException ex) {
42 | ex.printStackTrace();
43 | }
44 | return false;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/pbq/imagepickerdemo/imageloader/GlideImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepickerdemo.imageloader;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.net.Uri;
6 | import android.os.Environment;
7 | import android.widget.ImageView;
8 |
9 | import com.bumptech.glide.Glide;
10 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
11 | import com.pbq.imagepicker.loader.ImageLoader;
12 | import com.pbq.imagepickerdemo.R;
13 |
14 | import java.io.File;
15 |
16 | /**
17 | * ================================================
18 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
19 | * 版 本:1.0
20 | * 创建日期:2016/5/19
21 | * 描 述:
22 | * 修订历史:
23 | * ================================================
24 | */
25 | public class GlideImageLoader implements ImageLoader {
26 |
27 | @Override
28 | public void displayImage(Activity activity, String path, ImageView imageView, int width, int height) {
29 | Glide.with(activity) //配置上下文
30 | .load(Uri.fromFile(new File(path))) //设置图片路径(fix #8,文件名包含%符号 无法识别和显示)
31 | .error(R.mipmap.default_image) //设置错误图片
32 | .placeholder(R.mipmap.default_image) //设置占位图片
33 | .diskCacheStrategy( DiskCacheStrategy.NONE )
34 | .skipMemoryCache(true)
35 | .into(imageView);
36 | }
37 |
38 | @Override
39 | public void clearMemoryCache(Activity activity) {
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/pbq/imagepickerdemo/imageloader/XUtils3ImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepickerdemo.imageloader;
2 |
3 | /**
4 | * ================================================
5 | * 作 者:jeasonlzy(廖子尧)
6 | * 版 本:1.0
7 | * 创建日期:2016/3/28
8 | * 描 述:我的Github地址 https://github.com/jeasonlzy0216
9 | * 修订历史:
10 | * ================================================
11 | */
12 |
13 | import android.app.Activity;
14 | import android.graphics.Bitmap;
15 | import android.net.Uri;
16 | import android.widget.ImageView;
17 |
18 | import com.pbq.imagepicker.loader.ImageLoader;
19 | import com.pbq.imagepickerdemo.R;
20 |
21 | import org.xutils.image.ImageOptions;
22 | import org.xutils.x;
23 |
24 | import java.io.File;
25 |
26 | public class XUtils3ImageLoader implements ImageLoader {
27 | @Override
28 | public void displayImage(Activity activity, String path, ImageView imageView, int width, int height) {
29 | ImageOptions options = new ImageOptions.Builder()//
30 | .setLoadingDrawableId(R.mipmap.default_image)//
31 | .setFailureDrawableId(R.mipmap.default_image)//
32 | .setConfig(Bitmap.Config.RGB_565)//
33 | .setSize(width, height)//
34 | .setCrop(false)//
35 | .setUseMemCache(true)//
36 | .build();
37 | x.image().bind(imageView, Uri.fromFile(new File(path)).toString(), options);
38 | }
39 |
40 | @Override
41 | public void clearMemoryCache(Activity activity) {
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/activity_image_crop.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
15 |
16 |
20 |
21 |
39 |
40 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/adapter_folder_image_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
23 |
24 |
31 |
32 |
40 |
41 |
42 |
49 |
50 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/activity_image_preview.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
17 |
18 |
25 |
26 |
35 |
36 |
49 |
50 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/activity_video_preview.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
17 |
18 |
25 |
26 |
35 |
36 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/pbq/imagepickerdemo/GApp.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepickerdemo;
2 |
3 | import android.app.Application;
4 | import android.widget.ImageView;
5 |
6 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
7 | import com.nostra13.universalimageloader.core.ImageLoader;
8 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
9 |
10 | import org.xutils.image.ImageOptions;
11 | import org.xutils.x;
12 |
13 | /**
14 | * ================================================
15 | * 作 者:jeasonlzy(廖子尧)
16 | * 版 本:1.0
17 | * 创建日期:2016/4/13
18 | * 描 述:我的Github地址 https://github.com/jeasonlzy0216
19 | * 修订历史:
20 | * ================================================
21 | */
22 | public class GApp extends Application {
23 |
24 | public static DisplayImageOptions imageLoaderOptions = new DisplayImageOptions.Builder()//
25 | .showImageOnLoading(R.mipmap.default_image) //设置图片在下载期间显示的图片
26 | .showImageForEmptyUri(R.mipmap.default_image) //设置图片Uri为空或是错误的时候显示的图片
27 | .showImageOnFail(R.mipmap.default_image) //设置图片加载/解码过程中错误时候显示的图片
28 | .cacheInMemory(true) //设置下载的图片是否缓存在内存中
29 | .cacheOnDisk(true) //设置下载的图片是否缓存在SD卡中
30 | .build(); //构建完成
31 |
32 | public static ImageOptions xUtilsOptions = new ImageOptions.Builder()//
33 | .setIgnoreGif(false) //是否忽略GIF格式的图片
34 | .setImageScaleType(ImageView.ScaleType.FIT_CENTER) //缩放模式
35 | .setLoadingDrawableId(R.mipmap.default_image) //下载中显示的图片
36 | .setFailureDrawableId(R.mipmap.default_image) //下载失败显示的图片
37 | .build(); //得到ImageOptions对象
38 |
39 | @Override
40 | public void onCreate() {
41 | super.onCreate();
42 | ImageLoaderConfiguration config = ImageLoaderConfiguration.createDefault(this);
43 |
44 | ImageLoader.getInstance().init(config); //UniversalImageLoader初始化
45 | x.Ext.init(this); //xUtils3初始化
46 | }
47 | }
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/adapter_video_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
20 |
21 |
24 |
33 |
38 |
43 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ui/image/ImageBaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.ui.image;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.pm.PackageManager;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.support.annotation.NonNull;
8 | import android.support.v4.app.ActivityCompat;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.view.Window;
11 | import android.view.WindowManager;
12 | import android.widget.Toast;
13 |
14 | import com.pbq.imagepicker.R;
15 | import com.pbq.imagepicker.view.SystemBarTintManager;
16 |
17 | /**
18 | * ================================================
19 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
20 | * 版 本:1.0
21 | * 创建日期:2016/5/19
22 | * 描 述:
23 | * 修订历史:
24 | * ================================================
25 | */
26 | public class ImageBaseActivity extends AppCompatActivity {
27 |
28 | protected SystemBarTintManager tintManager;
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
34 | setTranslucentStatus(true);
35 | }
36 | tintManager = new SystemBarTintManager(this);
37 | tintManager.setStatusBarTintEnabled(true);
38 | tintManager.setStatusBarTintResource(R.color.status_bar); //设置上方状态栏的颜色
39 | }
40 |
41 | @TargetApi(19)
42 | private void setTranslucentStatus(boolean on) {
43 | Window win = getWindow();
44 | WindowManager.LayoutParams winParams = win.getAttributes();
45 | final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
46 | if (on) {
47 | winParams.flags |= bits;
48 | } else {
49 | winParams.flags &= ~bits;
50 | }
51 | win.setAttributes(winParams);
52 | }
53 |
54 | public boolean checkPermission(@NonNull String permission) {
55 | return ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
56 | }
57 |
58 | public void showToast(String toastText) {
59 | Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_SHORT).show();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/imagepicker/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
23 |
28 |
32 |
33 |
36 |
40 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/adapter_folder_video_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
19 |
26 |
27 |
28 |
34 |
35 |
42 |
43 |
51 |
52 |
53 |
60 |
61 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/Utils.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.graphics.Matrix;
8 | import android.os.Environment;
9 | import android.util.DisplayMetrics;
10 |
11 | import java.io.File;
12 | import java.io.FileOutputStream;
13 | import java.util.Random;
14 |
15 | /**
16 | * ================================================
17 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
18 | * 版 本:1.0
19 | * 创建日期:2016/5/19
20 | * 描 述:
21 | * 修订历史:
22 | * ================================================
23 | */
24 | public class Utils {
25 |
26 | /** 获得状态栏的高度 */
27 | public static int getStatusHeight(Context context) {
28 | int statusHeight = -1;
29 | try {
30 | Class> clazz = Class.forName("com.android.internal.R$dimen");
31 | Object object = clazz.newInstance();
32 | int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
33 | statusHeight = context.getResources().getDimensionPixelSize(height);
34 | } catch (Exception e) {
35 | e.printStackTrace();
36 | }
37 | return statusHeight;
38 | }
39 |
40 | /** 根据屏幕宽度与密度计算GridView显示的列数, 最少为三列,并获取Item宽度 */
41 | public static int getImageItemWidth(Activity activity) {
42 | int screenWidth = activity.getResources().getDisplayMetrics().widthPixels;
43 | int densityDpi = activity.getResources().getDisplayMetrics().densityDpi;
44 | int cols = screenWidth / densityDpi;
45 | cols = cols < 3 ? 3 : cols;
46 | int columnSpace = (int) (2 * activity.getResources().getDisplayMetrics().density);
47 | return (screenWidth - columnSpace * (cols - 1)) / cols;
48 | }
49 |
50 | /**
51 | * 判断SDCard是否可用
52 | */
53 | public static boolean existSDCard() {
54 | return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
55 | }
56 |
57 | /**
58 | * 获取手机大小(分辨率)
59 | */
60 | public static DisplayMetrics getScreenPix(Activity activity) {
61 | DisplayMetrics displaysMetrics = new DisplayMetrics();
62 | activity.getWindowManager().getDefaultDisplay().getMetrics(displaysMetrics);
63 | return displaysMetrics;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/include_top_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
25 |
26 |
36 |
37 |
52 |
53 |
63 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/activity_image_grid.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
12 |
13 |
17 |
18 |
32 |
33 |
39 |
40 |
56 |
57 |
69 |
70 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ui/image/ImagePreviewBaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.ui.image;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.RelativeLayout;
7 | import android.widget.TextView;
8 |
9 | import com.pbq.imagepicker.ImagePicker;
10 | import com.pbq.imagepicker.Utils;
11 | import com.pbq.imagepicker.adapter.image.ImagePageAdapter;
12 | import com.pbq.imagepicker.bean.ImageItem;
13 | import com.pbq.imagepicker.view.ViewPagerFixed;
14 |
15 | import java.util.ArrayList;
16 |
17 | /**
18 | * ================================================
19 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
20 | * 版 本:1.0
21 | * 创建日期:2016/5/19
22 | * 描 述:
23 | * 修订历史:图片预览的基类
24 | * ================================================
25 | */
26 | public abstract class ImagePreviewBaseActivity extends ImageBaseActivity {
27 |
28 | protected ImagePicker imagePicker;
29 | protected ArrayList mImageItems; //跳转进ImagePreviewFragment的图片文件夹
30 | protected int mCurrentPosition = 0; //跳转进ImagePreviewFragment时的序号,第几个图片
31 | protected TextView mTitleCount; //显示当前图片的位置 例如 5/31
32 | protected ArrayList selectedImages; //所有已经选中的图片
33 | protected View content;
34 | protected View topBar;
35 | protected ViewPagerFixed mViewPager;
36 | protected ImagePageAdapter mAdapter;
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | setContentView(com.pbq.imagepicker.R.layout.activity_image_preview);
42 |
43 | mCurrentPosition = getIntent().getIntExtra(ImagePicker.EXTRA_SELECTED_IMAGE_POSITION, 0);
44 | mImageItems = (ArrayList) getIntent().getSerializableExtra(ImagePicker.EXTRA_IMAGE_ITEMS);
45 | imagePicker = ImagePicker.getInstance();
46 | selectedImages = imagePicker.getSelectedImages();
47 |
48 | //初始化控件
49 | content = findViewById(com.pbq.imagepicker.R.id.content);
50 |
51 | //因为状态栏透明后,布局整体会上移,所以给头部加上状态栏的margin值,保证头部不会被覆盖
52 | topBar = findViewById(com.pbq.imagepicker.R.id.top_bar);
53 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
54 | RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) topBar.getLayoutParams();
55 | params.topMargin = Utils.getStatusHeight(this);
56 | topBar.setLayoutParams(params);
57 | }
58 | topBar.findViewById(com.pbq.imagepicker.R.id.btn_ok).setVisibility(View.GONE);
59 | topBar.findViewById(com.pbq.imagepicker.R.id.btn_back).setOnClickListener(new View.OnClickListener() {
60 | @Override
61 | public void onClick(View v) {
62 | finish();
63 | }
64 | });
65 |
66 | mTitleCount = (TextView) findViewById(com.pbq.imagepicker.R.id.tv_des);
67 |
68 | mViewPager = (ViewPagerFixed) findViewById(com.pbq.imagepicker.R.id.viewpager);
69 | mAdapter = new ImagePageAdapter(this, mImageItems);
70 | mAdapter.setPhotoViewClickListener(new ImagePageAdapter.PhotoViewClickListener() {
71 | @Override
72 | public void OnPhotoTapListener(View view) {
73 | onImageSingleTap();
74 | }
75 | });
76 | mViewPager.setAdapter(mAdapter);
77 | mViewPager.setCurrentItem(mCurrentPosition, false);
78 |
79 | //初始化当前页面的状态
80 | mTitleCount.setText(getString(com.pbq.imagepicker.R.string.preview_image_count, mCurrentPosition + 1, mImageItems.size()));
81 | }
82 |
83 | /** 单击时,隐藏头和尾 */
84 | public abstract void onImageSingleTap();
85 | }
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/adapter/image/ImagePageAdapter.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.adapter.image;
2 |
3 | import android.app.Activity;
4 | import android.support.v4.view.PagerAdapter;
5 | import android.util.DisplayMetrics;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.ImageView;
9 | import com.pbq.imagepicker.ImagePicker;
10 | import com.pbq.imagepicker.Utils;
11 | import com.pbq.imagepicker.bean.ImageItem;
12 | import java.util.ArrayList;
13 |
14 | /**
15 | * ================================================
16 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
17 | * 版 本:1.0
18 | * 创建日期:2016/5/19
19 | * 描 述:
20 | * 修订历史:
21 | * ================================================
22 | */
23 | public class ImagePageAdapter extends PagerAdapter {
24 |
25 | private int screenWidth;
26 | private int screenHeight;
27 | private ImagePicker imagePicker;
28 | private ArrayList images = new ArrayList<>();
29 | private Activity mActivity;
30 | public PhotoViewClickListener listener;
31 |
32 | public ImagePageAdapter(Activity activity, ArrayList images) {
33 | this.mActivity = activity;
34 | this.images = images;
35 |
36 | DisplayMetrics dm = Utils.getScreenPix(activity);
37 | screenWidth = dm.widthPixels;
38 | screenHeight = dm.heightPixels;
39 | imagePicker = ImagePicker.getInstance();
40 | }
41 |
42 | public void setData(ArrayList images) {
43 | this.images = images;
44 | }
45 |
46 | public void setPhotoViewClickListener(PhotoViewClickListener listener) {
47 | this.listener = listener;
48 | }
49 |
50 | @Override
51 | public Object instantiateItem(ViewGroup container, int position) {
52 | // PhotoView photoView = new PhotoView(mActivity);
53 | // ImageItem imageItem = images.get(position);
54 | // imagePicker.getImageLoader().displayImage(mActivity, imageItem.path, photoView, screenWidth, screenHeight);
55 | // photoView.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() {
56 | // @Override
57 | // public void onPhotoTap(View view, float x, float y) {
58 | // if (listener != null) listener.OnPhotoTapListener(view, x, y);
59 | // }
60 | // });
61 | // container.addView(photoView);
62 | // return photoView;
63 |
64 | ImageView photoView = new ImageView(mActivity);
65 | ImageItem imageItem = images.get(position);
66 | imagePicker.getImageLoader().displayImage(mActivity, imageItem.path, photoView, screenWidth, screenHeight);
67 | photoView.setOnClickListener(new View.OnClickListener() {
68 | @Override
69 | public void onClick(View view) {
70 | if (listener != null) listener.OnPhotoTapListener(view);
71 | }
72 | });
73 | container.addView(photoView);
74 | return photoView;
75 | }
76 |
77 | @Override
78 | public int getCount() {
79 | return images.size();
80 | }
81 |
82 | @Override
83 | public boolean isViewFromObject(View view, Object object) {
84 | return view == object;
85 | }
86 |
87 | @Override
88 | public void destroyItem(ViewGroup container, int position, Object object) {
89 | container.removeView((View) object);
90 | }
91 |
92 | @Override
93 | public int getItemPosition(Object object) {
94 | return POSITION_NONE;
95 | }
96 |
97 | public interface PhotoViewClickListener {
98 | void OnPhotoTapListener(View view);
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ui/video/VideoPreviewBaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.ui.video;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.RelativeLayout;
7 | import android.widget.TextView;
8 |
9 | import com.pbq.imagepicker.Utils;
10 | import com.pbq.imagepicker.VideoPicker;
11 | import com.pbq.imagepicker.adapter.video.VideoPageAdapter;
12 | import com.pbq.imagepicker.bean.VideoItem;
13 | import com.pbq.imagepicker.ui.image.ImageBaseActivity;
14 | import com.pbq.imagepicker.view.ViewPagerFixed;
15 |
16 | import java.util.ArrayList;
17 |
18 | /**
19 | * ================================================
20 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
21 | * 版 本:1.0
22 | * 创建日期:2016/5/19
23 | * 描 述:
24 | * 修订历史:视频预览的基类
25 | * ================================================
26 | */
27 | public abstract class VideoPreviewBaseActivity extends ImageBaseActivity {
28 |
29 | protected VideoPicker videoPicker;
30 | protected ArrayList mVideoItems; //跳转进VideoPreviewFragment的视频文件夹
31 | protected int mCurrentPosition = 0; //跳转进VideoPreviewFragment时的序号,第几个视频
32 | protected TextView mTitleCount; //显示当前视频的位置 例如 5/31
33 | protected ArrayList selectedVideos; //所有已经选中的视频
34 | protected View content;
35 | protected View topBar;
36 | protected ViewPagerFixed mViewPager;
37 | protected VideoPageAdapter mAdapter;
38 |
39 | @Override
40 | protected void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setContentView(com.pbq.imagepicker.R.layout.activity_video_preview);
43 |
44 | mCurrentPosition = getIntent().getIntExtra(VideoPicker.EXTRA_SELECTED_VIDEO_POSITION, 0);
45 | mVideoItems = (ArrayList) getIntent().getSerializableExtra(VideoPicker.EXTRA_VIDEO_ITEMS);
46 | videoPicker = VideoPicker.getInstance();
47 | selectedVideos = videoPicker.getSelectedVideos();
48 |
49 | //初始化控件
50 | content = findViewById(com.pbq.imagepicker.R.id.content);
51 |
52 | //因为状态栏透明后,布局整体会上移,所以给头部加上状态栏的margin值,保证头部不会被覆盖
53 | topBar = findViewById(com.pbq.imagepicker.R.id.top_bar);
54 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
55 | RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) topBar.getLayoutParams();
56 | params.topMargin = Utils.getStatusHeight(this);
57 | topBar.setLayoutParams(params);
58 | }
59 | topBar.findViewById(com.pbq.imagepicker.R.id.btn_ok).setVisibility(View.GONE);
60 | topBar.findViewById(com.pbq.imagepicker.R.id.btn_back).setOnClickListener(new View.OnClickListener() {
61 | @Override
62 | public void onClick(View v) {
63 | finish();
64 | }
65 | });
66 |
67 | mTitleCount = (TextView) findViewById(com.pbq.imagepicker.R.id.tv_des);
68 |
69 | mViewPager = (ViewPagerFixed) findViewById(com.pbq.imagepicker.R.id.viewpager);
70 | mAdapter = new VideoPageAdapter(this, mVideoItems);
71 | mAdapter.setPhotoViewClickListener(new VideoPageAdapter.PhotoViewClickListener() {
72 | @Override
73 | public void OnPhotoTapListener(View view) {
74 | onVideoSingleTap();
75 | }
76 | });
77 | mViewPager.setAdapter(mAdapter);
78 | mViewPager.setCurrentItem(mCurrentPosition, false);
79 |
80 | //初始化当前页面的状态
81 | mTitleCount.setText(getString(com.pbq.imagepicker.R.string.preview_image_count, mCurrentPosition + 1, mVideoItems.size()));
82 | }
83 |
84 | /** 单击时,隐藏头和尾 */
85 | public abstract void onVideoSingleTap();
86 | }
--------------------------------------------------------------------------------
/imagepicker/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | // 这里添加下面两行代码。
3 | apply plugin: 'com.github.dcendents.android-maven'
4 | apply plugin: 'com.jfrog.bintray'
5 | android {
6 | compileSdkVersion 24
7 | buildToolsVersion "24.0.2"
8 |
9 | defaultConfig {
10 | minSdkVersion 11
11 | targetSdkVersion 24
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | }
22 |
23 | dependencies {
24 | compile fileTree(dir: 'libs', include: ['*.jar'])
25 | compile 'com.android.support:appcompat-v7:24.2.1'
26 | // compile 'com.github.chrisbanes.photoview:library:1.2.4'
27 | compile 'com.github.bumptech.glide:glide:3.7.0'
28 | }
29 | //版本
30 | version = "1.2.0"
31 |
32 | // 定义两个链接,下面会用到。
33 | def siteUrl = 'https://github.com/pbq18785109289/ImagePicker-master' // 项目主页。
34 | def gitUrl = 'https://github.com/pbq18785109289/ImagePicker-master.git' // Git仓库的url。
35 |
36 | group = "com.pbq"
37 | install {
38 | repositories.mavenInstaller {
39 | // 生成pom.xml和参数
40 | pom {
41 | project {
42 | packaging 'aar'
43 | // 项目描述,复制我的话,这里需要修改。
44 | name 'ImagePicker For Android'// 可选,项目名称。
45 | description 'The Android build the framework of the image and video.'// 可选,项目描述。
46 | url siteUrl // 项目主页,这里是引用上面定义好。
47 |
48 | // 软件开源协议,现在一般都是Apache License2.0吧,复制我的,这里不需要修改。
49 | licenses {
50 | license {
51 | name 'The Apache Software License, Version 2.0'
52 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
53 | }
54 | }
55 |
56 | //填写开发者基本信息,复制我的,这里需要修改。
57 | developers {
58 | developer {
59 | id 'pbq' // 开发者的id。
60 | name 'pbq' // 开发者名字。
61 | email '870931145@qq.com' // 开发者邮箱。
62 | }
63 | }
64 |
65 | // SCM,复制我的,这里不需要修改。
66 | scm {
67 | connection gitUrl // Git仓库地址。
68 | developerConnection gitUrl // Git仓库地址。
69 | url siteUrl // 项目主页。
70 | }
71 | }
72 | }
73 | }
74 | }
75 | // 生成jar包的task,不需要修改。
76 | task sourcesJar(type: Jar) {
77 | from android.sourceSets.main.java.srcDirs
78 | classifier = 'sources'
79 | }
80 | // 生成jarDoc的task,不需要修改。
81 | task javadoc(type: Javadoc) {
82 | source = android.sourceSets.main.java.srcDirs
83 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
84 | // destinationDir = file("../javadoc/")
85 | failOnError false // 忽略注释语法错误,如果用jdk1.8你的注释写的不规范就编译不过。
86 | }
87 | // 生成javaDoc的jar,不需要修改。
88 | task javadocJar(type: Jar, dependsOn: javadoc) {
89 | classifier = 'javadoc'
90 | from javadoc.destinationDir
91 | }
92 | artifacts {
93 | archives javadocJar
94 | archives sourcesJar
95 | }
96 |
97 | // 这里是读取Bintray相关的信息,我们上传项目到github上的时候会把gradle文件传上去,所以不要把帐号密码的信息直接写在这里,写在local.properties中,这里动态读取。
98 | Properties properties = new Properties()
99 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
100 | bintray {
101 | user = properties.getProperty("bintray.user") // Bintray的用户名。
102 | key = properties.getProperty("bintray.apikey") // Bintray刚才保存的ApiKey。
103 |
104 | configurations = ['archives']
105 | pkg {
106 | repo = "maven" // 上传到maven库。
107 | name = "imagepicker"
108 | websiteUrl = siteUrl
109 | vcsUrl = gitUrl
110 | licenses = ["Apache-2.0"]
111 | publish = true // 是否是公开项目。
112 | }
113 | }
114 | //apply from: '../bintray.gradle'
--------------------------------------------------------------------------------
/app/src/main/java/com/pbq/imagepickerdemo/wxdemo/ImagePickerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepickerdemo.wxdemo;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.ImageView;
10 |
11 | import com.pbq.imagepicker.ImagePicker;
12 | import com.pbq.imagepicker.bean.ImageItem;
13 | import com.pbq.imagepickerdemo.R;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * ================================================
20 | * 作 者:ikkong (ikkong@163.com),修改 jeasonlzy(廖子尧)
21 | * 版 本:1.0
22 | * 创建日期:2016/5/19
23 | * 描 述:
24 | * 修订历史:微信图片选择的Adapter, 感谢 ikkong 的提交
25 | * ================================================
26 | */
27 | public class ImagePickerAdapter extends RecyclerView.Adapter {
28 | private int maxImgCount;
29 | private Context mContext;
30 | private List mData;
31 | private LayoutInflater mInflater;
32 | private OnRecyclerViewItemClickListener listener;
33 | private boolean isAdded; //是否额外添加了最后一个图片
34 |
35 | public interface OnRecyclerViewItemClickListener {
36 | void onItemClick(View view, int position);
37 | }
38 |
39 | public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
40 | this.listener = listener;
41 | }
42 |
43 | public void setImages(List data) {
44 | mData = new ArrayList<>(data);
45 | if (getItemCount() < maxImgCount) {
46 | mData.add(new ImageItem());
47 | isAdded = true;
48 | } else {
49 | isAdded = false;
50 | }
51 | notifyDataSetChanged();
52 | }
53 |
54 | public List getImages() {
55 | //由于图片未选满时,最后一张显示添加图片,因此这个方法返回真正的已选图片
56 | if (isAdded) return new ArrayList<>(mData.subList(0, mData.size() - 1));
57 | else return mData;
58 | }
59 |
60 | public ImagePickerAdapter(Context mContext, List data, int maxImgCount) {
61 | this.mContext = mContext;
62 | this.maxImgCount = maxImgCount;
63 | this.mInflater = LayoutInflater.from(mContext);
64 | setImages(data);
65 | }
66 |
67 | @Override
68 | public SelectedPicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
69 | return new SelectedPicViewHolder(mInflater.inflate(R.layout.list_item_image, parent, false));
70 | }
71 |
72 | @Override
73 | public void onBindViewHolder(SelectedPicViewHolder holder, int position) {
74 | holder.bind(position);
75 | }
76 |
77 | @Override
78 | public int getItemCount() {
79 | return mData.size();
80 | }
81 |
82 | public class SelectedPicViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
83 |
84 | private ImageView iv_img;
85 | private int clickPosition;
86 |
87 | public SelectedPicViewHolder(View itemView) {
88 | super(itemView);
89 | iv_img = (ImageView) itemView.findViewById(R.id.iv_img);
90 | }
91 |
92 | public void bind(int position) {
93 | //设置条目的点击事件
94 | itemView.setOnClickListener(this);
95 | //根据条目位置设置图片
96 | ImageItem item = mData.get(position);
97 | if (isAdded && position == getItemCount() - 1) {
98 | iv_img.setImageResource(R.drawable.selector_image_add);
99 | clickPosition = WxDemoActivity.IMAGE_ITEM_ADD;
100 | } else {
101 | ImagePicker.getInstance().getImageLoader().displayImage((Activity) mContext, item.path, iv_img, 0, 0);
102 | clickPosition = position;
103 | }
104 | }
105 |
106 | @Override
107 | public void onClick(View v) {
108 | if (listener != null) listener.onItemClick(v, clickPosition);
109 | }
110 | }
111 | }
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/adapter/image/ImageFolderAdapter.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.adapter.image;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.BaseAdapter;
9 | import android.widget.ImageView;
10 | import android.widget.TextView;
11 |
12 | import com.bumptech.glide.Glide;
13 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
14 | import com.pbq.imagepicker.ImagePicker;
15 | import com.pbq.imagepicker.R;
16 | import com.pbq.imagepicker.Utils;
17 | import com.pbq.imagepicker.bean.ImageFolder;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * ================================================
24 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
25 | * 版 本:1.0
26 | * 创建日期:2016/5/19
27 | * 描 述:
28 | * 修订历史:
29 | * ================================================
30 | */
31 | public class ImageFolderAdapter extends BaseAdapter {
32 |
33 | private ImagePicker imagePicker;
34 | private Activity mActivity;
35 | private LayoutInflater mInflater;
36 | private int mImageSize;
37 | private List imageFolders;
38 | private int lastSelected = 0;
39 |
40 | public ImageFolderAdapter(Activity activity, List folders) {
41 | mActivity = activity;
42 | if (folders != null && folders.size() > 0) imageFolders = folders;
43 | else imageFolders = new ArrayList<>();
44 |
45 | imagePicker = ImagePicker.getInstance();
46 | mImageSize = Utils.getImageItemWidth(mActivity);
47 | mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
48 | }
49 |
50 | public void refreshData(List folders) {
51 | if (folders != null && folders.size() > 0) imageFolders = folders;
52 | else imageFolders.clear();
53 | notifyDataSetChanged();
54 | }
55 |
56 | @Override
57 | public int getCount() {
58 | return imageFolders.size();
59 | }
60 |
61 | @Override
62 | public ImageFolder getItem(int position) {
63 | return imageFolders.get(position);
64 | }
65 |
66 | @Override
67 | public long getItemId(int position) {
68 | return position;
69 | }
70 |
71 | @Override
72 | public View getView(int position, View convertView, ViewGroup parent) {
73 | ViewHolder holder;
74 | if (convertView == null) {
75 | convertView = mInflater.inflate(R.layout.adapter_folder_image_item, parent, false);
76 | holder = new ViewHolder(convertView);
77 | } else {
78 | holder = (ViewHolder) convertView.getTag();
79 | }
80 |
81 | ImageFolder folder = getItem(position);
82 | holder.folderName.setText(folder.name);
83 | holder.imageCount.setText(mActivity.getString(R.string.folder_image_count, folder.images.size()));
84 | imagePicker.getImageLoader().displayImage(mActivity, folder.cover.path, holder.cover, mImageSize, mImageSize);
85 | if (lastSelected == position) {
86 | holder.folderCheck.setVisibility(View.VISIBLE);
87 | } else {
88 | holder.folderCheck.setVisibility(View.INVISIBLE);
89 | }
90 |
91 | return convertView;
92 | }
93 |
94 | public void setSelectIndex(int i) {
95 | if (lastSelected == i) {
96 | return;
97 | }
98 | lastSelected = i;
99 | notifyDataSetChanged();
100 | }
101 |
102 | public int getSelectIndex() {
103 | return lastSelected;
104 | }
105 |
106 | private class ViewHolder {
107 | ImageView cover;
108 | TextView folderName;
109 | TextView imageCount;
110 | ImageView folderCheck;
111 |
112 | public ViewHolder(View view) {
113 | cover = (ImageView) view.findViewById(R.id.iv_cover);
114 | folderName = (TextView) view.findViewById(R.id.tv_folder_name);
115 | imageCount = (TextView) view.findViewById(R.id.tv_image_count);
116 | folderCheck = (ImageView) view.findViewById(R.id.iv_folder_check);
117 | view.setTag(this);
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ui/image/ImagePreviewDelActivity.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.ui.image;
2 |
3 | import android.content.DialogInterface;
4 | import android.content.Intent;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.support.v4.view.ViewPager;
8 | import android.support.v7.app.AlertDialog;
9 | import android.view.View;
10 | import android.view.animation.AnimationUtils;
11 | import android.widget.ImageView;
12 |
13 | import com.pbq.imagepicker.ImagePicker;
14 | import com.pbq.imagepicker.R;
15 |
16 | /**
17 | * ================================================
18 | * 作 者:jeasonlzy(廖子尧),ikkong (ikkong@163.com)
19 | * 版 本:1.0
20 | * 创建日期:2016/5/19
21 | * 描 述:
22 | * 修订历史:预览已经选择的图片,并可以删除, 感谢 ikkong 的提交
23 | * ================================================
24 | */
25 | public class ImagePreviewDelActivity extends ImagePreviewBaseActivity implements View.OnClickListener {
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 |
31 | ImageView mBtnDel = (ImageView) findViewById(R.id.btn_del);
32 | mBtnDel.setOnClickListener(this);
33 | mBtnDel.setVisibility(View.VISIBLE);
34 | topBar.findViewById(R.id.btn_back).setOnClickListener(this);
35 |
36 | mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mImageItems.size()));
37 | //滑动ViewPager的时候,根据外界的数据改变当前的选中状态和当前的图片的位置描述文本
38 | mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
39 | @Override
40 | public void onPageSelected(int position) {
41 | mCurrentPosition = position;
42 | mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mImageItems.size()));
43 | }
44 | });
45 | }
46 |
47 | @Override
48 | public void onClick(View v) {
49 | int id = v.getId();
50 | if (id == R.id.btn_del) {
51 | showDeleteDialog();
52 | } else if (id == R.id.btn_back) {
53 | onBackPressed();
54 | }
55 | }
56 |
57 | /** 是否删除此张图片 */
58 | private void showDeleteDialog() {
59 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
60 | builder.setTitle("提示");
61 | builder.setMessage("要删除这张照片吗?");
62 | builder.setNegativeButton("取消", null);
63 | builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
64 | @Override
65 | public void onClick(DialogInterface dialog, int which) {
66 | //移除当前图片刷新界面
67 | mImageItems.remove(mCurrentPosition);
68 | if (mImageItems.size() > 0) {
69 | mAdapter.setData(mImageItems);
70 | mAdapter.notifyDataSetChanged();
71 | mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mImageItems.size()));
72 | } else {
73 | onBackPressed();
74 | }
75 | }
76 | });
77 | builder.show();
78 | }
79 |
80 | @Override
81 | public void onBackPressed() {
82 | Intent intent = new Intent();
83 | //带回最新数据
84 | intent.putExtra(ImagePicker.EXTRA_IMAGE_ITEMS, mImageItems);
85 | setResult(ImagePicker.RESULT_IMAGE_BACK, intent);
86 | finish();
87 | super.onBackPressed();
88 | }
89 |
90 | /** 单击时,隐藏头和尾 */
91 | @Override
92 | public void onImageSingleTap() {
93 | if (topBar.getVisibility() == View.VISIBLE) {
94 | topBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.top_out));
95 | topBar.setVisibility(View.GONE);
96 | tintManager.setStatusBarTintResource(R.color.transparent);//通知栏所需颜色
97 | //给最外层布局加上这个属性表示,Activity全屏显示,且状态栏被隐藏覆盖掉。
98 | if (Build.VERSION.SDK_INT >= 16) content.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
99 | } else {
100 | topBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.top_in));
101 | topBar.setVisibility(View.VISIBLE);
102 | tintManager.setStatusBarTintResource(R.color.status_bar);//通知栏所需颜色
103 | //Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住
104 | if (Build.VERSION.SDK_INT >= 16) content.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
105 | }
106 | }
107 | }
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/adapter/video/VideoFolderAdapter.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.adapter.video;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.BaseAdapter;
9 | import android.widget.ImageView;
10 | import android.widget.TextView;
11 |
12 | import com.bumptech.glide.Glide;
13 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
14 | import com.pbq.imagepicker.R;
15 | import com.pbq.imagepicker.Utils;
16 | import com.pbq.imagepicker.VideoPicker;
17 | import com.pbq.imagepicker.bean.VideoFolder;
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | /**
22 | * ================================================
23 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
24 | * 版 本:1.0
25 | * 创建日期:2016/5/19
26 | * 描 述:
27 | * 修订历史:
28 | * ================================================
29 | */
30 | public class VideoFolderAdapter extends BaseAdapter {
31 |
32 | private VideoPicker videoPicker;
33 | private Activity mActivity;
34 | private LayoutInflater mInflater;
35 | private int mVideoSize;
36 | private List videoFolders;
37 | private int lastSelected = 0;
38 |
39 | public VideoFolderAdapter(Activity activity, List folders) {
40 | mActivity = activity;
41 | if (folders != null && folders.size() > 0) videoFolders = folders;
42 | else videoFolders = new ArrayList<>();
43 | videoPicker = VideoPicker.getInstance();
44 | mVideoSize = Utils.getImageItemWidth(mActivity);
45 | mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
46 | }
47 |
48 | public void refreshData(List folders) {
49 | if (folders != null && folders.size() > 0) videoFolders = folders;
50 | else videoFolders.clear();
51 | notifyDataSetChanged();
52 | }
53 |
54 | @Override
55 | public int getCount() {
56 | return videoFolders.size();
57 | }
58 |
59 | @Override
60 | public VideoFolder getItem(int position) {
61 | return videoFolders.get(position);
62 | }
63 |
64 | @Override
65 | public long getItemId(int position) {
66 | return position;
67 | }
68 |
69 | @Override
70 | public View getView(int position, View convertView, ViewGroup parent) {
71 | ViewHolder holder;
72 | if (convertView == null) {
73 | convertView = mInflater.inflate(R.layout.adapter_folder_video_item, parent, false);
74 | holder = new ViewHolder(convertView);
75 | } else {
76 | holder = (ViewHolder) convertView.getTag();
77 | }
78 |
79 | VideoFolder folder = getItem(position);
80 | holder.folderName.setText(folder.name);
81 | holder.videoCount.setText(mActivity.getString(R.string.folder_image_count, folder.videos.size()));
82 | Glide.with(mActivity)
83 | .load(folder.cover.path)
84 | .placeholder(R.mipmap.default_image)
85 | .skipMemoryCache(true)
86 | .diskCacheStrategy(DiskCacheStrategy.NONE)
87 | .into(holder.cover);
88 | /**
89 | * 选中文件夹标记可见
90 | */
91 | if (lastSelected == position) {
92 | holder.folderCheck.setVisibility(View.VISIBLE);
93 | } else {
94 | holder.folderCheck.setVisibility(View.INVISIBLE);
95 | }
96 |
97 | return convertView;
98 | }
99 |
100 | public void setSelectIndex(int i) {
101 | if (lastSelected == i) {
102 | return;
103 | }
104 | lastSelected = i;
105 | notifyDataSetChanged();
106 | }
107 |
108 | public int getSelectIndex() {
109 | return lastSelected;
110 | }
111 |
112 | private class ViewHolder {
113 | ImageView cover;
114 | TextView folderName;
115 | TextView videoCount;
116 | ImageView folderCheck;
117 |
118 | public ViewHolder(View view) {
119 | cover = (ImageView) view.findViewById(R.id.iv_cover);
120 | folderName = (TextView) view.findViewById(R.id.tv_folder_name);
121 | videoCount = (TextView) view.findViewById(R.id.tv_image_count);
122 | folderCheck = (ImageView) view.findViewById(R.id.iv_folder_check);
123 | view.setTag(this);
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/adapter/video/VideoPageAdapter.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.adapter.video;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.support.v4.view.PagerAdapter;
7 | import android.util.DisplayMetrics;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ImageButton;
11 | import android.widget.ImageView;
12 |
13 | import com.bumptech.glide.Glide;
14 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
15 | import com.pbq.imagepicker.R;
16 | import com.pbq.imagepicker.Utils;
17 | import com.pbq.imagepicker.VideoPicker;
18 | import com.pbq.imagepicker.bean.VideoItem;
19 |
20 | import java.util.ArrayList;
21 |
22 | /**
23 | * ================================================
24 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
25 | * 版 本:1.0
26 | * 创建日期:2016/5/19
27 | * 描 述:
28 | * 修订历史:
29 | * ================================================
30 | */
31 | public class VideoPageAdapter extends PagerAdapter {
32 |
33 | private int screenWidth;
34 | private int screenHeight;
35 | private VideoPicker videoPicker;
36 | private ArrayList videos = new ArrayList<>();
37 | private Activity mActivity;
38 | public PhotoViewClickListener listener;
39 |
40 | /**
41 | * 构造函数
42 | * @param activity
43 | * @param videos 视频数据源
44 | */
45 | public VideoPageAdapter(Activity activity, ArrayList videos) {
46 | this.mActivity = activity;
47 | this.videos = videos;
48 |
49 | DisplayMetrics dm = Utils.getScreenPix(activity);
50 | screenWidth = dm.widthPixels;
51 | screenHeight = dm.heightPixels;
52 | videoPicker = VideoPicker.getInstance();
53 | }
54 |
55 | public void setData(ArrayList videos) {
56 | this.videos = videos;
57 | }
58 |
59 | public void setPhotoViewClickListener(PhotoViewClickListener listener) {
60 | this.listener = listener;
61 | }
62 |
63 | /**
64 | * 实例化一个页卡
65 | * @param container
66 | * @param position
67 | * @return
68 | */
69 | @Override
70 | public Object instantiateItem(ViewGroup container, final int position) {
71 | View view=mActivity.getLayoutInflater().inflate(com.pbq.imagepicker.R.layout.viewpager_video_item,null);
72 | ImageView imageview = (ImageView) view.findViewById(com.pbq.imagepicker.R.id.imageview);
73 | ImageButton btnPlay = (ImageButton) view.findViewById(com.pbq.imagepicker.R.id.btn_play);
74 | final VideoItem videoItem = videos.get(position);
75 | Glide.with(mActivity)
76 | .load(videoItem.path)
77 | .placeholder(R.mipmap.default_image)
78 | .skipMemoryCache(true)
79 | .diskCacheStrategy(DiskCacheStrategy.NONE)
80 | .into(imageview);
81 | /**
82 | * 点击播放播放视频
83 | */
84 | btnPlay.setOnClickListener(new View.OnClickListener() {
85 | @Override
86 | public void onClick(View view) {
87 | Uri uri = Uri.parse(videoItem.path);
88 | //调用系统自带的播放器
89 | Intent intent = new Intent(Intent.ACTION_VIEW);
90 | intent.setDataAndType(uri, "video/mp4");
91 | mActivity.startActivity(intent);
92 | }
93 | });
94 | imageview.setOnClickListener(new View.OnClickListener() {
95 | @Override
96 | public void onClick(View view) {
97 | if (listener != null) listener.OnPhotoTapListener(view);
98 | }
99 | });
100 | container.addView(view);
101 | return view;
102 | }
103 |
104 | /**
105 | * 返回页卡的数量
106 | * @return
107 | */
108 | @Override
109 | public int getCount() {
110 | return videos.size();
111 | }
112 |
113 | /**
114 | * view是否来自于对象
115 | * @param view
116 | * @param object
117 | * @return
118 | */
119 | @Override
120 | public boolean isViewFromObject(View view, Object object) {
121 | return view == object;
122 | }
123 |
124 | /**
125 | * 销毁一个页卡
126 | * @param container
127 | * @param position
128 | * @param object
129 | */
130 | @Override
131 | public void destroyItem(ViewGroup container, int position, Object object) {
132 | container.removeView((View) object);
133 | }
134 |
135 | @Override
136 | public int getItemPosition(Object object) {
137 | return POSITION_NONE;
138 | }
139 |
140 | public interface PhotoViewClickListener {
141 | void OnPhotoTapListener(View view);
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/app/src/main/java/com/pbq/imagepickerdemo/wxdemo/WxDemoActivity.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepickerdemo.wxdemo;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.GridLayoutManager;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.view.View;
9 |
10 | import com.pbq.imagepicker.ImagePicker;
11 | import com.pbq.imagepicker.bean.ImageItem;
12 | import com.pbq.imagepicker.ui.image.ImageGridActivity;
13 | import com.pbq.imagepicker.ui.image.ImagePreviewDelActivity;
14 | import com.pbq.imagepicker.view.CropImageView;
15 | import com.pbq.imagepickerdemo.R;
16 | import com.pbq.imagepickerdemo.imageloader.GlideImageLoader;
17 |
18 | import java.util.ArrayList;
19 |
20 | /**
21 | * ================================================
22 | * 作 者:ikkong (ikkong@163.com),修改 jeasonlzy(廖子尧)
23 | * 版 本:1.0
24 | * 创建日期:2016/5/19
25 | * 描 述:
26 | * 修订历史:微信图片选择的Adapter, 感谢 ikkong 的提交
27 | * ================================================
28 | */
29 | public class WxDemoActivity extends AppCompatActivity implements ImagePickerAdapter.OnRecyclerViewItemClickListener {
30 |
31 | public static final int IMAGE_ITEM_ADD = -1;
32 | public static final int REQUEST_CODE_SELECT = 100;
33 | public static final int REQUEST_CODE_PREVIEW = 101;
34 |
35 | private ImagePickerAdapter adapter;
36 | private ArrayList selImageList; //当前选择的所有图片
37 | private int maxImgCount = 8; //允许选择图片最大数
38 |
39 | @Override
40 | protected void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setContentView(R.layout.activity_wxdemo);
43 |
44 | //最好放到 Application oncreate执行
45 | initImagePicker();
46 | initWidget();
47 | }
48 |
49 | private void initImagePicker() {
50 | ImagePicker imagePicker = ImagePicker.getInstance();
51 | imagePicker.setImageLoader(new GlideImageLoader()); //设置图片加载器
52 | imagePicker.setShowCamera(true); //显示拍照按钮
53 | imagePicker.setCrop(false); //允许裁剪(单选才有效)
54 | imagePicker.setSaveRectangle(true); //是否按矩形区域保存
55 | imagePicker.setSelectLimit(maxImgCount); //选中数量限制
56 | imagePicker.setStyle(CropImageView.Style.RECTANGLE); //裁剪框的形状
57 | imagePicker.setFocusWidth(800); //裁剪框的宽度。单位像素(圆形自动取宽高最小值)
58 | imagePicker.setFocusHeight(800); //裁剪框的高度。单位像素(圆形自动取宽高最小值)
59 | imagePicker.setOutPutX(1000); //保存文件的宽度。单位像素
60 | imagePicker.setOutPutY(1000); //保存文件的高度。单位像素
61 | }
62 |
63 | private void initWidget() {
64 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
65 | selImageList = new ArrayList<>();
66 | adapter = new ImagePickerAdapter(this, selImageList, maxImgCount);
67 | adapter.setOnItemClickListener(this);
68 |
69 | recyclerView.setLayoutManager(new GridLayoutManager(this, 4));
70 | recyclerView.setHasFixedSize(true);
71 | recyclerView.setAdapter(adapter);
72 | }
73 |
74 | @Override
75 | public void onItemClick(View view, int position) {
76 | switch (position) {
77 | case IMAGE_ITEM_ADD:
78 | //打开选择,本次允许选择的数量
79 | ImagePicker.getInstance().setSelectLimit(maxImgCount - selImageList.size());
80 | Intent intent = new Intent(this, ImageGridActivity.class);
81 | startActivityForResult(intent, REQUEST_CODE_SELECT);
82 | break;
83 | default:
84 | //打开预览
85 | Intent intentPreview = new Intent(this, ImagePreviewDelActivity.class);
86 | intentPreview.putExtra(ImagePicker.EXTRA_IMAGE_ITEMS, (ArrayList) adapter.getImages());
87 | intentPreview.putExtra(ImagePicker.EXTRA_SELECTED_IMAGE_POSITION, position);
88 | startActivityForResult(intentPreview, REQUEST_CODE_PREVIEW);
89 | break;
90 | }
91 | }
92 |
93 | @Override
94 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
95 | super.onActivityResult(requestCode, resultCode, data);
96 | if (resultCode == ImagePicker.RESULT_IMAGE_ITEMS) {
97 | //添加图片返回
98 | if (data != null && requestCode == REQUEST_CODE_SELECT) {
99 | ArrayList images = (ArrayList) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS);
100 | selImageList.addAll(images);
101 | adapter.setImages(selImageList);
102 | }
103 | } else if (resultCode == ImagePicker.RESULT_IMAGE_BACK) {
104 | //预览图片返回
105 | if (data != null && requestCode == REQUEST_CODE_PREVIEW) {
106 | ArrayList images = (ArrayList) data.getSerializableExtra(ImagePicker.EXTRA_IMAGE_ITEMS);
107 | selImageList.clear();
108 | selImageList.addAll(images);
109 | adapter.setImages(selImageList);
110 | }
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ui/image/ImageCropActivity.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.ui.image;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.os.Bundle;
7 | import android.util.DisplayMetrics;
8 | import android.view.View;
9 | import android.widget.Button;
10 | import android.widget.TextView;
11 |
12 | import com.pbq.imagepicker.ImagePicker;
13 | import com.pbq.imagepicker.bean.ImageItem;
14 | import com.pbq.imagepicker.view.CropImageView;
15 |
16 | import java.io.File;
17 | import java.util.ArrayList;
18 |
19 | /**
20 | * ================================================
21 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
22 | * 版 本:1.0
23 | * 创建日期:2016/5/19
24 | * 描 述:
25 | * 修订历史:
26 | * ================================================
27 | */
28 | public class ImageCropActivity extends ImageBaseActivity implements View.OnClickListener, CropImageView.OnBitmapSaveCompleteListener {
29 |
30 | private CropImageView mCropImageView;
31 | private Bitmap mBitmap;
32 | private boolean mIsSaveRectangle;
33 | private int mOutputX;
34 | private int mOutputY;
35 | private ArrayList mImageItems;
36 | private ImagePicker imagePicker;
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | setContentView(com.pbq.imagepicker.R.layout.activity_image_crop);
42 |
43 | imagePicker = ImagePicker.getInstance();
44 |
45 | //初始化View
46 | findViewById(com.pbq.imagepicker.R.id.btn_back).setOnClickListener(this);
47 | Button btn_ok = (Button) findViewById(com.pbq.imagepicker.R.id.btn_ok);
48 | btn_ok.setText(getString(com.pbq.imagepicker.R.string.complete));
49 | btn_ok.setOnClickListener(this);
50 | TextView tv_des = (TextView) findViewById(com.pbq.imagepicker.R.id.tv_des);
51 | tv_des.setText(getString(com.pbq.imagepicker.R.string.photo_crop));
52 | mCropImageView = (CropImageView) findViewById(com.pbq.imagepicker.R.id.cv_crop_image);
53 | mCropImageView.setOnBitmapSaveCompleteListener(this);
54 |
55 | //获取需要的参数
56 | mOutputX = imagePicker.getOutPutX();
57 | mOutputY = imagePicker.getOutPutY();
58 | mIsSaveRectangle = imagePicker.isSaveRectangle();
59 | mImageItems = imagePicker.getSelectedImages();
60 | String imagePath = mImageItems.get(0).path;
61 |
62 | mCropImageView.setFocusStyle(imagePicker.getStyle());
63 | mCropImageView.setFocusWidth(imagePicker.getFocusWidth());
64 | mCropImageView.setFocusHeight(imagePicker.getFocusHeight());
65 |
66 | //缩放图片
67 | BitmapFactory.Options options = new BitmapFactory.Options();
68 | options.inJustDecodeBounds = true;
69 | BitmapFactory.decodeFile(imagePath, options);
70 | DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
71 | options.inSampleSize = calculateInSampleSize(options, displayMetrics.widthPixels, displayMetrics.heightPixels);
72 | options.inJustDecodeBounds = false;
73 | mBitmap = BitmapFactory.decodeFile(imagePath, options);
74 | mCropImageView.setImageBitmap(mBitmap);
75 |
76 | // mCropImageView.setImageURI(Uri.fromFile(new File(imagePath)));
77 | }
78 |
79 | public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
80 | int width = options.outWidth;
81 | int height = options.outHeight;
82 | int inSampleSize = 1;
83 | if (height > reqHeight || width > reqWidth) {
84 | if (width > height) {
85 | inSampleSize = width / reqWidth;
86 | } else {
87 | inSampleSize = height / reqHeight;
88 | }
89 | }
90 | return inSampleSize;
91 | }
92 |
93 | @Override
94 | public void onClick(View v) {
95 | int id = v.getId();
96 | if (id == com.pbq.imagepicker.R.id.btn_back) {
97 | setResult(RESULT_CANCELED);
98 | finish();
99 | } else if (id == com.pbq.imagepicker.R.id.btn_ok) {
100 | mCropImageView.saveBitmapToFile(imagePicker.getCropCacheFolder(this), mOutputX, mOutputY, mIsSaveRectangle);
101 | }
102 | }
103 |
104 | @Override
105 | public void onBitmapSaveSuccess(File file) {
106 | // Toast.makeText(ImageCropActivity.this, "裁剪成功:" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
107 |
108 | //裁剪后替换掉返回数据的内容,但是不要改变全局中的选中数据
109 | mImageItems.remove(0);
110 | ImageItem imageItem = new ImageItem();
111 | imageItem.path = file.getAbsolutePath();
112 | mImageItems.add(imageItem);
113 |
114 | Intent intent = new Intent();
115 | intent.putExtra(ImagePicker.EXTRA_RESULT_ITEMS, mImageItems);
116 | setResult(ImagePicker.RESULT_IMAGE_ITEMS, intent); //单选不需要裁剪,返回数据
117 | finish();
118 | }
119 |
120 | @Override
121 | public void onBitmapSaveError(File file) {
122 |
123 | }
124 |
125 | @Override
126 | protected void onDestroy() {
127 | super.onDestroy();
128 | if (null != mBitmap && !mBitmap.isRecycled()) {
129 | mBitmap.recycle();
130 | mBitmap = null;
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/view/FolderPopUpWindow.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.view;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorSet;
5 | import android.animation.ObjectAnimator;
6 | import android.content.Context;
7 | import android.graphics.drawable.ColorDrawable;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.view.ViewTreeObserver;
11 | import android.view.animation.AccelerateDecelerateInterpolator;
12 | import android.widget.AdapterView;
13 | import android.widget.BaseAdapter;
14 | import android.widget.LinearLayout;
15 | import android.widget.ListView;
16 | import android.widget.PopupWindow;
17 |
18 | /**
19 | * ================================================
20 | * 作 者:jeasonlzy(廖子尧)Github地址:https://github.com/jeasonlzy0216
21 | * 版 本:1.0
22 | * 创建日期:16/8/1
23 | * 描 述:
24 | * 修订历史:
25 | * ================================================
26 | */
27 | public class FolderPopUpWindow extends PopupWindow implements View.OnClickListener {
28 |
29 | private ListView listView;
30 | private OnItemClickListener onItemClickListener;
31 | private final View masker;
32 | private final View marginView;
33 | private int marginPx;
34 |
35 | public FolderPopUpWindow(Context context, BaseAdapter adapter) {
36 | super(context);
37 |
38 | final View view = View.inflate(context, com.pbq.imagepicker.R.layout.pop_folder, null);
39 | masker = view.findViewById(com.pbq.imagepicker.R.id.masker);
40 | masker.setOnClickListener(this);
41 | marginView = view.findViewById(com.pbq.imagepicker.R.id.margin);
42 | marginView.setOnClickListener(this);
43 | listView = (ListView) view.findViewById(com.pbq.imagepicker.R.id.listView);
44 | listView.setAdapter(adapter);
45 |
46 | setContentView(view);
47 | setWidth(ViewGroup.LayoutParams.MATCH_PARENT); //如果不设置,就是 AnchorView 的宽度
48 | setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
49 | setFocusable(true);
50 | setOutsideTouchable(true);
51 | setBackgroundDrawable(new ColorDrawable(0));
52 | setAnimationStyle(0);
53 | view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
54 | @Override
55 | public void onGlobalLayout() {
56 | view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
57 | int maxHeight = view.getHeight() * 5 / 8;
58 | int realHeight = listView.getHeight();
59 | ViewGroup.LayoutParams listParams = listView.getLayoutParams();
60 | listParams.height = realHeight > maxHeight ? maxHeight : realHeight;
61 | listView.setLayoutParams(listParams);
62 | LinearLayout.LayoutParams marginParams = (LinearLayout.LayoutParams) marginView.getLayoutParams();
63 | marginParams.height = marginPx;
64 | marginView.setLayoutParams(marginParams);
65 | enterAnimator();
66 | }
67 | });
68 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
69 | @Override
70 | public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
71 | if (onItemClickListener != null) onItemClickListener.onItemClick(adapterView, view, position, l);
72 | }
73 | });
74 | }
75 |
76 | private void enterAnimator() {
77 | ObjectAnimator alpha = ObjectAnimator.ofFloat(masker, "alpha", 0, 1);
78 | ObjectAnimator translationY = ObjectAnimator.ofFloat(listView, "translationY", listView.getHeight(), 0);
79 | AnimatorSet set = new AnimatorSet();
80 | set.setDuration(400);
81 | set.playTogether(alpha, translationY);
82 | set.setInterpolator(new AccelerateDecelerateInterpolator());
83 | set.start();
84 | }
85 |
86 | @Override
87 | public void dismiss() {
88 | exitAnimator();
89 | }
90 |
91 | private void exitAnimator() {
92 | ObjectAnimator alpha = ObjectAnimator.ofFloat(masker, "alpha", 1, 0);
93 | ObjectAnimator translationY = ObjectAnimator.ofFloat(listView, "translationY", 0, listView.getHeight());
94 | AnimatorSet set = new AnimatorSet();
95 | set.setDuration(300);
96 | set.playTogether(alpha, translationY);
97 | set.setInterpolator(new AccelerateDecelerateInterpolator());
98 | set.addListener(new Animator.AnimatorListener() {
99 | @Override
100 | public void onAnimationStart(Animator animation) {
101 | listView.setVisibility(View.VISIBLE);
102 | }
103 |
104 | @Override
105 | public void onAnimationEnd(Animator animation) {
106 | FolderPopUpWindow.super.dismiss();
107 | }
108 |
109 | @Override
110 | public void onAnimationCancel(Animator animation) {
111 | }
112 |
113 | @Override
114 | public void onAnimationRepeat(Animator animation) {
115 | }
116 | });
117 | set.start();
118 | }
119 |
120 | public void setOnItemClickListener(OnItemClickListener listener) {
121 | this.onItemClickListener = listener;
122 | }
123 |
124 | public void setSelection(int selection) {
125 | listView.setSelection(selection);
126 | }
127 |
128 | public void setMargin(int marginPx) {
129 | this.marginPx = marginPx;
130 | }
131 |
132 | @Override
133 | public void onClick(View v) {
134 | dismiss();
135 | }
136 |
137 | public interface OnItemClickListener {
138 | void onItemClick(AdapterView> adapterView, View view, int position, long l);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/imagepicker/src/main/res/layout/activity_video_grid.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
15 |
16 |
24 |
25 |
32 |
33 |
43 |
44 |
59 |
60 |
70 |
71 |
72 |
73 |
74 |
75 |
79 |
80 |
94 |
95 |
101 |
102 |
118 |
119 |
131 |
132 |
139 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ImageDataSource.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker;
2 |
3 | import android.database.Cursor;
4 | import android.os.Bundle;
5 | import android.provider.MediaStore;
6 | import android.support.v4.app.FragmentActivity;
7 | import android.support.v4.app.LoaderManager;
8 | import android.support.v4.content.CursorLoader;
9 | import android.support.v4.content.Loader;
10 | import com.pbq.imagepicker.bean.ImageFolder;
11 | import com.pbq.imagepicker.bean.ImageItem;
12 | import java.io.File;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | /**
17 | * ================================================
18 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
19 | * 版 本:1.0
20 | * 创建日期:2016/5/19
21 | * 描 述:加载手机图片实现类 异步加载数据 数据改变数重新更新
22 | * 修订历史:
23 | * ================================================
24 | */
25 | public class ImageDataSource implements LoaderManager.LoaderCallbacks {
26 |
27 | public static final int LOADER_ALL = 0; //加载所有图片
28 | public static final int LOADER_CATEGORY = 1; //分类加载图片
29 | private final String[] IMAGE_PROJECTION = { //查询图片需要的数据列
30 | MediaStore.Images.Media.DISPLAY_NAME, //图片的显示名称 aaa.jpg
31 | MediaStore.Images.Media.DATA, //图片的真实路径 /storage/emulated/0/pp/downloader/wallpaper/aaa.jpg
32 | MediaStore.Images.Media.SIZE, //图片的大小,long型 132492
33 | MediaStore.Images.Media.WIDTH, //图片的宽度,int型 1920
34 | MediaStore.Images.Media.HEIGHT, //图片的高度,int型 1080
35 | MediaStore.Images.Media.MIME_TYPE, //图片的类型 image/jpeg
36 | MediaStore.Images.Media.DATE_ADDED}; //图片被添加的时间,long型 1450518608
37 |
38 | private FragmentActivity activity;
39 | private OnImagesLoadedListener loadedListener; //图片加载完成的回调接口
40 | private ArrayList imageFolders = new ArrayList<>(); //所有的图片文件夹
41 |
42 | /**
43 | * @param activity 用于初始化LoaderManager,需要兼容到2.3
44 | * @param path 指定扫描的文件夹目录,可以为 null,表示扫描所有图片
45 | * @param loadedListener 图片加载完成的监听
46 | */
47 | public ImageDataSource(FragmentActivity activity, String path, OnImagesLoadedListener loadedListener) {
48 | this.activity = activity;
49 | this.loadedListener = loadedListener;
50 |
51 | //得到LoaderManager对象
52 | LoaderManager loaderManager = activity.getSupportLoaderManager();
53 | //初始化loader
54 | if (path == null) {
55 | loaderManager.initLoader(LOADER_ALL, null, this);//加载所有的图片
56 | } else {
57 | //加载指定目录的图片
58 | Bundle bundle = new Bundle();
59 | bundle.putString("path", path);
60 | loaderManager.initLoader(LOADER_CATEGORY, bundle, this);
61 | }
62 | }
63 |
64 | /**
65 | * 指定ID不存在 触发该方法返回一个新的loader对象
66 | * @param id
67 | * @param args
68 | * @return
69 | */
70 | @Override
71 | public Loader onCreateLoader(int id, Bundle args) {
72 | CursorLoader cursorLoader = null;
73 | //扫描所有图片
74 | //查询ContentResolver并返回一个Cursor对象
75 | if (id == LOADER_ALL)
76 | cursorLoader = new CursorLoader(activity, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, null, null, IMAGE_PROJECTION[6] + " DESC");
77 | //扫描某个图片文件夹
78 | if (id == LOADER_CATEGORY)
79 | cursorLoader = new CursorLoader(activity, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, IMAGE_PROJECTION[1] + " like '%" + args.getString("path") + "%'", null, IMAGE_PROJECTION[6] + " DESC");
80 |
81 | return cursorLoader;
82 | }
83 |
84 | /**
85 | * 完成对UI界面的更新
86 | * @param loader
87 | * @param data
88 | */
89 | @Override
90 | public void onLoadFinished(Loader loader, Cursor data) {
91 | imageFolders.clear();
92 | if (data != null) {
93 | ArrayList allImages = new ArrayList<>(); //所有图片的集合,不分文件夹
94 | while (data.moveToNext()) {
95 | //查询数据
96 | String imageName = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
97 | String imagePath = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
98 | long imageSize = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
99 | int imageWidth = data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[3]));
100 | int imageHeight = data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[4]));
101 | String imageMimeType = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[5]));
102 | long imageAddTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[6]));
103 | //封装实体
104 | ImageItem imageItem = new ImageItem();
105 | imageItem.name = imageName;
106 | imageItem.path = imagePath;
107 | imageItem.size = imageSize;
108 | imageItem.width = imageWidth;
109 | imageItem.height = imageHeight;
110 | imageItem.mimeType = imageMimeType;
111 | imageItem.addTime = imageAddTime;
112 | allImages.add(imageItem);
113 | //根据父路径分类存放图片
114 | //根据图片的路径获取到图片所在文件夹的路径和名称
115 | File imageFile = new File(imagePath);
116 | File imageParentFile = imageFile.getParentFile();
117 | ImageFolder imageFolder = new ImageFolder();
118 | imageFolder.name = imageParentFile.getName();
119 | imageFolder.path = imageParentFile.getAbsolutePath();
120 | //判断这个文件夹是否已经存在 如果存在直接添加图片进去 否则将文件夹添加到文件夹的集合中
121 | if (!imageFolders.contains(imageFolder)) {
122 | ArrayList images = new ArrayList<>();
123 | images.add(imageItem);
124 | //缩略图
125 | imageFolder.cover = imageItem;
126 | imageFolder.images = images;
127 | imageFolders.add(imageFolder);
128 | } else {
129 | imageFolders.get(imageFolders.indexOf(imageFolder)).images.add(imageItem);
130 | }
131 | }
132 | //防止没有图片报异常
133 | if (data.getCount() > 0) {
134 | //构造所有图片的集合
135 | ImageFolder allImagesFolder = new ImageFolder();
136 | allImagesFolder.name = activity.getResources().getString(R.string.all_images);
137 | allImagesFolder.path = "/";
138 | //把第一张设置缩略图
139 | allImagesFolder.cover = allImages.get(0);
140 | allImagesFolder.images = allImages;
141 | imageFolders.add(0, allImagesFolder); //确保第一条是所有图片
142 | }
143 | }
144 |
145 | //回调接口,通知图片数据准备完成
146 | ImagePicker.getInstance().setImageFolders(imageFolders);
147 | loadedListener.onImagesLoaded(imageFolders);
148 | }
149 |
150 | @Override
151 | public void onLoaderReset(Loader loader) {
152 | System.out.println("--------");
153 | }
154 |
155 | /** 所有图片加载完成的回调接口 */
156 | public interface OnImagesLoadedListener {
157 | void onImagesLoaded(List imageFolders);
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/VideoDataSource.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker;
2 |
3 | import android.database.Cursor;
4 | import android.os.Bundle;
5 | import android.provider.MediaStore;
6 | import android.support.v4.app.FragmentActivity;
7 | import android.support.v4.app.LoaderManager;
8 | import android.support.v4.content.CursorLoader;
9 | import android.support.v4.content.Loader;
10 | import com.pbq.imagepicker.bean.VideoFolder;
11 | import com.pbq.imagepicker.bean.VideoItem;
12 |
13 | import java.io.File;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | /**
18 | * Created by pengbangqin on 2016/12/27.
19 | * 加载手机视频实现类 异步加载数据 数据改变数重新更新
20 | */
21 |
22 | public class VideoDataSource implements LoaderManager.LoaderCallbacks {
23 |
24 | public static final int LOADER_ALL = 0; //加载所有视频
25 | public static final int LOADER_CATEGORY = 1; //分类加载视频
26 | private final String[] IMAGE_PROJECTION = { //查询视频需要的数据列
27 | MediaStore.Video.Media.DISPLAY_NAME, //视频的显示名称 aaa.jpg
28 | MediaStore.Video.Media.DATA, //视频的真实路径 /storage/emulated/0/pp/downloader/wallpaper/aaa.jpg
29 | MediaStore.Video.Media.SIZE, //视频的大小,long型 132492
30 | MediaStore.Video.Media.WIDTH, //视频的宽度,int型 1920
31 | MediaStore.Video.Media.HEIGHT, //视频的高度,int型 1080
32 | MediaStore.Video.Media.MIME_TYPE, //视频的类型 image/jpeg
33 | MediaStore.Video.Media.DATE_ADDED //视频被添加的时间,long型 1450518608
34 | ,MediaStore.Video.Media.DURATION}; //视频的时长
35 |
36 | private FragmentActivity activity;
37 | private OnVideosLoadedListener loadedListener; //视频加载完成的回调接口
38 | private ArrayList videoFolders = new ArrayList<>(); //所有的视频文件夹
39 |
40 | /**
41 | * @param activity 用于初始化LoaderManager,需要兼容到2.3
42 | * @param path 指定扫描的文件夹目录,可以为 null,表示扫描所有视频
43 | * @param loadedListener 视频加载完成的监听
44 | */
45 | public VideoDataSource(FragmentActivity activity, String path, OnVideosLoadedListener loadedListener) {
46 | this.activity = activity;
47 | this.loadedListener = loadedListener;
48 |
49 | //得到LoaderManager对象
50 | LoaderManager loaderManager = activity.getSupportLoaderManager();
51 | //初始化loader
52 | if (path == null) {
53 | loaderManager.initLoader(LOADER_ALL, null, this);//加载所有的视频
54 | } else {
55 | //加载指定目录的视频
56 | Bundle bundle = new Bundle();
57 | bundle.putString("path", path);
58 | loaderManager.initLoader(LOADER_CATEGORY, bundle, this);
59 | }
60 | }
61 |
62 | /**
63 | * 指定ID不存在 触发该方法返回一个新的loader对象
64 | * @param id
65 | * @param args
66 | * @return
67 | */
68 | @Override
69 | public Loader onCreateLoader(int id, Bundle args) {
70 | CursorLoader cursorLoader = null;
71 | //扫描所有视频
72 | //查询ContentResolver并返回一个Cursor对象
73 | if (id == LOADER_ALL)
74 | cursorLoader = new CursorLoader(activity, MediaStore.Video.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, null, null, IMAGE_PROJECTION[7] + " DESC");
75 | //扫描某个视频文件夹
76 | if (id == LOADER_CATEGORY)
77 | cursorLoader = new CursorLoader(activity, MediaStore.Video.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, IMAGE_PROJECTION[1] + " like '%" + args.getString("path") + "%'", null, IMAGE_PROJECTION[7] + " DESC");
78 |
79 | return cursorLoader;
80 | }
81 |
82 | /**
83 | * 完成对UI界面的更新
84 | * @param loader
85 | * @param data
86 | */
87 | @Override
88 | public void onLoadFinished(Loader loader, Cursor data) {
89 | videoFolders.clear();
90 | if (data != null) {
91 | ArrayList allVideos = new ArrayList<>(); //所有视频的集合,不分文件夹
92 | while (data.moveToNext()) {
93 | //查询数据
94 | String videoName = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
95 | String videoPath = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
96 | long videoSize = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
97 | int videoWidth = data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[3]));
98 | int videoHeight = data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[4]));
99 | String videoMimeType = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[5]));
100 | long videoAddTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[6]));
101 | long videoTimeLong = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[7]));
102 | //封装实体
103 | VideoItem videoItem = new VideoItem();
104 | videoItem.name = videoName;
105 | videoItem.path = videoPath;
106 | videoItem.size = videoSize;
107 | videoItem.width = videoWidth;
108 | videoItem.height = videoHeight;
109 | videoItem.mimeType = videoMimeType;
110 | videoItem.addTime = videoAddTime;
111 | videoItem.timeLong = videoTimeLong;
112 | allVideos.add(videoItem);
113 | //根据父路径分类存放视频
114 | //根据视频的路径获取到视频所在文件夹的路径和名称
115 | File videoFile = new File(videoPath);
116 | File videoParentFile = videoFile.getParentFile();
117 | VideoFolder videoFolder = new VideoFolder();
118 | videoFolder.name = videoParentFile.getName();
119 | videoFolder.path = videoParentFile.getAbsolutePath();
120 | //判断这个文件夹是否已经存在 如果存在直接添加视频进去 否则将文件夹添加到文件夹的集合中
121 | if (!videoFolders.contains(videoFolder)) {
122 | ArrayList images = new ArrayList<>();
123 | images.add(videoItem);
124 | //缩略图
125 | videoFolder.cover = videoItem;
126 | videoFolder.videos = images;
127 | videoFolders.add(videoFolder);
128 | } else {
129 | videoFolders.get(videoFolders.indexOf(videoFolder)).videos.add(videoItem);
130 | }
131 | }
132 | //防止没有视频报异常
133 | if (data.getCount() > 0) {
134 | //构造所有视频的集合
135 | VideoFolder allVideosFolder = new VideoFolder();
136 | allVideosFolder.name = activity.getResources().getString(R.string.all_images);
137 | allVideosFolder.path = "/";
138 | //把第一张设置缩略图
139 | allVideosFolder.cover = allVideos.get(0);
140 | allVideosFolder.videos = allVideos;
141 | videoFolders.add(0, allVideosFolder); //确保第一条是所有图片
142 | }
143 | }
144 |
145 | //回调接口,通知视频数据准备完成
146 | VideoPicker.getInstance().setVideoFolders(videoFolders);
147 | loadedListener.onVideosLoaded(videoFolders);
148 | }
149 |
150 | @Override
151 | public void onLoaderReset(Loader loader) {
152 | System.out.println("--------");
153 | }
154 |
155 | /** 所有视频加载完成的回调接口 */
156 | public interface OnVideosLoadedListener {
157 | void onVideosLoaded(List videoFolders);
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/adapter/image/ImageGridAdapter.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.adapter.image;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.support.v4.app.ActivityCompat;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.AbsListView;
10 | import android.widget.BaseAdapter;
11 | import android.widget.ImageView;
12 | import android.widget.Toast;
13 |
14 | import com.bumptech.glide.Glide;
15 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
16 | import com.pbq.imagepicker.ImagePicker;
17 | import com.pbq.imagepicker.R;
18 | import com.pbq.imagepicker.Utils;
19 | import com.pbq.imagepicker.bean.ImageItem;
20 | import com.pbq.imagepicker.ui.image.ImageBaseActivity;
21 | import com.pbq.imagepicker.ui.image.ImageGridActivity;
22 | import com.pbq.imagepicker.view.SuperCheckBox;
23 |
24 | import java.util.ArrayList;
25 |
26 | /**
27 | * ================================================
28 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
29 | * 版 本:1.0
30 | * 创建日期:2016/5/19
31 | * 描 述:
32 | * 修订历史:
33 | * ================================================
34 | */
35 | public class ImageGridAdapter extends BaseAdapter {
36 |
37 | private static final int ITEM_TYPE_CAMERA = 0; //第一个条目是相机
38 | private static final int ITEM_TYPE_NORMAL = 1; //第一个条目不是相机
39 |
40 | private ImagePicker imagePicker;
41 | private Activity mActivity;
42 | private ArrayList images; //当前需要显示的所有的图片数据
43 | private ArrayList mSelectedImages; //全局保存的已经选中的图片数据
44 | private boolean isShowCamera; //是否显示拍照按钮
45 | private int mImageSize; //每个条目的大小
46 | private OnImageItemClickListener listener; //图片被点击的监听
47 |
48 | public ImageGridAdapter(Activity activity, ArrayList images) {
49 | this.mActivity = activity;
50 | if (images == null || images.size() == 0) this.images = new ArrayList<>();
51 | else this.images = images;
52 |
53 | mImageSize = Utils.getImageItemWidth(mActivity);
54 | imagePicker = ImagePicker.getInstance();
55 | isShowCamera = imagePicker.isShowCamera();
56 | mSelectedImages = imagePicker.getSelectedImages();
57 | }
58 |
59 | public void refreshData(ArrayList images) {
60 | if (images == null || images.size() == 0) this.images = new ArrayList<>();
61 | else this.images = images;
62 | notifyDataSetChanged();
63 | }
64 |
65 | @Override
66 | public int getViewTypeCount() {
67 | return 2;
68 | }
69 |
70 | @Override
71 | public int getItemViewType(int position) {
72 | if (isShowCamera) return position == 0 ? ITEM_TYPE_CAMERA : ITEM_TYPE_NORMAL;
73 | return ITEM_TYPE_NORMAL;
74 | }
75 |
76 | @Override
77 | public int getCount() {
78 | return isShowCamera ? images.size() + 1 : images.size();
79 | }
80 |
81 | @Override
82 | public ImageItem getItem(int position) {
83 | if (isShowCamera) {
84 | if (position == 0) return null;
85 | return images.get(position - 1);
86 | } else {
87 | return images.get(position);
88 | }
89 | }
90 |
91 | @Override
92 | public long getItemId(int position) {
93 | return position;
94 | }
95 |
96 | @Override
97 | public View getView(final int position, View convertView, ViewGroup parent) {
98 | int itemViewType = getItemViewType(position);
99 | if (itemViewType == ITEM_TYPE_CAMERA) {
100 | convertView = LayoutInflater.from(mActivity).inflate(com.pbq.imagepicker.R.layout.adapter_camera_item, parent, false);
101 | convertView.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mImageSize)); //让图片是个正方形
102 | convertView.setTag(null);
103 | convertView.setOnClickListener(new View.OnClickListener() {
104 | @Override
105 | public void onClick(View v) {
106 | if (!((ImageBaseActivity) mActivity).checkPermission(Manifest.permission.CAMERA)) {
107 | ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.CAMERA}, ImageGridActivity.REQUEST_PERMISSION_CAMERA);
108 | } else {
109 | imagePicker.takePicture(mActivity, ImagePicker.REQUEST_IMAGE_TAKE);
110 | }
111 | }
112 | });
113 | } else {
114 | final ViewHolder holder;
115 | if (convertView == null) {
116 | convertView = LayoutInflater.from(mActivity).inflate(com.pbq.imagepicker.R.layout.adapter_image_item, parent, false);
117 | convertView.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mImageSize)); //让图片是个正方形
118 | holder = new ViewHolder(convertView);
119 | convertView.setTag(holder);
120 | } else {
121 | holder = (ViewHolder) convertView.getTag();
122 | }
123 | final ImageItem imageItem = getItem(position);
124 |
125 | holder.ivThumb.setOnClickListener(new View.OnClickListener() {
126 | @Override
127 | public void onClick(View v) {
128 | if (listener != null) listener.onImageItemClick(holder.rootView, imageItem, position);
129 | }
130 | });
131 | holder.cbCheck.setOnClickListener(new View.OnClickListener() {
132 | @Override
133 | public void onClick(View v) {
134 | int selectLimit = imagePicker.getSelectLimit();
135 | if (holder.cbCheck.isChecked() && mSelectedImages.size() >= selectLimit) {
136 | Toast.makeText(mActivity.getApplicationContext(), mActivity.getString(com.pbq.imagepicker.R.string.select_limit, selectLimit), Toast.LENGTH_SHORT).show();
137 | holder.cbCheck.setChecked(false);
138 | holder.mask.setVisibility(View.GONE);
139 | } else {
140 | imagePicker.addSelectedImageItem(position, imageItem, holder.cbCheck.isChecked());
141 | holder.mask.setVisibility(View.VISIBLE);
142 | }
143 | }
144 | });
145 | //根据是否多选,显示或隐藏checkbox
146 | if (imagePicker.isMultiMode()) {
147 | holder.cbCheck.setVisibility(View.VISIBLE);
148 | boolean checked = mSelectedImages.contains(imageItem);
149 | if (checked) {
150 | holder.mask.setVisibility(View.VISIBLE);
151 | holder.cbCheck.setChecked(true);
152 | } else {
153 | holder.mask.setVisibility(View.GONE);
154 | holder.cbCheck.setChecked(false);
155 | }
156 | } else {
157 | holder.cbCheck.setVisibility(View.GONE);
158 | }
159 | imagePicker.getImageLoader().displayImage(mActivity, imageItem.path, holder.ivThumb, mImageSize, mImageSize); //显示图片
160 | }
161 | return convertView;
162 | }
163 |
164 | private class ViewHolder {
165 | public View rootView;
166 | public ImageView ivThumb;
167 | public View mask;
168 | public SuperCheckBox cbCheck;
169 |
170 | public ViewHolder(View view) {
171 | rootView = view;
172 | ivThumb = (ImageView) view.findViewById(com.pbq.imagepicker.R.id.iv_thumb);
173 | mask = view.findViewById(com.pbq.imagepicker.R.id.mask);
174 | cbCheck = (SuperCheckBox) view.findViewById(com.pbq.imagepicker.R.id.cb_check);
175 | }
176 | }
177 |
178 | public void setOnImageItemClickListener(OnImageItemClickListener listener) {
179 | this.listener = listener;
180 | }
181 |
182 | public interface OnImageItemClickListener {
183 | void onImageItemClick(View view, ImageItem imageItem, int position);
184 | }
185 | }
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ui/video/VideoPreviewActivity.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.ui.video;
2 |
3 | import android.content.Intent;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import android.support.v4.view.ViewPager;
7 | import android.text.format.Formatter;
8 | import android.view.View;
9 | import android.view.animation.AnimationUtils;
10 | import android.widget.Button;
11 | import android.widget.CompoundButton;
12 | import android.widget.Toast;
13 |
14 | import com.pbq.imagepicker.R;
15 | import com.pbq.imagepicker.VideoPicker;
16 | import com.pbq.imagepicker.bean.VideoItem;
17 | import com.pbq.imagepicker.view.SuperCheckBox;
18 |
19 | /**
20 | * 视频预览界面
21 | */
22 | public class VideoPreviewActivity extends VideoPreviewBaseActivity implements VideoPicker.OnVideoSelectedListener, View.OnClickListener, CompoundButton.OnCheckedChangeListener {
23 | /**
24 | * 是否选中了原图的常量
25 | */
26 | public static final String ISORIGIN = "isOrigin";
27 |
28 | private boolean isOrigin; //是否选中原图
29 | private SuperCheckBox mCbCheck; //是否选中当前视频的CheckBox
30 | private SuperCheckBox mCbOrigin; //原图
31 | private Button mBtnOk; //确认视频的选择
32 | private View bottomBar;
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 |
38 | isOrigin = getIntent().getBooleanExtra(VideoPreviewActivity.ISORIGIN, false);
39 | videoPicker.addOnVideoSelectedListener(this);
40 |
41 | mBtnOk = (Button) topBar.findViewById(R.id.btn_ok);
42 | mBtnOk.setVisibility(View.VISIBLE);
43 | mBtnOk.setOnClickListener(this);
44 |
45 | bottomBar = findViewById(R.id.bottom_bar);
46 | bottomBar.setVisibility(View.VISIBLE);
47 |
48 | mCbCheck = (SuperCheckBox) findViewById(R.id.cb_check);
49 | mCbOrigin = (SuperCheckBox) findViewById(R.id.cb_origin);
50 | mCbOrigin.setText(getString(R.string.origin));
51 | mCbOrigin.setOnCheckedChangeListener(this);
52 | mCbOrigin.setChecked(isOrigin);
53 |
54 | //初始化当前页面的状态
55 | onVideoSelected(0, null, false);
56 | VideoItem item = mVideoItems.get(mCurrentPosition);
57 | boolean isSelected = videoPicker.isSelect(item);
58 | mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mVideoItems.size()));
59 | mCbCheck.setChecked(isSelected);
60 | //滑动ViewPager的时候,根据外界的数据改变当前的选中状态和当前的视频的位置描述文本
61 | mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
62 | @Override
63 | public void onPageSelected(int position) {
64 | mCurrentPosition = position;
65 | VideoItem item = mVideoItems.get(mCurrentPosition);
66 | boolean isSelected = videoPicker.isSelect(item);
67 | mCbCheck.setChecked(isSelected);
68 | mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mVideoItems.size()));
69 | }
70 | });
71 | //当点击当前选中按钮的时候,需要根据当前的选中状态添加和移除视频
72 | mCbCheck.setOnClickListener(new View.OnClickListener() {
73 | @Override
74 | public void onClick(View v) {
75 | VideoItem videoItem = mVideoItems.get(mCurrentPosition);
76 | int selectLimit = videoPicker.getSelectLimit();
77 | if (mCbCheck.isChecked() && selectedVideos.size() >= selectLimit) {
78 | Toast.makeText(VideoPreviewActivity.this, VideoPreviewActivity.this.getString(R.string.select_limit, selectLimit), Toast.LENGTH_SHORT).show();
79 | mCbCheck.setChecked(false);
80 | } else {
81 | videoPicker.addSelectedVideoItem(mCurrentPosition, videoItem, mCbCheck.isChecked());
82 | }
83 | }
84 | });
85 | }
86 |
87 | /**
88 | * 视频添加成功后,修改当前视频的选中数量
89 | * 当调用 addSelectedVideoItem 或 deleteSelectedVideoItem 都会触发当前回调
90 | */
91 | @Override
92 | public void onVideoSelected(int position, VideoItem item, boolean isAdd) {
93 | if (videoPicker.getSelectVideoCount() > 0) {
94 | mBtnOk.setText(getString(R.string.select_complete, videoPicker.getSelectVideoCount(), videoPicker.getSelectLimit()));
95 | mBtnOk.setEnabled(true);
96 | } else {
97 | mBtnOk.setText(getString(R.string.complete));
98 | mBtnOk.setEnabled(false);
99 | }
100 | //选中原图时获取视频的大小
101 | if (mCbOrigin.isChecked()) {
102 | long size = 0;
103 | for (VideoItem videoItem : selectedVideos)
104 | size += videoItem.size;
105 | String fileSize = Formatter.formatFileSize(this, size);
106 | mCbOrigin.setText(getString(R.string.origin_size, fileSize));
107 | }
108 | }
109 |
110 | @Override
111 | public void onClick(View v) {
112 | int id = v.getId();
113 | if (id == R.id.btn_ok) {
114 | Intent intent = new Intent();
115 | intent.putExtra(VideoPicker.EXTRA_RESULT_VIDEO_ITEMS, videoPicker.getSelectedVideos());
116 | setResult(VideoPicker.RESULT_VIDEO_ITEMS, intent);
117 | finish();
118 | } else if (id == R.id.btn_back) {
119 | Intent intent = new Intent();
120 | //携带参数书否选中原图
121 | intent.putExtra(VideoPreviewActivity.ISORIGIN, isOrigin);
122 | setResult(VideoPicker.RESULT_VIDEO_BACK, intent);
123 | finish();
124 | }
125 | }
126 |
127 | @Override
128 | public void onBackPressed() {
129 | Intent intent = new Intent();
130 | intent.putExtra(VideoPreviewActivity.ISORIGIN, isOrigin);
131 | setResult(VideoPicker.RESULT_VIDEO_BACK, intent);
132 | finish();
133 | super.onBackPressed();
134 | }
135 |
136 | @Override
137 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
138 | int id = buttonView.getId();
139 | if (id == R.id.cb_origin) {
140 | if (isChecked) {
141 | long size = 0;
142 | for (VideoItem item : selectedVideos)
143 | size += item.size;
144 | String fileSize = Formatter.formatFileSize(this, size);
145 | isOrigin = true;
146 | mCbOrigin.setText(getString(R.string.origin_size, fileSize));
147 | } else {
148 | isOrigin = false;
149 | mCbOrigin.setText(getString(R.string.origin));
150 | }
151 | }
152 | }
153 |
154 | @Override
155 | protected void onDestroy() {
156 | videoPicker.removeOnVideoSelectedListener(this);
157 | super.onDestroy();
158 | }
159 |
160 | /** 单击时,隐藏头和尾 */
161 | @Override
162 | public void onVideoSingleTap() {
163 | if (topBar.getVisibility() == View.VISIBLE) {
164 | topBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.top_out));
165 | bottomBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_out));
166 | topBar.setVisibility(View.GONE);
167 | bottomBar.setVisibility(View.GONE);
168 | tintManager.setStatusBarTintResource(R.color.transparent);//通知栏所需颜色
169 | //给最外层布局加上这个属性表示,Activity全屏显示,且状态栏被隐藏覆盖掉。
170 | if (Build.VERSION.SDK_INT >= 16) content.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
171 | } else {
172 | topBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.top_in));
173 | bottomBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in));
174 | topBar.setVisibility(View.VISIBLE);
175 | bottomBar.setVisibility(View.VISIBLE);
176 | tintManager.setStatusBarTintResource(R.color.status_bar);//通知栏所需颜色
177 | //Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住
178 | if (Build.VERSION.SDK_INT >= 16) content.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
179 | }
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ui/image/ImagePreviewActivity.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.ui.image;
2 |
3 | import android.content.Intent;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import android.support.v4.view.ViewPager;
7 | import android.text.format.Formatter;
8 | import android.view.View;
9 | import android.view.animation.AnimationUtils;
10 | import android.widget.Button;
11 | import android.widget.CompoundButton;
12 | import android.widget.Toast;
13 |
14 | import com.pbq.imagepicker.ImagePicker;
15 | import com.pbq.imagepicker.R;
16 | import com.pbq.imagepicker.bean.ImageItem;
17 | import com.pbq.imagepicker.view.SuperCheckBox;
18 |
19 | /**
20 | * ================================================
21 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
22 | * 版 本:1.0
23 | * 创建日期:2016/5/19
24 | * 描 述:
25 | * 修订历史:
26 | * ================================================
27 | */
28 | public class ImagePreviewActivity extends ImagePreviewBaseActivity implements ImagePicker.OnImageSelectedListener, View.OnClickListener, CompoundButton.OnCheckedChangeListener {
29 |
30 | public static final String ISORIGIN = "isOrigin";
31 |
32 | private boolean isOrigin; //是否选中原图
33 | private SuperCheckBox mCbCheck; //是否选中当前图片的CheckBox
34 | private SuperCheckBox mCbOrigin; //原图
35 | private Button mBtnOk; //确认图片的选择
36 | private View bottomBar;
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 |
42 | isOrigin = getIntent().getBooleanExtra(ImagePreviewActivity.ISORIGIN, false);
43 | imagePicker.addOnImageSelectedListener(this);
44 |
45 | mBtnOk = (Button) topBar.findViewById(R.id.btn_ok);
46 | mBtnOk.setVisibility(View.VISIBLE);
47 | mBtnOk.setOnClickListener(this);
48 |
49 | bottomBar = findViewById(R.id.bottom_bar);
50 | bottomBar.setVisibility(View.VISIBLE);
51 |
52 | mCbCheck = (SuperCheckBox) findViewById(R.id.cb_check);
53 | mCbOrigin = (SuperCheckBox) findViewById(R.id.cb_origin);
54 | mCbOrigin.setText(getString(R.string.origin));
55 | mCbOrigin.setOnCheckedChangeListener(this);
56 | mCbOrigin.setChecked(isOrigin);
57 |
58 | //初始化当前页面的状态
59 | onImageSelected(0, null, false);
60 | ImageItem item = mImageItems.get(mCurrentPosition);
61 | boolean isSelected = imagePicker.isSelect(item);
62 | mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mImageItems.size()));
63 | mCbCheck.setChecked(isSelected);
64 | //滑动ViewPager的时候,根据外界的数据改变当前的选中状态和当前的图片的位置描述文本
65 | mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
66 | @Override
67 | public void onPageSelected(int position) {
68 | mCurrentPosition = position;
69 | ImageItem item = mImageItems.get(mCurrentPosition);
70 | boolean isSelected = imagePicker.isSelect(item);
71 | mCbCheck.setChecked(isSelected);
72 | mTitleCount.setText(getString(R.string.preview_image_count, mCurrentPosition + 1, mImageItems.size()));
73 | }
74 | });
75 | //当点击当前选中按钮的时候,需要根据当前的选中状态添加和移除图片
76 | mCbCheck.setOnClickListener(new View.OnClickListener() {
77 | @Override
78 | public void onClick(View v) {
79 | ImageItem imageItem = mImageItems.get(mCurrentPosition);
80 | int selectLimit = imagePicker.getSelectLimit();
81 | if (mCbCheck.isChecked() && selectedImages.size() >= selectLimit) {
82 | Toast.makeText(ImagePreviewActivity.this, ImagePreviewActivity.this.getString(R.string.select_limit, selectLimit), Toast.LENGTH_SHORT).show();
83 | mCbCheck.setChecked(false);
84 | } else {
85 | imagePicker.addSelectedImageItem(mCurrentPosition, imageItem, mCbCheck.isChecked());
86 | }
87 | }
88 | });
89 | }
90 |
91 | /**
92 | * 图片添加成功后,修改当前图片的选中数量
93 | * 当调用 addSelectedImageItem 或 deleteSelectedImageItem 都会触发当前回调
94 | */
95 | @Override
96 | public void onImageSelected(int position, ImageItem item, boolean isAdd) {
97 | if (imagePicker.getSelectImageCount() > 0) {
98 | mBtnOk.setText(getString(R.string.select_complete, imagePicker.getSelectImageCount(), imagePicker.getSelectLimit()));
99 | mBtnOk.setEnabled(true);
100 | } else {
101 | mBtnOk.setText(getString(R.string.complete));
102 | mBtnOk.setEnabled(false);
103 | }
104 |
105 | if (mCbOrigin.isChecked()) {
106 | long size = 0;
107 | for (ImageItem imageItem : selectedImages)
108 | size += imageItem.size;
109 | String fileSize = Formatter.formatFileSize(this, size);
110 | mCbOrigin.setText(getString(R.string.origin_size, fileSize));
111 | }
112 | }
113 |
114 | @Override
115 | public void onClick(View v) {
116 | int id = v.getId();
117 | if (id == R.id.btn_ok) {
118 | Intent intent = new Intent();
119 | intent.putExtra(ImagePicker.EXTRA_RESULT_ITEMS, imagePicker.getSelectedImages());
120 | setResult(ImagePicker.RESULT_IMAGE_ITEMS, intent);
121 | finish();
122 | } else if (id == R.id.btn_back) {
123 | Intent intent = new Intent();
124 | intent.putExtra(ImagePreviewActivity.ISORIGIN, isOrigin);
125 | setResult(ImagePicker.RESULT_IMAGE_BACK, intent);
126 | finish();
127 | }
128 | }
129 |
130 | @Override
131 | public void onBackPressed() {
132 | Intent intent = new Intent();
133 | intent.putExtra(ImagePreviewActivity.ISORIGIN, isOrigin);
134 | setResult(ImagePicker.RESULT_IMAGE_BACK, intent);
135 | finish();
136 | super.onBackPressed();
137 | }
138 |
139 | @Override
140 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
141 | int id = buttonView.getId();
142 | if (id == R.id.cb_origin) {
143 | if (isChecked) {
144 | long size = 0;
145 | for (ImageItem item : selectedImages)
146 | size += item.size;
147 | String fileSize = Formatter.formatFileSize(this, size);
148 | isOrigin = true;
149 | mCbOrigin.setText(getString(R.string.origin_size, fileSize));
150 | } else {
151 | isOrigin = false;
152 | mCbOrigin.setText(getString(R.string.origin));
153 | }
154 | }
155 | }
156 |
157 | @Override
158 | protected void onDestroy() {
159 | imagePicker.removeOnImageSelectedListener(this);
160 | super.onDestroy();
161 | }
162 |
163 | /** 单击时,隐藏头和尾 */
164 | @Override
165 | public void onImageSingleTap() {
166 | if (topBar.getVisibility() == View.VISIBLE) {
167 | topBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.top_out));
168 | bottomBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_out));
169 | topBar.setVisibility(View.GONE);
170 | bottomBar.setVisibility(View.GONE);
171 | tintManager.setStatusBarTintResource(R.color.transparent);//通知栏所需颜色
172 | //给最外层布局加上这个属性表示,Activity全屏显示,且状态栏被隐藏覆盖掉。
173 | if (Build.VERSION.SDK_INT >= 16) content.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
174 | } else {
175 | topBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.top_in));
176 | bottomBar.setAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in));
177 | topBar.setVisibility(View.VISIBLE);
178 | bottomBar.setVisibility(View.VISIBLE);
179 | tintManager.setStatusBarTintResource(R.color.status_bar);//通知栏所需颜色
180 | //Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住
181 | if (Build.VERSION.SDK_INT >= 16) content.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
182 | }
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/adapter/video/VideoGridAdapter.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker.adapter.video;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.support.v4.app.ActivityCompat;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.AbsListView;
10 | import android.widget.BaseAdapter;
11 | import android.widget.ImageView;
12 | import android.widget.TextView;
13 | import android.widget.Toast;
14 |
15 | import com.bumptech.glide.Glide;
16 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
17 | import com.pbq.imagepicker.R;
18 | import com.pbq.imagepicker.Utils;
19 | import com.pbq.imagepicker.VideoPicker;
20 | import com.pbq.imagepicker.bean.VideoItem;
21 | import com.pbq.imagepicker.ui.image.ImageBaseActivity;
22 | import com.pbq.imagepicker.ui.video.VideoGridActivity;
23 | import com.pbq.imagepicker.view.SuperCheckBox;
24 |
25 | import java.util.ArrayList;
26 |
27 | /**
28 | * 加载视频的GridView
29 | */
30 | public class VideoGridAdapter extends BaseAdapter {
31 |
32 | private static final int ITEM_TYPE_CAMERA = 0; //第一个条目是相机
33 | private static final int ITEM_TYPE_NORMAL = 1; //第一个条目不是相机
34 |
35 | private VideoPicker videoPicker;
36 | private Activity mActivity;
37 | private ArrayList videos; //当前需要显示的所有的视频数据
38 | private ArrayList mSelectedVideos; //全局保存的已经选中的视频数据
39 | private boolean isShowCamera; //是否显示录像按钮
40 | private int mVideoSize; //每个条目的大小
41 | private OnVideoItemClickListener listener; //视频被点击的监听
42 |
43 | public VideoGridAdapter(Activity activity, ArrayList videos) {
44 | this.mActivity = activity;
45 | if (videos == null || videos.size() == 0) this.videos = new ArrayList<>();
46 | else this.videos = videos;
47 |
48 | mVideoSize = Utils.getImageItemWidth(mActivity);
49 | videoPicker = VideoPicker.getInstance();
50 | isShowCamera = videoPicker.isShowCamera();
51 | mSelectedVideos = videoPicker.getSelectedVideos();
52 | }
53 |
54 | public void refreshData(ArrayList videos) {
55 | if (videos == null || videos.size() == 0) this.videos = new ArrayList<>();
56 | else this.videos = videos;
57 | notifyDataSetChanged();
58 | }
59 |
60 | @Override
61 | public int getViewTypeCount() {
62 | return 2;
63 | }
64 |
65 | @Override
66 | public int getItemViewType(int position) {
67 | if (isShowCamera) return position == 0 ? ITEM_TYPE_CAMERA : ITEM_TYPE_NORMAL;
68 | return ITEM_TYPE_NORMAL;
69 | }
70 |
71 | @Override
72 | public int getCount() {
73 | return isShowCamera ? videos.size() + 1 : videos.size();
74 | }
75 |
76 | /**
77 | * 根据是否显示相机来判断list位置
78 | * @param position
79 | * @return
80 | */
81 | @Override
82 | public VideoItem getItem(int position) {
83 | if (isShowCamera) {
84 | if (position == 0) return null;
85 | return videos.get(position - 1);
86 | } else {
87 | return videos.get(position);
88 | }
89 | }
90 |
91 | @Override
92 | public long getItemId(int position) {
93 | return position;
94 | }
95 |
96 | @Override
97 | public View getView(final int position, View convertView, ViewGroup parent) {
98 | int itemViewType = getItemViewType(position);
99 | //相机录像
100 | if (itemViewType == ITEM_TYPE_CAMERA) {
101 | convertView = LayoutInflater.from(mActivity).inflate(com.pbq.imagepicker.R.layout.adapter_record_item, parent, false);
102 | convertView.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mVideoSize)); //让视频是个正方形
103 | convertView.setTag(null);
104 | convertView.setOnClickListener(new View.OnClickListener() {
105 | @Override
106 | public void onClick(View v) {
107 | if (!((ImageBaseActivity) mActivity).checkPermission(Manifest.permission.CAMERA)) {
108 | ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.CAMERA}, VideoGridActivity.REQUEST_PERMISSION_CAMERA);
109 | } else {
110 | //录像
111 | videoPicker.takeRecord(mActivity, VideoPicker.REQUEST_VIDEO_TAKE);
112 | }
113 | }
114 | });
115 | } else {
116 | final ViewHolder holder;
117 | if (convertView == null) {
118 | convertView = LayoutInflater.from(mActivity).inflate(com.pbq.imagepicker.R.layout.adapter_video_item, parent, false);
119 | convertView.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mVideoSize)); //让视频是个正方形
120 | holder = new ViewHolder(convertView);
121 | convertView.setTag(holder);
122 | } else {
123 | holder = (ViewHolder) convertView.getTag();
124 | }
125 | final VideoItem videoItem = getItem(position);
126 | /**
127 | * 点击图片的监听
128 | */
129 | holder.ivThumb.setOnClickListener(new View.OnClickListener() {
130 | @Override
131 | public void onClick(View v) {
132 | if (listener != null) listener.onVideoItemClick(holder.rootView, videoItem, position);
133 | }
134 | });
135 |
136 | //显示时长 转化成分秒
137 | holder.tv_timelong.setText(videoPicker.timeParse(videoItem.timeLong));
138 |
139 | //视频的选择
140 | holder.cbCheck.setOnClickListener(new View.OnClickListener() {
141 | @Override
142 | public void onClick(View v) {
143 | int selectLimit = videoPicker.getSelectLimit();
144 | if (holder.cbCheck.isChecked() && mSelectedVideos.size() >= selectLimit) {
145 | Toast.makeText(mActivity.getApplicationContext(), mActivity.getString(com.pbq.imagepicker.R.string.select_video_limit, selectLimit), Toast.LENGTH_SHORT).show();
146 | holder.cbCheck.setChecked(false);
147 | holder.mask.setVisibility(View.GONE);
148 | } else {
149 | videoPicker.addSelectedVideoItem(position, videoItem, holder.cbCheck.isChecked());
150 | holder.mask.setVisibility(View.VISIBLE);
151 | }
152 | }
153 | });
154 | //根据是否多选,显示或隐藏checkbox
155 | if (videoPicker.isMultiMode()) {
156 | holder.cbCheck.setVisibility(View.VISIBLE);
157 | boolean checked = mSelectedVideos.contains(videoItem);
158 | /**
159 | * 判断该项视频是否选中,如果选中,将背景显示出来,将多选框选中状态
160 | * 否则隐藏背景,多选框未选中状态
161 | */
162 | if (checked) {
163 | holder.mask.setVisibility(View.VISIBLE);
164 | holder.cbCheck.setChecked(true);
165 | } else {
166 | holder.mask.setVisibility(View.GONE);
167 | holder.cbCheck.setChecked(false);
168 | }
169 | } else {
170 | //单选的话直接隐藏多选框
171 | holder.cbCheck.setVisibility(View.GONE);
172 | }
173 |
174 | if(videoPicker.isSelect(videoItem)){
175 | holder.mask.setVisibility(View.VISIBLE);
176 | holder.cbCheck.setChecked(true);
177 | }
178 | Glide.with(mActivity)
179 | .load(videoItem.path)
180 | .placeholder(R.mipmap.default_image)
181 | .skipMemoryCache(true)
182 | .diskCacheStrategy(DiskCacheStrategy.NONE)
183 | .into(holder.ivThumb);
184 | }
185 | return convertView;
186 | }
187 |
188 | private class ViewHolder {
189 | public View rootView;
190 | public ImageView ivThumb;
191 | public View mask;
192 | public SuperCheckBox cbCheck;
193 | public TextView tv_timelong;
194 |
195 | public ViewHolder(View view) {
196 | rootView = view;
197 | ivThumb = (ImageView) view.findViewById(com.pbq.imagepicker.R.id.iv_thumb);
198 | mask = view.findViewById(com.pbq.imagepicker.R.id.mask);
199 | cbCheck = (SuperCheckBox) view.findViewById(com.pbq.imagepicker.R.id.cb_check);
200 | tv_timelong = (TextView) view.findViewById(com.pbq.imagepicker.R.id.tv_timelong);
201 | }
202 | }
203 |
204 | public void setOnVideoItemClickListener(OnVideoItemClickListener listener) {
205 | this.listener = listener;
206 | }
207 |
208 | /**
209 | * 定义一个监听视频被点击的接口
210 | */
211 | public interface OnVideoItemClickListener {
212 | void onVideoItemClick(View view, VideoItem videoItem, int position);
213 | }
214 | }
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/VideoPicker.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.Environment;
8 | import android.provider.MediaStore;
9 | import com.pbq.imagepicker.bean.VideoFolder;
10 | import com.pbq.imagepicker.bean.VideoItem;
11 | import com.pbq.imagepicker.loader.ImageLoader;
12 |
13 | import java.io.File;
14 | import java.text.SimpleDateFormat;
15 | import java.util.ArrayList;
16 | import java.util.Date;
17 | import java.util.List;
18 | import java.util.Locale;
19 |
20 | /**
21 | * ================================================
22 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
23 | * 版 本:1.0
24 | * 创建日期:2016/5/19
25 | * 描 述:视频选择的入口类
26 | * 修订历史:
27 | * ================================================
28 | */
29 | public class VideoPicker {
30 |
31 | public static final String TAG = VideoPicker.class.getSimpleName();
32 | /**
33 | * 录像的结果请求
34 | */
35 | public static final int REQUEST_VIDEO_TAKE = 1001;
36 | /**
37 | * 请求视频预览
38 | */
39 | public static final int REQUEST_VIDEO_PREVIEW = 1002;
40 | /**
41 | * 返回视频数据的结果
42 | */
43 | public static final int RESULT_VIDEO_ITEMS = 1003;
44 | /**
45 | * 从预览界面返回
46 | */
47 | public static final int RESULT_VIDEO_BACK = 1004;
48 |
49 | /**
50 | * 选中的视频项
51 | */
52 | public static final String EXTRA_RESULT_VIDEO_ITEMS = "extra_result_items";
53 | /**
54 | * 已选择的视频项
55 | */
56 | public static final String EXTRA_SELECTED_VIDEO_POSITION = "selected_video_position";
57 | /**
58 | * 已选中的所有视频文件夹项
59 | */
60 | public static final String EXTRA_VIDEO_ITEMS = "extra_video_items";
61 |
62 | private boolean multiMode = true; //图片选择模式
63 | private int selectLimit = 9; //最大选择图片数量
64 | private boolean showCamera = true; //显示相机
65 | private ImageLoader imageLoader; //图片加载器
66 | private File takeVideoFile;
67 |
68 | private ArrayList mSelectedVideos = new ArrayList<>(); //选中的图片集合
69 | private List mVideoFolders; //所有的图片文件夹
70 | private int mCurrentVideoFolderPosition = 0; //当前选中的文件夹位置 0表示所有图片
71 | private List mVideoSelectedListeners; // 图片选中的监听回调
72 |
73 | private static VideoPicker mInstance;
74 |
75 | private VideoPicker() {
76 | }
77 |
78 | public static VideoPicker getInstance() {
79 | if (mInstance == null) {
80 | synchronized (VideoPicker.class) {
81 | if (mInstance == null) {
82 | mInstance = new VideoPicker();
83 | }
84 | }
85 | }
86 | return mInstance;
87 | }
88 |
89 | public boolean isMultiMode() {
90 | return multiMode;
91 | }
92 |
93 | public void setMultiMode(boolean multiMode) {
94 | this.multiMode = multiMode;
95 | }
96 |
97 | public int getSelectLimit() {
98 | return selectLimit;
99 | }
100 |
101 | public void setSelectLimit(int selectLimit) {
102 | this.selectLimit = selectLimit;
103 | }
104 |
105 | public boolean isShowCamera() {
106 | return showCamera;
107 | }
108 |
109 | public void setShowCamera(boolean showCamera) {
110 | this.showCamera = showCamera;
111 | }
112 |
113 | public File getTakeVideoFile() {
114 | return takeVideoFile;
115 | }
116 |
117 | public ImageLoader getImageLoader() {
118 | return imageLoader;
119 | }
120 |
121 | public void setImageLoader(ImageLoader imageLoader) {
122 | this.imageLoader = imageLoader;
123 | }
124 | public List getVideoFolders() {
125 | return mVideoFolders;
126 | }
127 |
128 | public void setVideoFolders(List videoFolders) {
129 | mVideoFolders = videoFolders;
130 | }
131 |
132 | public int getCurrentVideoFolderPosition() {
133 | return mCurrentVideoFolderPosition;
134 | }
135 |
136 | /** 设置当前选中视频文件夹所在的位置*/
137 | public void setCurrentVideoFolderPosition(int mCurrentSelectedVideoSetPosition) {
138 | mCurrentVideoFolderPosition = mCurrentSelectedVideoSetPosition;
139 | }
140 | /** 获取当前视频所在的文件夹 */
141 | public ArrayList getCurrentVideoFolderItems() {
142 | return mVideoFolders.get(mCurrentVideoFolderPosition).videos;
143 | }
144 | /** 是否选中该视频 checkbox*/
145 | public boolean isSelect(VideoItem item) {
146 | return mSelectedVideos.contains(item);
147 | }
148 |
149 | public int getSelectVideoCount() {
150 | if (mSelectedVideos == null) {
151 | return 0;
152 | }
153 | return mSelectedVideos.size();
154 | }
155 |
156 | public ArrayList getSelectedVideos() {
157 | return mSelectedVideos;
158 | }
159 | /** 清除选中的视频 */
160 | public void clearSelectedVideos() {
161 | if (mSelectedVideos != null) mSelectedVideos.clear();
162 | }
163 |
164 | public void clear() {
165 | if (mVideoSelectedListeners != null) {
166 | mVideoSelectedListeners.clear();
167 | mVideoSelectedListeners = null;
168 | }
169 | if (mVideoFolders != null) {
170 | mVideoFolders.clear();
171 | mVideoFolders = null;
172 | }
173 | if (mSelectedVideos != null) {
174 | mSelectedVideos.clear();
175 | }
176 | mCurrentVideoFolderPosition = 0;
177 | }
178 |
179 | /** 录像的方法 */
180 | public void takeRecord(Activity activity, int requestCode) {
181 | Intent takeRecordIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
182 | // takeRecordIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
183 | if (takeRecordIntent.resolveActivity(activity.getPackageManager()) != null) {
184 | //是否存在SD卡
185 | if (Utils.existSDCard())
186 | takeVideoFile = new File(Environment.getExternalStorageDirectory(), "/DCIM/movie/");
187 | else takeVideoFile = Environment.getDataDirectory();
188 | takeVideoFile = createFile(takeVideoFile, "RIDEO_", ".mp4");
189 | if (takeVideoFile != null) {
190 | // 默认情况下,即不需要指定intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
191 | // 照相机有自己默认的存储路径,拍摄的照片将返回一个缩略图。如果想访问原始图片,
192 | // 可以通过dat extra能够得到原始图片位置。即,如果指定了目标uri,data就没有数据,
193 | // 如果没有指定uri,则data就返回有数据!
194 | takeRecordIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(takeVideoFile));
195 | }
196 | }
197 | takeRecordIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
198 | activity.startActivityForResult(takeRecordIntent, requestCode);
199 | }
200 |
201 | /** 根据系统时间、前缀、后缀产生一个文件 */
202 | public static File createFile(File folder, String prefix, String suffix) {
203 | if (!folder.exists() || !folder.isDirectory()) folder.mkdirs();
204 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA);
205 | String filename = prefix + dateFormat.format(new Date(System.currentTimeMillis())) + suffix;
206 | return new File(folder, filename);
207 | }
208 |
209 | /** 扫描图片 */
210 | public static void galleryAddPic(Context context, File file) {
211 | Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
212 | Uri contentUri = Uri.fromFile(file);
213 | mediaScanIntent.setData(contentUri);
214 | context.sendBroadcast(mediaScanIntent);
215 | }
216 |
217 | /** 视频选中的监听 */
218 | public interface OnVideoSelectedListener {
219 | void onVideoSelected(int position, VideoItem item, boolean isAdd);
220 | }
221 | /** 添加视频选中的监听 */
222 | public void addOnVideoSelectedListener(OnVideoSelectedListener l) {
223 | if (mVideoSelectedListeners == null) mVideoSelectedListeners = new ArrayList<>();
224 | mVideoSelectedListeners.add(l);
225 | }
226 |
227 | public void removeOnVideoSelectedListener(OnVideoSelectedListener l) {
228 | if (mVideoSelectedListeners == null) return;
229 | mVideoSelectedListeners.remove(l);
230 | }
231 | /** 添加选中某一项视频 */
232 | public void addSelectedVideoItem(int position, VideoItem item, boolean isAdd) {
233 | if (isAdd) mSelectedVideos.add(item);
234 | else mSelectedVideos.remove(item);
235 | notifyVideoSelectedChanged(position, item, isAdd);
236 | }
237 |
238 | private void notifyVideoSelectedChanged(int position, VideoItem item, boolean isAdd) {
239 | if (mVideoSelectedListeners == null) return;
240 | for (OnVideoSelectedListener l : mVideoSelectedListeners) {
241 | l.onVideoSelected(position, item, isAdd);
242 | }
243 | }
244 |
245 | /**
246 | * Android读出的时长为 long 类型以毫秒数为单位,例如:将 234736 转化为分钟和秒应为 03:55 (包含四舍五入)
247 | * @param duration 时长
248 | * @return
249 | */
250 | public String timeParse(long duration) {
251 | String time = "" ;
252 | long minute = duration / 60000 ;
253 | long seconds = duration % 60000 ;
254 | long second = Math.round((float)seconds/1000) ;
255 | if( minute < 10 ){
256 | time += "0" ;
257 | }
258 | time += minute+":" ;
259 | if( second < 10 ){
260 | time += "0" ;
261 | }
262 | time += second ;
263 | return time ;
264 | }
265 | }
--------------------------------------------------------------------------------
/imagepicker/src/main/java/com/pbq/imagepicker/ImagePicker.java:
--------------------------------------------------------------------------------
1 | package com.pbq.imagepicker;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.Bitmap;
7 | import android.net.Uri;
8 | import android.os.Environment;
9 | import android.provider.MediaStore;
10 |
11 | import com.pbq.imagepicker.bean.ImageFolder;
12 | import com.pbq.imagepicker.bean.ImageItem;
13 | import com.pbq.imagepicker.loader.ImageLoader;
14 | import com.pbq.imagepicker.view.CropImageView;
15 |
16 | import java.io.File;
17 | import java.text.SimpleDateFormat;
18 | import java.util.ArrayList;
19 | import java.util.Date;
20 | import java.util.List;
21 | import java.util.Locale;
22 |
23 | /**
24 | * ================================================
25 | * 作 者:jeasonlzy(廖子尧 Github地址:https://github.com/jeasonlzy0216
26 | * 版 本:1.0
27 | * 创建日期:2016/5/19
28 | * 描 述:图片选择的入口类
29 | * 修订历史:
30 | * ================================================
31 | */
32 | public class ImagePicker {
33 |
34 | public static final String TAG = ImagePicker.class.getSimpleName();
35 | public static final int REQUEST_IMAGE_TAKE = 1001;
36 | public static final int REQUEST_IMAGE_CROP = 1002;
37 | public static final int REQUEST_IMAGE_PREVIEW = 1003;
38 | public static final int RESULT_IMAGE_ITEMS = 1004;
39 | public static final int RESULT_IMAGE_BACK = 1005;
40 |
41 | public static final String EXTRA_RESULT_ITEMS = "extra_result_items";
42 | public static final String EXTRA_SELECTED_IMAGE_POSITION = "selected_image_position";
43 | public static final String EXTRA_IMAGE_ITEMS = "extra_image_items";
44 |
45 | private boolean multiMode = true; //图片选择模式
46 | private int selectLimit = 9; //最大选择图片数量
47 | private boolean crop = true; //裁剪
48 | private boolean showCamera = true; //显示相机
49 | private boolean isSaveRectangle = false; //裁剪后的图片是否是矩形,否者跟随裁剪框的形状
50 | private int outPutX = 800; //裁剪保存宽度
51 | private int outPutY = 800; //裁剪保存高度
52 | private int focusWidth = 280; //焦点框的宽度
53 | private int focusHeight = 280; //焦点框的高度
54 | private ImageLoader imageLoader; //图片加载器
55 | private CropImageView.Style style = CropImageView.Style.RECTANGLE; //裁剪框的形状
56 | private File cropCacheFolder;
57 | private File takeImageFile;
58 | public Bitmap cropBitmap;
59 |
60 | private ArrayList mSelectedImages = new ArrayList<>(); //选中的图片集合
61 | private List mImageFolders; //所有的图片文件夹
62 | private int mCurrentImageFolderPosition = 0; //当前选中的文件夹位置 0表示所有图片
63 | private List mImageSelectedListeners; // 图片选中的监听回调
64 |
65 | private static ImagePicker mInstance;
66 |
67 | private ImagePicker() {
68 | }
69 |
70 | public static ImagePicker getInstance() {
71 | if (mInstance == null) {
72 | synchronized (ImagePicker.class) {
73 | if (mInstance == null) {
74 | mInstance = new ImagePicker();
75 | }
76 | }
77 | }
78 | return mInstance;
79 | }
80 |
81 | public boolean isMultiMode() {
82 | return multiMode;
83 | }
84 |
85 | public void setMultiMode(boolean multiMode) {
86 | this.multiMode = multiMode;
87 | }
88 |
89 | public int getSelectLimit() {
90 | return selectLimit;
91 | }
92 |
93 | public void setSelectLimit(int selectLimit) {
94 | this.selectLimit = selectLimit;
95 | }
96 |
97 | public boolean isCrop() {
98 | return crop;
99 | }
100 |
101 | public void setCrop(boolean crop) {
102 | this.crop = crop;
103 | }
104 |
105 | public boolean isShowCamera() {
106 | return showCamera;
107 | }
108 |
109 | public void setShowCamera(boolean showCamera) {
110 | this.showCamera = showCamera;
111 | }
112 |
113 | public boolean isSaveRectangle() {
114 | return isSaveRectangle;
115 | }
116 |
117 | public void setSaveRectangle(boolean isSaveRectangle) {
118 | this.isSaveRectangle = isSaveRectangle;
119 | }
120 |
121 | public int getOutPutX() {
122 | return outPutX;
123 | }
124 |
125 | public void setOutPutX(int outPutX) {
126 | this.outPutX = outPutX;
127 | }
128 |
129 | public int getOutPutY() {
130 | return outPutY;
131 | }
132 |
133 | public void setOutPutY(int outPutY) {
134 | this.outPutY = outPutY;
135 | }
136 |
137 | public int getFocusWidth() {
138 | return focusWidth;
139 | }
140 |
141 | public void setFocusWidth(int focusWidth) {
142 | this.focusWidth = focusWidth;
143 | }
144 |
145 | public int getFocusHeight() {
146 | return focusHeight;
147 | }
148 |
149 | public void setFocusHeight(int focusHeight) {
150 | this.focusHeight = focusHeight;
151 | }
152 |
153 | public File getTakeImageFile() {
154 | return takeImageFile;
155 | }
156 |
157 | public File getCropCacheFolder(Context context) {
158 | if (cropCacheFolder == null) {
159 | cropCacheFolder = new File(context.getCacheDir() + "/ImagePicker/cropTemp/");
160 | }
161 | return cropCacheFolder;
162 | }
163 |
164 | public void setCropCacheFolder(File cropCacheFolder) {
165 | this.cropCacheFolder = cropCacheFolder;
166 | }
167 |
168 | public ImageLoader getImageLoader() {
169 | return imageLoader;
170 | }
171 |
172 | public void setImageLoader(ImageLoader imageLoader) {
173 | this.imageLoader = imageLoader;
174 | }
175 |
176 | public CropImageView.Style getStyle() {
177 | return style;
178 | }
179 |
180 | public void setStyle(CropImageView.Style style) {
181 | this.style = style;
182 | }
183 |
184 | public List getImageFolders() {
185 | return mImageFolders;
186 | }
187 |
188 | public void setImageFolders(List imageFolders) {
189 | mImageFolders = imageFolders;
190 | }
191 |
192 | public int getCurrentImageFolderPosition() {
193 | return mCurrentImageFolderPosition;
194 | }
195 |
196 | public void setCurrentImageFolderPosition(int mCurrentSelectedImageSetPosition) {
197 | mCurrentImageFolderPosition = mCurrentSelectedImageSetPosition;
198 | }
199 |
200 | public ArrayList getCurrentImageFolderItems() {
201 | return mImageFolders.get(mCurrentImageFolderPosition).images;
202 | }
203 |
204 | public boolean isSelect(ImageItem item) {
205 | return mSelectedImages.contains(item);
206 | }
207 |
208 | public int getSelectImageCount() {
209 | if (mSelectedImages == null) {
210 | return 0;
211 | }
212 | return mSelectedImages.size();
213 | }
214 |
215 | public ArrayList getSelectedImages() {
216 | return mSelectedImages;
217 | }
218 |
219 | public void clearSelectedImages() {
220 | if (mSelectedImages != null) mSelectedImages.clear();
221 | }
222 |
223 | public void clear() {
224 | if (mImageSelectedListeners != null) {
225 | mImageSelectedListeners.clear();
226 | mImageSelectedListeners = null;
227 | }
228 | if (mImageFolders != null) {
229 | mImageFolders.clear();
230 | mImageFolders = null;
231 | }
232 | if (mSelectedImages != null) {
233 | mSelectedImages.clear();
234 | }
235 | mCurrentImageFolderPosition = 0;
236 | }
237 |
238 | /** 拍照的方法 */
239 | public void takePicture(Activity activity, int requestCode) {
240 | Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
241 | takePictureIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
242 | if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {
243 | if (Utils.existSDCard())
244 | takeImageFile = new File(Environment.getExternalStorageDirectory(), "/DCIM/camera/");
245 | else takeImageFile = Environment.getDataDirectory();
246 | takeImageFile = createFile(takeImageFile, "IMG_", ".jpg");
247 | if (takeImageFile != null) {
248 | // 默认情况下,即不需要指定intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
249 | // 照相机有自己默认的存储路径,拍摄的照片将返回一个缩略图。如果想访问原始图片,
250 | // 可以通过dat extra能够得到原始图片位置。即,如果指定了目标uri,data就没有数据,
251 | // 如果没有指定uri,则data就返回有数据!
252 | takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(takeImageFile));
253 | }
254 | }
255 | activity.startActivityForResult(takePictureIntent, requestCode);
256 | }
257 |
258 | /** 根据系统时间、前缀、后缀产生一个文件 */
259 | public static File createFile(File folder, String prefix, String suffix) {
260 | if (!folder.exists() || !folder.isDirectory()) folder.mkdirs();
261 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA);
262 | String filename = prefix + dateFormat.format(new Date(System.currentTimeMillis())) + suffix;
263 | return new File(folder, filename);
264 | }
265 |
266 | /** 扫描图片 */
267 | public static void galleryAddPic(Context context, File file) {
268 | Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
269 | Uri contentUri = Uri.fromFile(file);
270 | mediaScanIntent.setData(contentUri);
271 | context.sendBroadcast(mediaScanIntent);
272 | }
273 |
274 | /** 图片选中的监听 */
275 | public interface OnImageSelectedListener {
276 | void onImageSelected(int position, ImageItem item, boolean isAdd);
277 | }
278 |
279 | public void addOnImageSelectedListener(OnImageSelectedListener l) {
280 | if (mImageSelectedListeners == null) mImageSelectedListeners = new ArrayList<>();
281 | mImageSelectedListeners.add(l);
282 | }
283 |
284 | public void removeOnImageSelectedListener(OnImageSelectedListener l) {
285 | if (mImageSelectedListeners == null) return;
286 | mImageSelectedListeners.remove(l);
287 | }
288 |
289 | public void addSelectedImageItem(int position, ImageItem item, boolean isAdd) {
290 | if (isAdd) mSelectedImages.add(item);
291 | else mSelectedImages.remove(item);
292 | notifyImageSelectedChanged(position, item, isAdd);
293 | }
294 |
295 | private void notifyImageSelectedChanged(int position, ImageItem item, boolean isAdd) {
296 | if (mImageSelectedListeners == null) return;
297 | for (OnImageSelectedListener l : mImageSelectedListeners) {
298 | l.onImageSelected(position, item, isAdd);
299 | }
300 | }
301 | }
--------------------------------------------------------------------------------