├── .gitignore
├── .idea
├── .name
├── codeStyleSettings.xml
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── findbugs-idea.xml
├── gradle.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── imageseletor
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── io
│ │ └── github
│ │ └── lijunguan
│ │ └── imgselector
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── io
│ │ │ └── github
│ │ │ └── lijunguan
│ │ │ └── imgselector
│ │ │ ├── AlbumConfig.java
│ │ │ ├── ImageSelector.java
│ │ │ ├── album
│ │ │ ├── AlbumActivity.java
│ │ │ ├── AlbumContract.java
│ │ │ ├── AlbumFragment.java
│ │ │ ├── AlbumPresenter.java
│ │ │ ├── adapter
│ │ │ │ ├── FolderListAdapter.java
│ │ │ │ └── ImageGridAdapter.java
│ │ │ ├── previewimage
│ │ │ │ ├── ImageContract.java
│ │ │ │ ├── ImageDetailFragment.java
│ │ │ │ └── ImageDetailPresenter.java
│ │ │ └── widget
│ │ │ │ ├── GridDividerDecorator.java
│ │ │ │ └── HackyViewPager.java
│ │ │ ├── base
│ │ │ ├── BaseActivity.java
│ │ │ ├── BaseFragment.java
│ │ │ ├── BasePresenter.java
│ │ │ └── BaseView.java
│ │ │ ├── cropimage
│ │ │ ├── CropActivity.java
│ │ │ ├── CropFragment.java
│ │ │ └── crop
│ │ │ │ ├── CropView.java
│ │ │ │ ├── CropViewConfig.java
│ │ │ │ └── TouchManager.java
│ │ │ ├── model
│ │ │ ├── AlbumDataSource.java
│ │ │ ├── AlbumRepository.java
│ │ │ └── entity
│ │ │ │ ├── AlbumFolder.java
│ │ │ │ └── ImageInfo.java
│ │ │ └── utils
│ │ │ ├── ActivityUtils.java
│ │ │ ├── CommonUtils.java
│ │ │ ├── FileUtils.java
│ │ │ ├── KLog.java
│ │ │ └── StatusBarUtil.java
│ └── res
│ │ ├── drawable-v21
│ │ ├── ic_add_a_photo_grey_100_36dp.xml
│ │ └── ic_photo_library_white_24dp.xml
│ │ ├── drawable
│ │ ├── action_btn.xml
│ │ ├── button_bg.xml
│ │ ├── divider_bg.xml
│ │ ├── ic_add_a_photo_grey_100_36dp.xml
│ │ ├── ic_photo_library_white_24dp.xml
│ │ └── placeholder.png
│ │ ├── layout
│ │ ├── activity_album.xml
│ │ ├── activity_crop.xml
│ │ ├── crop_view.xml
│ │ ├── fragment_album.xml
│ │ ├── fragmetn_image_detail.xml
│ │ ├── item_album_folder_list.xml
│ │ ├── item_camera.xml
│ │ ├── item_image_detail.xml
│ │ ├── item_image_grid.xml
│ │ ├── layout_album_list.xml
│ │ ├── layout_appbar.xml
│ │ └── layout_no_image.xml
│ │ ├── menu
│ │ └── menu_album.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-v21
│ │ ├── attrs.xml
│ │ └── styles.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── io
│ └── github
│ └── lijunguan
│ └── imgselector
│ └── ExampleUnitTest.java
├── sample
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── io
│ │ └── github
│ │ └── lijunguan
│ │ └── sample
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── io
│ │ │ └── github
│ │ │ └── lijunguan
│ │ │ └── sample
│ │ │ ├── App.java
│ │ │ ├── GridDividerDecorator.java
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── drawable-v21
│ │ └── ic_send_white_24dp.xml
│ │ ├── drawable
│ │ ├── bg_rounded_rectangle.xml
│ │ ├── divider_background.xml
│ │ └── ic_send_white_24dp.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ └── content_main.xml
│ │ ├── menu
│ │ └── menu_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-v21
│ │ └── styles.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── io
│ └── github
│ └── lijunguan
│ └── sample
│ └── ExampleUnitTest.java
├── screenshot
├── ScrennShot1.gif
├── ScrennShot2.gif
└── sample-imageselector.apk
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | <<<<<<< HEAD
2 | *.iml
3 | .gradle
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 | /captures
10 | =======
11 | # Built application files
12 | *.apk
13 | *.ap_
14 |
15 | # Files for the Dalvik VM
16 | *.dex
17 |
18 | # Java class files
19 | *.class
20 |
21 | # Generated files
22 | bin/
23 | gen/
24 |
25 | # Gradle files
26 | .gradle/
27 | build/
28 |
29 | # Local configuration file (sdk path, etc)
30 | local.properties
31 |
32 | # Proguard folder generated by Eclipse
33 | proguard/
34 |
35 | # Log Files
36 | *.log
37 |
38 | # Android Studio Navigation editor temp files
39 | .navigation/
40 |
41 | # Android Studio captures folder
42 | captures/
43 | >>>>>>> 97156da623033c1f6d7a8544e7cd788872411058
44 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | AlbumSelector
--------------------------------------------------------------------------------
/.idea/codeStyleSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
24 |
29 |
34 |
61 |
63 |
null
if no {@link Bitmap} has been
178 | * provided.
179 | */
180 | @Nullable
181 | public Bitmap crop() {
182 | if (bitmap == null) {
183 | return null;
184 | }
185 |
186 | final Bitmap src = bitmap;
187 | final Bitmap.Config srcConfig = src.getConfig();
188 | final Bitmap.Config config = srcConfig == null ? Bitmap.Config.ARGB_8888 : srcConfig;
189 | final int viewportHeight = touchManager.getViewportHeight();
190 | final int viewportWidth = touchManager.getViewportWidth();
191 |
192 | final Bitmap dst = Bitmap.createBitmap(viewportWidth, viewportHeight, config);
193 |
194 | Canvas canvas = new Canvas(dst);
195 | final int left = (getRight() - viewportWidth) / 2;
196 | final int top = (getBottom() - viewportHeight) / 2;
197 | canvas.translate(-left, -top);
198 |
199 | drawBitmap(canvas);
200 |
201 | return dst;
202 | }
203 |
204 | /**
205 | * Obtain current viewport width.
206 | *
207 | * @return Current viewport width.
208 | * Note: It might be 0 if layout pass has not been completed.
209 | */ 210 | public int getViewportWidth() { 211 | return touchManager.getViewportWidth(); 212 | } 213 | 214 | /** 215 | * Obtain current viewport height. 216 | * 217 | * @return Current viewport height. 218 | *Note: It might be 0 if layout pass has not been completed.
219 | */ 220 | public int getViewportHeight() { 221 | return touchManager.getViewportHeight(); 222 | } 223 | 224 | 225 | public static class CropRequest { 226 | 227 | private final CropView cropView; 228 | private Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG; 229 | private int quality = CropViewConfig.DEFAULT_IMAGE_QUALITY; 230 | 231 | public CropRequest(@NonNull CropView cropView) { 232 | checkNotNull(cropView, "cropView == null"); 233 | this.cropView = cropView; 234 | } 235 | 236 | /** 237 | * Compression format to use, defaults to {@link Bitmap.CompressFormat#JPEG}. 238 | * 239 | * @return current request for chaining. 240 | */ 241 | public CropRequest format(@NonNull Bitmap.CompressFormat format) { 242 | checkNotNull(format, "format == null"); 243 | this.format = format; 244 | return this; 245 | } 246 | 247 | /** 248 | * Compression quality to use (must be 0..100), defaults to {@value CropViewConfig#DEFAULT_IMAGE_QUALITY}. 249 | * 250 | * @return current request for chaining. 251 | */ 252 | public CropRequest quality(int quality) { 253 | checkArgument(quality >= 0 && quality <= 100, "quality must be 0..100"); 254 | this.quality = quality; 255 | return this; 256 | } 257 | 258 | 259 | //TODO 有必要的话 采用Callable + Future (将此方法在非主线程中执行) 260 | 261 | /** 262 | * 同步地将裁剪后的bitmap 写入到提供的file中, 如果需要会创建父目录 263 | * 264 | * @param file Must have permissions to write, will be created if doesn't exist or overwrite if it does. 265 | */ 266 | public void into(@NonNull File file) throws IOException { 267 | final Bitmap croppedBitmap = cropView.crop(); 268 | flushToFile(croppedBitmap, format, quality, file); 269 | } 270 | 271 | private void flushToFile(final Bitmap bitmap, 272 | final Bitmap.CompressFormat format, 273 | final int quality, 274 | final File file) throws IOException { 275 | 276 | OutputStream outputStream = null; 277 | try { 278 | file.getParentFile().mkdirs(); 279 | outputStream = new FileOutputStream(file); 280 | bitmap.compress(format, quality, outputStream); 281 | outputStream.flush(); 282 | } finally { 283 | try { 284 | if (outputStream != null) { 285 | outputStream.close(); 286 | } 287 | } catch (IOException e) { 288 | e.printStackTrace(); 289 | } 290 | } 291 | 292 | } 293 | } 294 | 295 | } 296 | -------------------------------------------------------------------------------- /imageseletor/src/main/java/io/github/lijunguan/imgselector/cropimage/crop/CropViewConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Lyft, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.github.lijunguan.imgselector.cropimage.crop; 17 | 18 | import android.content.Context; 19 | import android.content.res.TypedArray; 20 | import android.util.AttributeSet; 21 | 22 | import io.github.lijunguan.imgselector.R; 23 | 24 | class CropViewConfig { 25 | 26 | public static final float DEFAULT_VIEWPORT_RATIO = 0f; 27 | public static final float DEFAULT_MAXIMUM_SCALE = 10f; 28 | public static final float DEFAULT_MINIMUM_SCALE = 0f; 29 | public static final int DEFAULT_IMAGE_QUALITY = 100; 30 | public static final int DEFAULT_VIEWPORT_OVERLAY_PADDING = 0; 31 | public static final int DEFAULT_VIEWPORT_OVERLAY_COLOR = 0xC8000000; // Black with 200 alpha 32 | 33 | private float viewportRatio = DEFAULT_VIEWPORT_RATIO; 34 | private float maxScale = DEFAULT_MAXIMUM_SCALE; 35 | private float minScale = DEFAULT_MINIMUM_SCALE; 36 | private int viewportOverlayPadding = DEFAULT_VIEWPORT_OVERLAY_PADDING; 37 | private int viewportOverlayColor = DEFAULT_VIEWPORT_OVERLAY_COLOR; 38 | 39 | public int getViewportOverlayColor() { 40 | return viewportOverlayColor; 41 | } 42 | 43 | void setViewportOverlayColor(int viewportOverlayColor) { 44 | this.viewportOverlayColor = viewportOverlayColor; 45 | } 46 | 47 | public int getViewportOverlayPadding() { 48 | return viewportOverlayPadding; 49 | } 50 | 51 | void setViewportOverlayPadding(int viewportOverlayPadding) { 52 | this.viewportOverlayPadding = viewportOverlayPadding; 53 | } 54 | 55 | public float getViewportRatio() { 56 | return viewportRatio; 57 | } 58 | 59 | void setViewportRatio(float viewportRatio) { 60 | this.viewportRatio = viewportRatio <= 0 ? DEFAULT_VIEWPORT_RATIO : viewportRatio; 61 | } 62 | 63 | public float getMaxScale() { 64 | return maxScale; 65 | } 66 | 67 | void setMaxScale(float maxScale) { 68 | this.maxScale = maxScale <= 0 ? DEFAULT_MAXIMUM_SCALE : maxScale; 69 | } 70 | 71 | public float getMinScale() { 72 | return minScale; 73 | } 74 | 75 | void setMinScale(float minScale) { 76 | this.minScale = minScale <= 0 ? DEFAULT_MINIMUM_SCALE : minScale; 77 | } 78 | 79 | public static CropViewConfig from(Context context, AttributeSet attrs) { 80 | final CropViewConfig cropViewConfig = new CropViewConfig(); 81 | 82 | if (attrs == null) { 83 | return cropViewConfig; 84 | } 85 | 86 | TypedArray attributes = context.obtainStyledAttributes( 87 | attrs, 88 | R.styleable.CropView); 89 | 90 | cropViewConfig.setViewportRatio( 91 | attributes.getFloat(R.styleable.CropView_ViewportRatio, 92 | CropViewConfig.DEFAULT_VIEWPORT_RATIO)); 93 | 94 | cropViewConfig.setMaxScale( 95 | attributes.getFloat(R.styleable.CropView_MaxScale, 96 | CropViewConfig.DEFAULT_MAXIMUM_SCALE)); 97 | 98 | cropViewConfig.setMinScale( 99 | attributes.getFloat(R.styleable.CropView_MinScale, 100 | CropViewConfig.DEFAULT_MINIMUM_SCALE)); 101 | 102 | cropViewConfig.setViewportOverlayColor( 103 | attributes.getColor(R.styleable.CropView_ViewportOverlayColor, 104 | CropViewConfig.DEFAULT_VIEWPORT_OVERLAY_COLOR)); 105 | 106 | cropViewConfig.setViewportOverlayPadding( 107 | attributes.getDimensionPixelSize(R.styleable.CropView_ViewportOverlayPadding, 108 | CropViewConfig.DEFAULT_VIEWPORT_OVERLAY_PADDING)); 109 | 110 | attributes.recycle(); 111 | 112 | return cropViewConfig; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /imageseletor/src/main/java/io/github/lijunguan/imgselector/model/AlbumDataSource.java: -------------------------------------------------------------------------------- 1 | package io.github.lijunguan.imgselector.model; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.LoaderManager; 6 | 7 | import java.util.List; 8 | 9 | import io.github.lijunguan.imgselector.model.entity.AlbumFolder; 10 | 11 | 12 | /** 13 | * Created by lijunguan on 2016/4/8 14 | * email: lijunguan199210@gmail.com 15 | * blog : https://lijunguan.github.io 16 | *
17 | * Model 层接口
18 | */
19 | public interface AlbumDataSource {
20 |
21 |
22 | void initImgRepository(@NonNull LoaderManager loaderManager, @NonNull InitAlbumCallback mCallback);
23 |
24 | @Nullable
25 | List