├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wuwang
│ │ └── app
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── wuwang
│ │ │ └── app
│ │ │ ├── ExampleCropPath.java
│ │ │ ├── MainActivity.java
│ │ │ └── ShowAdapter.java
│ └── res
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ └── item_image.xml
│ │ ├── menu
│ │ └── item_menu.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-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── wuwang
│ └── app
│ └── ExampleUnitTest.java
├── build.gradle
├── chooser
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wuwang
│ │ └── imagechooser
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── wuwang
│ │ │ ├── imagechooser
│ │ │ ├── ChooserSetting.java
│ │ │ ├── EntryActivity.java
│ │ │ ├── IcFinal.java
│ │ │ ├── abslayer
│ │ │ │ ├── IAlpha.java
│ │ │ │ ├── IImageClickListener.java
│ │ │ │ └── IPhotoShoot.java
│ │ │ ├── album
│ │ │ │ ├── AbsAlbumEntry.java
│ │ │ │ ├── AlbumAdapter.java
│ │ │ │ ├── AlbumEntry.java
│ │ │ │ ├── AlbumPopup.java
│ │ │ │ ├── AlbumTool.java
│ │ │ │ ├── AlbumVar.java
│ │ │ │ ├── FolderAdapter.java
│ │ │ │ ├── FolderFragment.java
│ │ │ │ ├── IAlbumClickListener.java
│ │ │ │ ├── ImageFolder.java
│ │ │ │ └── ImageInfo.java
│ │ │ ├── crop
│ │ │ │ ├── ACropCoverDrawable.java
│ │ │ │ ├── CropActivity.java
│ │ │ │ ├── CropCoverDrawable.java
│ │ │ │ ├── CropFragment.java
│ │ │ │ ├── CropHelper.java
│ │ │ │ └── CropPath.java
│ │ │ └── res
│ │ │ │ ├── CircleChooseDrawable.java
│ │ │ │ └── IChooseDrawable.java
│ │ │ ├── utils
│ │ │ ├── DensityUtils.java
│ │ │ └── LogUtils.java
│ │ │ └── widget
│ │ │ ├── SquareImageView.java
│ │ │ └── SquareRelativeLayout.java
│ └── res
│ │ ├── drawable
│ │ ├── image_chooser_folder_item_bg.xml
│ │ └── left_back.xml
│ │ ├── layout
│ │ ├── image_chooser_activity_crop.xml
│ │ ├── image_chooser_activity_entry.xml
│ │ ├── image_chooser_default_title.xml
│ │ ├── image_chooser_fragment_album.xml
│ │ ├── image_chooser_fragment_crop.xml
│ │ ├── image_chooser_fragment_folder.xml
│ │ ├── image_chooser_item_album.xml
│ │ ├── image_chooser_item_camera.xml
│ │ └── image_chooser_item_image.xml
│ │ ├── menu
│ │ ├── menu_album.xml
│ │ └── menu_crop.xml
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── image_chooser_back.png
│ │ ├── image_chooser_camera.png
│ │ ├── image_chooser_down.png
│ │ └── image_chooser_placeholder.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── wuwang
│ └── imagechooser
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── readme.md
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 1.8
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.1"
6 | defaultConfig {
7 | applicationId "com.wuwang.app"
8 | minSdkVersion 9
9 | targetSdkVersion 24
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
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 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | testCompile 'junit:junit:4.12'
28 | compile project(':chooser')
29 | }
30 |
--------------------------------------------------------------------------------
/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 C:\Android\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/androidTest/java/com/wuwang/app/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.app;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.wuwang.app", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuwang/app/ExampleCropPath.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.app;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.ColorFilter;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.graphics.PixelFormat;
9 | import android.graphics.PorterDuff;
10 | import android.graphics.PorterDuffXfermode;
11 | import android.graphics.Rect;
12 | import android.os.Build;
13 |
14 | import com.wuwang.imagechooser.crop.ACropCoverDrawable;
15 |
16 | /**
17 | * Created by wuwang on 2016/11/13
18 | */
19 |
20 | public class ExampleCropPath extends ACropCoverDrawable{
21 |
22 | Paint paint;
23 | private Rect rect;
24 | private Path cropPath;
25 |
26 | public ExampleCropPath(int param){
27 | super(0);
28 | paint=new Paint();
29 | paint.setAntiAlias(true);
30 | paint.setColor(0x88000000);
31 | }
32 |
33 | @Override
34 | public void draw(Canvas canvas) {
35 | int cWidth=canvas.getWidth();
36 | int cHeight=canvas.getHeight();
37 | if(rect==null){
38 | rect=new Rect(cWidth/6,cHeight/2-cWidth/3,cWidth*5/6,cHeight/2+cWidth/3);
39 | }
40 | canvas.drawColor(Color.TRANSPARENT);
41 | Path path=new Path();
42 | path.addRect(0,0,cWidth,cHeight, Path.Direction.CW);
43 | cropPath=new Path();
44 | cropPath.moveTo(rect.left,rect.top+rect.height()/4);
45 | cropPath.lineTo(rect.left+rect.width()/4,rect.top);
46 | cropPath.lineTo(rect.right-rect.width()/4,rect.top);
47 | cropPath.lineTo(rect.right,rect.top+rect.height()/4);
48 | cropPath.lineTo(rect.right,rect.centerY());
49 | cropPath.quadTo(rect.right,rect.bottom,rect.centerX(),rect.bottom);
50 | cropPath.quadTo(rect.left,rect.bottom,rect.left,rect.centerY());
51 | cropPath.close();
52 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
53 | path.op(cropPath, Path.Op.DIFFERENCE); //可以抗锯齿
54 | canvas.drawPath(path,paint);
55 | }else{
56 | //此方法可以去掉锯齿
57 | //在这里saveLayer然后restoreToCount的操作不能少,否则不会得到想要的效果
58 | int layerId = canvas.saveLayer(0, 0, cWidth, cHeight, null, Canvas.ALL_SAVE_FLAG);
59 | canvas.drawPath(path,paint);
60 | //已经绘制的可以看做为目标图
61 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
62 | canvas.drawPath(cropPath,paint);
63 | paint.setXfermode(null);
64 | canvas.restoreToCount(layerId);
65 | //裁剪的方式会有锯齿,没找到方法去掉锯齿
66 | //canvas.clipPath(opPath, Region.Op.DIFFERENCE);
67 | //canvas.drawRect(0,0,cWidth,cHeight,paint);
68 | }
69 | }
70 |
71 | @Override
72 | public void setAlpha(int alpha) {
73 | paint.setAlpha(alpha);
74 | }
75 |
76 | @Override
77 | public void setColorFilter(ColorFilter colorFilter) {
78 | paint.setColorFilter(colorFilter);
79 | }
80 |
81 | @Override
82 | public int getOpacity() {
83 | return PixelFormat.TRANSPARENT;
84 | }
85 |
86 | @Override
87 | public Rect limit() {
88 | return rect;
89 | }
90 |
91 | @Override
92 | public Path path() {
93 | return cropPath;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuwang/app/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.app;
2 |
3 | import android.content.Intent;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.view.Menu;
8 | import android.view.MenuItem;
9 | import android.widget.GridView;
10 |
11 | import com.wuwang.imagechooser.EntryActivity;
12 | import com.wuwang.imagechooser.IcFinal;
13 | import com.wuwang.imagechooser.crop.CropPath;
14 | import com.wuwang.utils.LogUtils;
15 |
16 | public class MainActivity extends AppCompatActivity {
17 |
18 | private GridView mGrid;
19 | private ShowAdapter adapter;
20 | private boolean flag; //多选flag
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_main);
26 | mGrid= (GridView) findViewById(R.id.mGrid);
27 | mGrid.setAdapter(adapter=new ShowAdapter());
28 | }
29 |
30 | @Override
31 | public boolean onCreateOptionsMenu(Menu menu) {
32 | getMenuInflater().inflate(R.menu.item_menu,menu);
33 | return super.onCreateOptionsMenu(menu);
34 | }
35 |
36 | @Override
37 | public boolean onOptionsItemSelected(MenuItem item) {
38 | flag=false;
39 | Intent intent=new Intent(IcFinal.ACTION_ALBUM);
40 | switch (item.getItemId()){
41 | case R.id.mOne:
42 | intent.putExtra(IcFinal.INTENT_MAX_IMG,1);
43 | break;
44 | case R.id.mNine:
45 | intent.putExtra(IcFinal.INTENT_MAX_IMG,9);
46 | if(flag){
47 | intent.putStringArrayListExtra(IcFinal.INTENT_EXIST_DATA,adapter.data);
48 | }
49 | flag=true;
50 | break;
51 | case R.id.mCrop:
52 | intent.putExtra(IcFinal.INTENT_IS_CROP,true);
53 | intent.putExtra(IcFinal.INTENT_CROP_SHAPE, CropPath.SHAPE_CIRCLE);
54 | intent.putExtra(IcFinal.INTENT_CROP_WIDTH,500);
55 | intent.putExtra(IcFinal.INTENT_CROP_HEIGHT,500);
56 | break;
57 | case R.id.mCrop2:
58 | intent.putExtra(IcFinal.INTENT_IS_CROP,true);
59 | intent.putExtra(IcFinal.INTENT_CROP_SHAPE, CropPath.SHAPE_RECT);
60 | intent.putExtra(IcFinal.INTENT_CROP_WIDTH,500);
61 | intent.putExtra(IcFinal.INTENT_CROP_HEIGHT,500);
62 | break;
63 | case R.id.mCrop3:
64 | LogUtils.e("wuwang",ExampleCropPath.class.getName());
65 | intent.putExtra(IcFinal.INTENT_IS_CROP,true);
66 | intent.putExtra(IcFinal.INTENT_CROP_COVER,ExampleCropPath.class.getName());
67 | intent.putExtra(IcFinal.INTENT_CROP_PARAM,1);
68 | break;
69 | }
70 | startActivityForResult(intent,1);
71 | return super.onOptionsItemSelected(item);
72 | }
73 |
74 | @Override
75 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
76 | super.onActivityResult(requestCode, resultCode, data);
77 | if(resultCode==RESULT_OK){
78 | adapter.data.clear();
79 | adapter.data.addAll(data.getStringArrayListExtra(IcFinal.RESULT_DATA_IMG));
80 | adapter.notifyDataSetChanged();
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wuwang/app/ShowAdapter.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.app;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.BaseAdapter;
7 | import android.widget.ImageView;
8 |
9 | import com.bumptech.glide.Glide;
10 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /**
16 | * Created by wuwang on 2016/11/4
17 | */
18 |
19 | public class ShowAdapter extends BaseAdapter {
20 |
21 | public ArrayList data=new ArrayList<>();
22 |
23 | public ShowAdapter(){
24 | }
25 |
26 | @Override
27 | public int getCount() {
28 | return data.size();
29 | }
30 |
31 | @Override
32 | public Object getItem(int position) {
33 | return data.get(position);
34 | }
35 |
36 | @Override
37 | public long getItemId(int position) {
38 | return position;
39 | }
40 |
41 | @Override
42 | public View getView(int position, View convertView, ViewGroup parent) {
43 | if(convertView==null){
44 | convertView= LayoutInflater.from(parent.getContext()).inflate(R.layout.image_chooser_item_image,parent,false);
45 | ImageView iv= (ImageView) convertView.findViewById(R.id.mImage);
46 | Glide.with(parent.getContext()).load(data.get(position)).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(iv);
47 | convertView.setTag(iv);
48 | }else{
49 | Glide.with(parent.getContext()).load(data.get(position)).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into((ImageView) convertView.getTag());
50 | }
51 | return convertView;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/item_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #0dc6e2
4 | #0dc6e2
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ImageChooser
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/wuwang/app/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.app;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/chooser/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chooser/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 9
9 | targetSdkVersion 24
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 |
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(include: ['*.jar'], dir: 'libs')
25 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
26 | exclude group: 'com.android.support', module: 'support-annotations'
27 | })
28 | compile 'com.android.support:appcompat-v7:24.2.0'
29 | testCompile 'junit:junit:4.12'
30 | compile 'com.github.bumptech.glide:glide:3.7.0'
31 | }
32 |
--------------------------------------------------------------------------------
/chooser/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 C:\Android\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 |
--------------------------------------------------------------------------------
/chooser/src/androidTest/java/com/wuwang/imagechooser/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.wuwang.imagechooser.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/chooser/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/ChooserSetting.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser;
2 |
3 |
4 | import android.os.Environment;
5 |
6 | import com.wuwang.imagechooser.res.CircleChooseDrawable;
7 | import com.wuwang.imagechooser.res.IChooseDrawable;
8 |
9 | /**
10 | * Description:
11 | */
12 | public class ChooserSetting{
13 |
14 |
15 | public static final int TP_SYSTEM=0;
16 | public static final int TP_CUSTOM=1;
17 | public static final int TP_NONE=2;
18 |
19 | /**标题的背景颜色*/
20 | public static int TITLE_COLOR=0xFF0dc6e2;
21 |
22 | /**图片选择页,每行显示数*/
23 | public static int NUM_COLUMNS=3;
24 |
25 | /**图片加载失败的图片*/
26 | public static int errorResId=0;
27 |
28 | /**图片加载的占位图片*/
29 | public static int placeResId=R.mipmap.image_chooser_placeholder;
30 |
31 | /**图片加载的动画*/
32 | public static int loadAnimateResId=0;
33 |
34 | /**拍照设置*/
35 | public static int takePhotoType=TP_SYSTEM;
36 |
37 | public static int tackPhotoIcon=0;
38 |
39 | /**选中图片的滤镜颜色*/
40 | public static int chooseFilter=0x55000000;
41 |
42 | /**未被选中的图片的滤镜颜色*/
43 | public static int unChooseFilter=0;
44 |
45 | /**最新的图片集合显示名字*/
46 | public static String newestAlbumName="最新图片";
47 |
48 | /**最新图片集合的最大数量*/
49 | public static int newestAlbumSize=100;
50 |
51 | public static int albumPopupHeight=600;
52 |
53 | public static String tantoToast="";
54 |
55 | /**照片选择指示器*/
56 | public static IChooseDrawable chooseDrawable=new CircleChooseDrawable(true,0xFF25c2e6);
57 |
58 | /**临时文件存储位置*/
59 | public static String tempFolder= Environment.getExternalStorageDirectory().getAbsolutePath()+"/Wuwang/";
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/EntryActivity.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser;
2 |
3 | import android.app.Activity;
4 | import android.content.BroadcastReceiver;
5 | import android.content.ContentResolver;
6 | import android.content.ContentValues;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.content.IntentFilter;
10 | import android.content.res.Resources;
11 | import android.database.ContentObserver;
12 | import android.graphics.Bitmap;
13 | import android.graphics.Rect;
14 | import android.media.MediaScannerConnection;
15 | import android.net.Uri;
16 | import android.os.Bundle;
17 | import android.provider.MediaStore;
18 | import android.support.annotation.Nullable;
19 | import android.support.v4.app.FragmentActivity;
20 | import android.support.v7.widget.Toolbar;
21 | import android.view.MenuItem;
22 | import android.view.View;
23 | import android.widget.Toast;
24 |
25 | import com.wuwang.imagechooser.abslayer.IPhotoShoot;
26 | import com.wuwang.imagechooser.album.AlbumEntry;
27 | import com.wuwang.imagechooser.album.AlbumPopup;
28 | import com.wuwang.imagechooser.album.FolderFragment;
29 | import com.wuwang.imagechooser.album.ImageFolder;
30 | import com.wuwang.imagechooser.album.ImageInfo;
31 | import com.wuwang.utils.LogUtils;
32 |
33 | import java.io.File;
34 | import java.util.ArrayList;
35 | import java.util.List;
36 |
37 | /**
38 | * Description:
39 | */
40 | public class EntryActivity extends FragmentActivity implements IPhotoShoot{
41 |
42 | private AlbumEntry entry;
43 | private Toolbar toolbar;
44 | private MenuItem mSure;
45 |
46 | private String tackPicStr;
47 | private static final int REQ_TACK_PIC=0x15;
48 |
49 | @Override
50 | protected void onCreate(@Nullable Bundle savedInstanceState) {
51 | super.onCreate(savedInstanceState);
52 | setContentView(R.layout.image_chooser_activity_entry);
53 | setTitle();
54 | Rect outRect=new Rect();
55 | getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect);
56 | ChooserSetting.albumPopupHeight=(int) (outRect.height()*0.6f);
57 | // mAlbumNum= (TextView) findViewById(R.id.mAlbum);
58 | // mAlbumNum.setOnClickListener(new View.OnClickListener() {
59 | // @Override
60 | // public void onClick(View v) {
61 | // entry.showAlbumChooser();
62 | // }
63 | // });
64 | // findViewById(R.id.mSure).setOnClickListener(new View.OnClickListener() {
65 | // @Override
66 | // public void onClick(View v) {
67 | // entry.chooseFinish();
68 | // }
69 | // });
70 | FolderFragment m=new FolderFragment();
71 | m.setPhotoShoot(this);
72 | m.setSelectImgs(getIntent().getStringArrayListExtra(IcFinal.INTENT_EXIST_DATA));
73 | entry=new AlbumEntry(this, R.id.mEntry, m, new AlbumPopup(this,toolbar,m)){
74 | @Override
75 | public void onAlbumClick(ImageFolder folder) {
76 | super.onAlbumClick(folder);
77 | // toolbar.setTitle(folder.getName()+"("+folder.getCount()+")");
78 | }
79 |
80 | @Override
81 | public boolean onAdd(List data, ImageInfo info) {
82 | boolean a=super.onAdd(data, info);
83 | if(!a&&mSure!=null&&getMax()!=1){
84 | mSure.setEnabled(true);
85 | }
86 | return a;
87 | }
88 |
89 | @Override
90 | public boolean onCancel(List data, ImageInfo info) {
91 | boolean a=super.onCancel(data, info);
92 | if(!a&&mSure!=null&&data.size()<=1){
93 | mSure.setEnabled(false);
94 | }
95 | return a;
96 | }
97 | };
98 |
99 | if(entry.getMax()>1){
100 | mSure=toolbar.getMenu().getItem(1);
101 | mSure.setEnabled(false);
102 | }else{
103 | toolbar.getMenu().getItem(1).setVisible(false);
104 | }
105 |
106 | // IntentFilter filter=new IntentFilter(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
107 | // registerReceiver(receiver,filter);
108 | }
109 |
110 | BroadcastReceiver receiver=new BroadcastReceiver() {
111 | @Override
112 | public void onReceive(Context context, Intent intent) {
113 | entry.refreshData();
114 | }
115 | };
116 |
117 | private void setTitle(){
118 | toolbar= (Toolbar) findViewById(R.id.mTitle);
119 | toolbar.setBackgroundColor(ChooserSetting.TITLE_COLOR);
120 | toolbar.setTitle("图片选择");
121 | toolbar.setNavigationIcon(R.mipmap.image_chooser_back);
122 | toolbar.setContentInsetStartWithNavigation(0);
123 | toolbar.inflateMenu(R.menu.menu_album);
124 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
125 | @Override
126 | public void onClick(View v) {
127 | finish();
128 | }
129 | });
130 | toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
131 | @Override
132 | public boolean onMenuItemClick(MenuItem item) {
133 | int i = item.getItemId();
134 | if (i == R.id.mAlbum) {
135 | entry.showAlbumChooser();
136 | }else if(i==R.id.mSure){
137 | entry.chooseFinish();
138 | }
139 | return false;
140 | }
141 | });
142 | }
143 |
144 | @Override
145 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
146 | super.onActivityResult(requestCode, resultCode, data);
147 | LogUtils.e("result-"+resultCode+"/"+requestCode);
148 | entry.onActivityResult(requestCode, resultCode, data);
149 | if(resultCode== Activity.RESULT_OK){
150 | if(requestCode==REQ_TACK_PIC){
151 | //Bitmap bmp= (Bitmap) data.getExtras().get("data");
152 | //让拍摄的图片可以在相册目录中出现
153 |
154 | sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(tackPicStr))));
155 |
156 | if(entry.isCrop()){
157 | entry.crop(tackPicStr);
158 | }else{
159 | Intent intent=new Intent();
160 | ArrayList d=new ArrayList<>();
161 | d.add(tackPicStr);
162 | intent.putExtra(IcFinal.RESULT_DATA_IMG,d);
163 | setResult(Activity.RESULT_OK,intent);
164 | finish();
165 | }
166 | }
167 | }
168 | }
169 |
170 | @Override
171 | protected void onDestroy() {
172 | super.onDestroy();
173 | // unregisterReceiver(receiver);
174 | }
175 |
176 | @Override
177 | public void takePhoto() {
178 | Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
179 | //TODO 传入保存路径直接保存
180 | tackPicStr=ChooserSetting.tempFolder+"photo/"+System.currentTimeMillis()+".jpg";
181 | File folder=new File(ChooserSetting.tempFolder+"photo/");
182 | if(!folder.exists()){
183 | if(!folder.mkdirs()){
184 | Toast.makeText(this,"无法拍照",Toast.LENGTH_SHORT).show();
185 | return;
186 | }
187 | }
188 | File file = new File(tackPicStr);
189 | Uri imageUri = Uri.fromFile(file);
190 | intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
191 | startActivityForResult(intent,REQ_TACK_PIC);
192 | }
193 |
194 | }
195 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/IcFinal.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser;
2 |
3 | /**
4 | * Description:
5 | */
6 | public class IcFinal {
7 | public static final int NOW_COUNT=0;
8 |
9 | public static final String INTENT_MAX_IMG="ic_final_max_pic";
10 | public static final String INTENT_IS_CROP="ic_final_is_crop";
11 | public static final String INTENT_CROP_WIDTH="ic_final_crop_width";
12 | public static final String INTENT_CROP_HEIGHT="ic_final_crop_height";
13 | public static final String INTENT_CROP_SHAPE="ic_final_crop_shape";
14 | public static final String INTENT_CROP_DATA="ic_final_crop_data";
15 | public static final String INTENT_CROP_COVER="ic_final_crop_set";
16 | public static final String INTENT_CROP_PARAM="ic_final_crop_param";
17 | public static final String INTENT_EXIST_DATA="ic_final_exist_data";
18 |
19 | public static final String RESULT_DATA_IMG="ic_final_img";
20 |
21 | public static final String ACTION_ALBUM="android.intent.action.wuwang.album";
22 | public static final String ACTION_CROP="android.intent.action.wuwang.crop";
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/abslayer/IAlpha.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.abslayer;
2 |
3 | /**
4 | * Description:
5 | */
6 | public interface IAlpha {
7 |
8 | void setAlpha(int alpha);
9 | void show();
10 | void hide();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/abslayer/IImageClickListener.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.abslayer;
2 |
3 | import com.wuwang.imagechooser.album.ImageInfo;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Description:
9 | */
10 | public interface IImageClickListener {
11 |
12 | //返回值为是否阻止默认操作,默认会增加选中
13 | boolean onAdd(List data,ImageInfo info);
14 | //返回值为是否阻止默认操作,默认会取消选中
15 | boolean onCancel(List data,ImageInfo info);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/abslayer/IPhotoShoot.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.abslayer;
2 |
3 | /**
4 | * Created by wuwang on 2016/11/10
5 | */
6 |
7 | public interface IPhotoShoot {
8 |
9 | void takePhoto();
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/AbsAlbumEntry.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | /**
4 | * Description:
5 | */
6 | public abstract class AbsAlbumEntry {
7 |
8 | private int max=9;
9 | private int min=1;
10 | private boolean isCrop;
11 |
12 | public void setMax(int max){
13 | this.max=max;
14 | }
15 |
16 | public void setMin(int min){
17 | this.min=min;
18 | }
19 |
20 | public void setCrop(boolean isCrop){
21 | this.isCrop=isCrop;
22 | }
23 |
24 | public int getMax(){
25 | return this.max;
26 | }
27 |
28 | public int getMin(){
29 | return this.min;
30 | }
31 |
32 | public boolean isCrop(){
33 | return this.isCrop;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/AlbumAdapter.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.ImageView;
9 | import android.widget.TextView;
10 |
11 | import com.bumptech.glide.DrawableRequestBuilder;
12 | import com.bumptech.glide.Glide;
13 | import com.wuwang.imagechooser.ChooserSetting;
14 | import com.wuwang.imagechooser.R;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Locale;
18 |
19 | /**
20 | * Description:
21 | */
22 | public class AlbumAdapter extends BaseAdapter {
23 |
24 | private ArrayList data;
25 | private Context context;
26 |
27 | public AlbumAdapter(Context context, ArrayList data){
28 | this.context=context;
29 | this.data=data;
30 | }
31 |
32 | @Override
33 | public int getCount() {
34 | return data==null?0:data.size();
35 | }
36 |
37 | @Override
38 | public Object getItem(int position) {
39 | return data.get(position);
40 | }
41 |
42 | @Override
43 | public long getItemId(int position) {
44 | return position;
45 | }
46 |
47 | @Override
48 | public View getView(int position, View convertView, ViewGroup parent) {
49 | FolderHolder holder;
50 | if(convertView==null){
51 | convertView= LayoutInflater.from(context).inflate(R.layout.image_chooser_item_album,parent,false);
52 | holder=new FolderHolder(convertView);
53 | }else{
54 | holder= (FolderHolder) convertView.getTag();
55 | }
56 | holder.setData(data.get(position));
57 | return convertView;
58 | }
59 |
60 | private class FolderHolder{
61 | ImageView mImage;
62 | TextView mInfo;
63 | FolderHolder(View view){
64 | mImage= (ImageView) view.findViewById(R.id.mImage);
65 | mInfo= (TextView) view.findViewById(R.id.mInfo);
66 | view.setTag(this);
67 | }
68 |
69 | void setData(ImageFolder folder){
70 | //图片加载
71 | DrawableRequestBuilder r= Glide.with(context).load(folder.getFirstImagePath())
72 | .error(ChooserSetting.errorResId)
73 | .placeholder(ChooserSetting.placeResId);
74 | if(ChooserSetting.loadAnimateResId<=0){
75 | r.dontAnimate();
76 | }else{
77 | r.animate(ChooserSetting.loadAnimateResId);
78 | }
79 | r.into(mImage);
80 | mInfo.setText(String.format(Locale.CHINA,"%1$s(%2$d)",folder.getName(),folder.getCount()));
81 | }
82 |
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/AlbumEntry.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v4.app.FragmentActivity;
7 | import android.widget.Toast;
8 |
9 | import com.wuwang.imagechooser.ChooserSetting;
10 | import com.wuwang.imagechooser.IcFinal;
11 | import com.wuwang.imagechooser.abslayer.IImageClickListener;
12 | import com.wuwang.imagechooser.res.IChooseDrawable;
13 | import com.wuwang.utils.LogUtils;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * Description:
20 | */
21 | public class AlbumEntry extends AbsAlbumEntry implements AlbumTool.Callback,IAlbumClickListener,IImageClickListener {
22 |
23 | private FragmentActivity activity;
24 | private int containerId;
25 | private IFolderShower folderShower;
26 | private IAlbumShower albumShower;
27 |
28 | private Intent actIntent;
29 |
30 | private AlbumTool tool;
31 |
32 | private final int REQ_CROP=0x10;
33 |
34 | public AlbumEntry(FragmentActivity activity, int containerId, IFolderShower fShower, IAlbumShower aShower){
35 | this.activity=activity;
36 | this.containerId=containerId;
37 | this.folderShower=fShower;
38 | this.albumShower=aShower;
39 | init();
40 | }
41 |
42 | private void init(){
43 | activity.getSupportFragmentManager()
44 | .beginTransaction()
45 | .add(containerId,folderShower.getFragment())
46 | .commitAllowingStateLoss();
47 | albumShower.setAlbumClickListener(this);
48 | folderShower.setImageClickListener(this);
49 | tool=new AlbumTool(activity);
50 | tool.setCallback(this);
51 | tool.findAlbumsAsync();
52 |
53 | actIntent=activity.getIntent();
54 | setCrop(actIntent.getBooleanExtra(IcFinal.INTENT_IS_CROP,false));
55 | if(isCrop()){
56 | setMax(1);
57 | }else{
58 | setMax(actIntent.getIntExtra(IcFinal.INTENT_MAX_IMG,getMax()));
59 | }
60 | if(getMax()==1){
61 | this.folderShower.setChooseDrawable(null);
62 | }else{
63 | this.folderShower.setChooseDrawable(ChooserSetting.chooseDrawable);
64 | }
65 | }
66 |
67 | public void refreshData(){
68 | tool.findAlbumsAsync();
69 | }
70 |
71 | //显示相册选择器
72 | public void showAlbumChooser(){
73 | LogUtils.e("显示相册选择器");
74 | albumShower.show();
75 | }
76 |
77 | //关闭相册选择器
78 | public void cancelAlbumChooser(){
79 | albumShower.cancel();
80 | }
81 |
82 | @Override
83 | public void onFolderFinish(ImageFolder folder) {
84 | LogUtils.e("图片集《"+folder.getName()+"》查找完毕");
85 | folderShower.setFolder(folder);
86 | }
87 |
88 | @Override
89 | public void onAlbumFinish(ArrayList albums) {
90 | LogUtils.e("相册查找完毕,共"+albums.size()+"个相册");
91 | albumShower.setAlbums(albums);
92 | }
93 |
94 | @Override
95 | public void onAlbumClick(ImageFolder folder) {
96 | tool.findFolderAsync(folder);
97 | cancelAlbumChooser();
98 | }
99 |
100 | public void crop(String path){
101 | int shape=actIntent.getIntExtra(IcFinal.INTENT_CROP_SHAPE,0);
102 | Intent intent=new Intent(IcFinal.ACTION_CROP);
103 | intent.putExtra(IcFinal.INTENT_CROP_DATA,path);
104 | intent.putExtra(IcFinal.INTENT_CROP_SHAPE,shape);
105 | if(shape==0){
106 | intent.putExtra(IcFinal.INTENT_CROP_COVER,actIntent.getStringExtra(IcFinal.INTENT_CROP_COVER));
107 | intent.putExtra(IcFinal.INTENT_CROP_PARAM,actIntent.getIntExtra(IcFinal.INTENT_CROP_PARAM,0));
108 | }else{
109 | intent.putExtra(IcFinal.INTENT_CROP_WIDTH,actIntent.getIntExtra(IcFinal.INTENT_CROP_WIDTH,500));
110 | intent.putExtra(IcFinal.INTENT_CROP_HEIGHT,actIntent.getIntExtra(IcFinal.INTENT_CROP_HEIGHT,500));
111 | }
112 | activity.startActivityForResult(intent,REQ_CROP);
113 | }
114 |
115 | @Override
116 | public boolean onAdd(List data, ImageInfo info) {
117 | if(getMax()==1){
118 | if(isCrop()){
119 | crop(info.path);
120 | }else{
121 | Intent intent=new Intent();
122 | ArrayList result=new ArrayList<>();
123 | result.add(info.path);
124 | intent.putExtra(IcFinal.RESULT_DATA_IMG,result);
125 | activity.setResult(Activity.RESULT_OK,intent);
126 | activity.finish();
127 | }
128 | return true;
129 | }else{
130 | if(data.size()==getMax()){
131 | Toast.makeText(activity,"无法继续选中",Toast.LENGTH_SHORT).show();
132 | return true;
133 | }
134 | }
135 | return false;
136 | }
137 |
138 | public void chooseFinish(){
139 | List res=folderShower.getSelectedImages();
140 | int resSize=res.size();
141 | if(resSize>0){
142 | ArrayList data=new ArrayList<>(resSize);
143 | for (int i=0;i data){
159 | if(data.size()>0){
160 | Intent intent=new Intent();
161 | intent.putExtra(IcFinal.RESULT_DATA_IMG,data);
162 | activity.setResult(Activity.RESULT_OK,intent);
163 | activity.finish();
164 | }
165 | }
166 |
167 | private void chooseFinish(String data){
168 | if(data!=null){
169 | ArrayList c=new ArrayList<>(1);
170 | c.add(data);
171 | chooseFinish(c);
172 | }
173 | }
174 |
175 | @Override
176 | public boolean onCancel(List data, ImageInfo info) {
177 | return false;
178 | }
179 |
180 | public interface IAlbumShower{
181 | void setAlbums(ArrayList albums);
182 | void setAlbumClickListener(IAlbumClickListener listener);
183 | void show();
184 | void cancel();
185 | }
186 |
187 | public interface IFolderShower{
188 | void setChooseDrawable(IChooseDrawable drawable);
189 | void setFolder(ImageFolder folder);
190 | void setImageClickListener(IImageClickListener listener);
191 | List getSelectedImages();
192 | Fragment getFragment();
193 | }
194 |
195 | }
196 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/AlbumPopup.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | import android.app.Activity;
4 | import android.graphics.drawable.ColorDrawable;
5 | import android.view.LayoutInflater;
6 | import android.view.MotionEvent;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.AdapterView;
10 | import android.widget.ListView;
11 | import android.widget.PopupWindow;
12 |
13 | import com.wuwang.imagechooser.ChooserSetting;
14 | import com.wuwang.imagechooser.R;
15 | import com.wuwang.imagechooser.abslayer.IAlpha;
16 |
17 | import java.util.ArrayList;
18 |
19 | /**
20 | * Description:
21 | */
22 | public class AlbumPopup implements AlbumEntry.IAlbumShower{
23 |
24 | private Activity context;
25 | private PopupWindow window;
26 | private View contentView;
27 | private ListView mList;
28 | private AlbumAdapter adapter;
29 | private ArrayList data;
30 | private IAlbumClickListener listener;
31 | private IAlpha alpha;
32 | private View anchor;
33 |
34 | public AlbumPopup(Activity context, View anchor, IAlpha iAlpha){
35 | this.context=context;
36 | this.anchor=anchor;
37 | this.alpha=iAlpha;
38 | createPopup();
39 | }
40 |
41 | private void createPopup(){
42 | contentView= LayoutInflater.from(context).inflate(R.layout.image_chooser_fragment_folder,null);
43 | window=new PopupWindow(contentView, ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
44 | window.setBackgroundDrawable(new ColorDrawable(0));
45 | window.setTouchable(true);
46 | window.setOutsideTouchable(true);
47 | window.setFocusable(true);
48 | window.setOnDismissListener(new PopupWindow.OnDismissListener() {
49 | @Override
50 | public void onDismiss() {
51 | alpha.hide();
52 | }
53 | });
54 | window.setTouchInterceptor(new View.OnTouchListener() {
55 | @Override
56 | public boolean onTouch(View v, MotionEvent event) {
57 | if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
58 | window.dismiss();
59 | return true;
60 | }
61 | return false;
62 | }
63 | });
64 | mList= (ListView) contentView.findViewById(R.id.mList);
65 | adapter=new AlbumAdapter(context,data=new ArrayList<>());
66 | mList.setAdapter(adapter);
67 | mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
68 | @Override
69 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
70 | listener.onAlbumClick(data.get(position));
71 | }
72 | });
73 | contentView.setOnClickListener(new View.OnClickListener() {
74 | @Override
75 | public void onClick(View v) {
76 | window.dismiss();
77 | }
78 | });
79 | }
80 |
81 | @Override
82 | public void setAlbums(ArrayList albums) {
83 | data.clear();
84 | data.addAll(albums);
85 | adapter.notifyDataSetChanged();
86 | mList.pointToPosition(0,0);
87 | }
88 |
89 | @Override
90 | public void setAlbumClickListener(IAlbumClickListener listener) {
91 | this.listener=listener;
92 | }
93 |
94 | @Override
95 | public void show() {
96 | alpha.show();
97 | mList.getLayoutParams().height= ChooserSetting.albumPopupHeight;
98 | mList.setLayoutParams(mList.getLayoutParams());
99 | window.showAsDropDown(anchor);
100 | }
101 |
102 | @Override
103 | public void cancel() {
104 | window.dismiss();
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/AlbumTool.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | import android.content.ContentResolver;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.graphics.ImageFormat;
7 | import android.os.Handler;
8 | import android.os.Looper;
9 | import android.os.Message;
10 | import android.provider.MediaStore;
11 |
12 | import com.wuwang.imagechooser.ChooserSetting;
13 |
14 | import java.io.File;
15 | import java.io.FilenameFilter;
16 | import java.util.ArrayList;
17 | import java.util.concurrent.Semaphore;
18 |
19 | /**
20 | * Description:
21 | */
22 | public class AlbumTool {
23 |
24 | private Handler handler;
25 | //private Semaphore semaphore;
26 | private Callback callback;
27 | private Context context;
28 |
29 | private final int TYPE_FOLDER=1;
30 | private final int TYPE_ALBUM=2;
31 |
32 | public AlbumTool(Context context){
33 | this.context=context;
34 | handler=new Handler(Looper.getMainLooper()){
35 | @Override
36 | public void handleMessage(Message msg) {
37 | if(callback!=null){
38 | switch (msg.what){
39 | case TYPE_FOLDER:
40 | callback.onFolderFinish((ImageFolder) msg.obj);
41 | break;
42 | case TYPE_ALBUM:
43 | callback.onAlbumFinish((ArrayList) msg.obj);
44 | break;
45 | }
46 | }
47 | super.handleMessage(msg);
48 | }
49 | };
50 | }
51 |
52 | public void setCallback(Callback callback){
53 | this.callback=callback;
54 | }
55 |
56 | public void findAlbumsAsync(){
57 | new Thread(new Runnable() {
58 | @Override
59 | public void run() {
60 | getAlbums(context);
61 | }
62 | }).start();
63 | }
64 |
65 | public void findFolderAsync(final ImageFolder folder){
66 | new Thread(new Runnable() {
67 | @Override
68 | public void run() {
69 | getFolder(context,folder);
70 | }
71 | }).start();
72 | }
73 |
74 | //获取所有图片集
75 | private ArrayList getAlbums(Context context) {
76 | ArrayList albums=new ArrayList<>();
77 | albums.add(getNewestPhotos(context));
78 | //利用ContentResolver查询数据库,找出所有包含图片的文件夹,保存到相册列表中
79 | ContentResolver resolver = context.getContentResolver();
80 | Cursor cursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
81 | new String[]{
82 | MediaStore.Images.Media.DATA,
83 | MediaStore.Images.ImageColumns.BUCKET_ID,
84 | MediaStore.Images.Media.DATE_MODIFIED,
85 | "count(*) as count"
86 | },
87 | MediaStore.Images.Media.MIME_TYPE + "=? or " +
88 | MediaStore.Images.Media.MIME_TYPE + "=? or " +
89 | MediaStore.Images.Media.MIME_TYPE + "=?) " +
90 | "group by (" + MediaStore.Images.ImageColumns.BUCKET_ID,
91 | new String[]{"image/jpeg", "image/png", "image/jpg"},
92 | MediaStore.Images.Media.DATE_MODIFIED + " desc");
93 | if (cursor != null) {
94 | while (cursor.moveToNext()) {
95 | final File file = new File(cursor.getString(0));
96 | ImageFolder imageFolder = new ImageFolder();
97 | imageFolder.setDir(file.getParent());
98 | imageFolder.setId(cursor.getString(1));
99 | imageFolder.setFirstImagePath(cursor.getString(0));
100 | String[] all=file.getParentFile().list(new FilenameFilter() {
101 |
102 | private boolean e(String filename,String ends){
103 | return filename.toLowerCase().endsWith(ends);
104 | }
105 |
106 | @Override
107 | public boolean accept(File dir, String filename) {
108 | return e(filename,".png") || e(filename,".jpg") || e(filename,"jpeg");
109 | }
110 | });
111 | if(all!=null&&all.length>0){
112 | imageFolder.setCount(all.length);
113 | albums.add(imageFolder);
114 | }
115 | }
116 | cursor.close();
117 | }
118 | sendMessage(TYPE_ALBUM,albums);
119 | return albums;
120 | }
121 |
122 | //获取《最新图片》集
123 | private ImageFolder getNewestPhotos(Context context) {
124 | ImageFolder newestFolder=new ImageFolder();
125 | newestFolder.setName(ChooserSetting.newestAlbumName);
126 | ArrayList imageBeans = new ArrayList<>();
127 | ContentResolver resolver = context.getContentResolver();
128 | Cursor cursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
129 | new String[]{
130 | MediaStore.Images.Media.DATA,
131 | MediaStore.Images.Media.DISPLAY_NAME,
132 | MediaStore.Images.Media.DATE_MODIFIED,
133 | },
134 | MediaStore.Images.Media.MIME_TYPE + "=? or "
135 | + MediaStore.Images.Media.MIME_TYPE + "=? or "
136 | + MediaStore.Images.Media.MIME_TYPE + "=?",
137 | new String[]{"image/jpeg", "image/png", "image/jpg"},
138 | MediaStore.Images.Media.DATE_MODIFIED + " desc"
139 | + (ChooserSetting.newestAlbumSize < 0 ? ""
140 | : (" limit " + ChooserSetting.newestAlbumSize)));
141 | if (cursor != null){
142 | while (cursor.moveToNext()) {
143 | ImageInfo info=new ImageInfo();
144 | info.path=cursor.getString(0);
145 | info.displayName=cursor.getString(1);
146 | info.time=cursor.getLong(2);
147 | imageBeans.add(info);
148 | }
149 | cursor.close();
150 | newestFolder.setFirstImagePath(imageBeans.get(0).path);
151 | newestFolder.setDatas(imageBeans);
152 | newestFolder.setCount(imageBeans.size());
153 | }
154 | sendMessage(TYPE_FOLDER,newestFolder);
155 | return newestFolder;
156 | }
157 |
158 | //获取具体图片集,确保图片数据已被查询
159 | private ImageFolder getFolder(Context context,ImageFolder folder) {
160 | ContentResolver resolver = context.getContentResolver();
161 | Cursor cursor;
162 | if(folder!=null&&folder.getDatas()!=null&&folder.getDatas().size()>0){
163 | sendMessage(TYPE_FOLDER,folder);
164 | return folder;
165 | }
166 | if (folder == null) {
167 | return getNewestPhotos(context);
168 | } else {
169 | cursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
170 | new String[]{
171 | MediaStore.Images.Media.DATA,
172 | MediaStore.Images.Media.DISPLAY_NAME,
173 | MediaStore.Images.Media.DATE_MODIFIED
174 | },
175 | MediaStore.Images.ImageColumns.BUCKET_ID + "=? and (" +
176 | MediaStore.Images.Media.MIME_TYPE + "=? or "
177 | + MediaStore.Images.Media.MIME_TYPE + "=? or "
178 | + MediaStore.Images.Media.MIME_TYPE + "=?) ",
179 | new String[]{folder.getId(), "image/jpeg", "image/png", "image/jpg"},
180 | MediaStore.Images.Media.DATE_MODIFIED + " desc");
181 | }
182 | ArrayList datas=new ArrayList<>();
183 | folder.setDatas(datas);
184 | if (cursor != null){
185 | while (cursor.moveToNext()) {
186 | ImageInfo info=new ImageInfo();
187 | info.path=cursor.getString(0);
188 | info.displayName=cursor.getString(1);
189 | info.time=cursor.getLong(2);
190 | datas.add(info);
191 | }
192 | cursor.close();
193 | }
194 | folder.setCount(datas.size());
195 | sendMessage(TYPE_FOLDER,folder);
196 | return folder;
197 | }
198 |
199 | private void sendMessage(int what,Object obj){
200 | Message msg=new Message();
201 | msg.what=what;
202 | msg.obj=obj;
203 | handler.sendMessage(msg);
204 | }
205 |
206 | public interface Callback{
207 |
208 | //文件夹查找完毕
209 | void onFolderFinish(ImageFolder folder);
210 | //成功搜索出所有的图片集
211 | void onAlbumFinish(ArrayList albums);
212 |
213 | }
214 |
215 | }
216 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/AlbumVar.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | /**
4 | * Description:
5 | */
6 | public class AlbumVar {
7 |
8 | private static AlbumVar instance;
9 | private int goal;
10 | private int now;
11 |
12 | private AlbumVar(){
13 |
14 | }
15 |
16 | public static AlbumVar getInstance(){
17 | if(null==instance){
18 | synchronized (AlbumVar.class){
19 | if(null==instance){
20 | instance=new AlbumVar();
21 | }
22 | }
23 | }
24 | return instance;
25 | }
26 |
27 | public void init(int goal,int now){
28 | this.goal=goal;
29 | this.now=now;
30 | }
31 |
32 | public void nowAdd(){
33 |
34 | }
35 |
36 | public void nowDec(){
37 |
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/FolderAdapter.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | import android.graphics.drawable.Drawable;
4 | import android.support.v4.app.Fragment;
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 |
11 | import com.bumptech.glide.DrawableRequestBuilder;
12 | import com.bumptech.glide.Glide;
13 | import com.wuwang.imagechooser.ChooserSetting;
14 | import com.wuwang.imagechooser.R;
15 | import com.wuwang.imagechooser.res.IChooseDrawable;
16 |
17 | import java.util.ArrayList;
18 |
19 | /**
20 | * Description:
21 | */
22 | public class FolderAdapter extends BaseAdapter {
23 |
24 | private IChooseDrawable drawable;
25 | private Fragment fragment;
26 | public ArrayList data;
27 |
28 | private final int TYPE_DEFAULT=0;
29 | private final int TYPE_TAKEPIC=1;
30 |
31 | private boolean isTackPhoto=ChooserSetting.takePhotoType!=ChooserSetting.TP_NONE;
32 |
33 | public FolderAdapter(Fragment fragment, ArrayList data, IChooseDrawable drawable){
34 | this.fragment=fragment;
35 | this.data=data;
36 | this.drawable=drawable;
37 | }
38 |
39 | public void setChooseDrawable(IChooseDrawable drawable){
40 | this.drawable=drawable;
41 | }
42 |
43 | @Override
44 | public int getCount() {
45 | return data==null?0:data.size();
46 | }
47 |
48 | @Override
49 | public Object getItem(int position) {
50 | return data.get(position);
51 | }
52 |
53 | @Override
54 | public long getItemId(int position) {
55 | return position;
56 | }
57 |
58 | @Override
59 | public int getItemViewType(int position) {
60 | if(position==0&&isTackPhoto){
61 | return TYPE_TAKEPIC;
62 | }
63 | return TYPE_DEFAULT;
64 | }
65 |
66 | public boolean isTakePhoto(int position){
67 | return getItemViewType(position)==TYPE_TAKEPIC;
68 | }
69 |
70 | @Override
71 | public View getView(int position, View convertView, ViewGroup parent) {
72 | if(getItemViewType(position)==TYPE_TAKEPIC){
73 | convertView= LayoutInflater.from(fragment.getContext()).inflate(R.layout.image_chooser_item_camera,parent,false);
74 | if(ChooserSetting.tackPhotoIcon>0){
75 | ((ImageView)convertView).setImageResource(ChooserSetting.tackPhotoIcon);
76 | }
77 | }else{
78 | ImageHolder holder;
79 | if(convertView==null||convertView.getTag()==null){
80 | convertView= LayoutInflater.from(fragment.getContext()).inflate(R.layout.image_chooser_item_image,parent,false);
81 | holder=new ImageHolder(convertView);
82 | }else{
83 | holder= (ImageHolder) convertView.getTag();
84 | }
85 | holder.setData(data.get(position));
86 | }
87 | return convertView;
88 | }
89 |
90 | private class ImageHolder{
91 | ImageView mImage;
92 | View mFlag;
93 | ImageHolder(View convertView){
94 | mImage= (ImageView) convertView.findViewById(R.id.mImage);
95 | mFlag=convertView.findViewById(R.id.mFlag);
96 | convertView.setTag(this);
97 | }
98 |
99 | void setData(ImageInfo info){
100 | //图片加载
101 | DrawableRequestBuilder r=Glide.with(fragment).load(info.path)
102 | .error(ChooserSetting.errorResId)
103 | .placeholder(ChooserSetting.placeResId);
104 | if(ChooserSetting.loadAnimateResId<=0){
105 | r.dontAnimate();
106 | }else{
107 | r.animate(ChooserSetting.loadAnimateResId);
108 | }
109 | r.into(mImage);
110 |
111 | //状态加载
112 | if(drawable!=null){
113 | if(info.state<=0){
114 | mImage.setColorFilter(ChooserSetting.unChooseFilter);
115 | }else{
116 | mImage.setColorFilter(ChooserSetting.chooseFilter);
117 | }
118 | setBg(mFlag,drawable.get(info.state));
119 | }
120 | }
121 |
122 | private void setBg(View v, Drawable drawable){
123 | v.setBackgroundDrawable(null);
124 | v.setBackgroundDrawable(drawable);
125 | }
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/FolderFragment.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.Bitmap;
6 | import android.net.Uri;
7 | import android.os.Bundle;
8 | import android.os.Environment;
9 | import android.provider.MediaStore;
10 | import android.support.annotation.Nullable;
11 | import android.support.v4.app.Fragment;
12 | import android.support.v4.os.EnvironmentCompat;
13 | import android.util.Log;
14 | import android.view.LayoutInflater;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.widget.AdapterView;
18 | import android.widget.GridView;
19 |
20 | import com.wuwang.imagechooser.ChooserSetting;
21 | import com.wuwang.imagechooser.IcFinal;
22 | import com.wuwang.imagechooser.R;
23 | import com.wuwang.imagechooser.abslayer.IAlpha;
24 | import com.wuwang.imagechooser.abslayer.IImageClickListener;
25 | import com.wuwang.imagechooser.abslayer.IPhotoShoot;
26 | import com.wuwang.imagechooser.res.IChooseDrawable;
27 | import com.wuwang.utils.LogUtils;
28 |
29 | import java.io.File;
30 | import java.util.ArrayList;
31 | import java.util.List;
32 | import java.util.Vector;
33 |
34 | /**
35 | * Description:
36 | */
37 | public class FolderFragment extends Fragment implements AlbumEntry.IFolderShower,IAlpha {
38 |
39 | private ViewGroup rootView;
40 | private GridView mGrid;
41 | private View mCover;
42 | private FolderAdapter adapter;
43 | private ArrayList data=new ArrayList<>();
44 | private Vector selectImgs;
45 | private IImageClickListener listener;
46 | private IChooseDrawable drawable;
47 | private IPhotoShoot photoShoot;
48 |
49 | private List initSelect;
50 |
51 | @Nullable
52 | @Override
53 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
54 | if(rootView==null){
55 | rootView= (ViewGroup) LayoutInflater.from(getContext()).inflate(R.layout.image_chooser_fragment_album,container,false);
56 | initView();
57 | initData();
58 | }
59 | return rootView;
60 | }
61 |
62 | private void initView(){
63 | mGrid= (GridView) rootView.findViewById(R.id.mAlbum);
64 | mGrid.setNumColumns(ChooserSetting.NUM_COLUMNS);
65 | mGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
66 | @Override
67 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
68 | if(adapter.isTakePhoto(position)){
69 | if(photoShoot!=null){
70 | photoShoot.takePhoto();
71 | }
72 | }else{
73 | ImageInfo info=data.get(position);
74 | if(info.state>0){ //点击已经选择过得
75 | boolean a=listener.onCancel(selectImgs,info);
76 | if(!a){
77 | info.state=0;
78 | selectImgs.removeElement(info);
79 | int size=selectImgs.size();
80 | for(int i=0;i data){
103 | initSelect=data;
104 | }
105 |
106 | private void initData(){
107 | adapter=new FolderAdapter(this,data,drawable);
108 | mGrid.setAdapter(adapter);
109 | selectImgs=new Vector<>();
110 | if(initSelect!=null){
111 | int size=initSelect.size();
112 | for (int i=0;i getSelectedImages() {
169 | return selectImgs;
170 | }
171 |
172 | @Override
173 | public Fragment getFragment() {
174 | return this;
175 | }
176 |
177 | @Override
178 | public void setAlpha(int alpha) {
179 | mCover.setBackgroundColor(alpha);
180 | }
181 |
182 | @Override
183 | public void show() {
184 | mCover.setVisibility(View.VISIBLE);
185 | }
186 |
187 | @Override
188 | public void hide() {
189 | mCover.setVisibility(View.GONE);
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/IAlbumClickListener.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | /**
4 | * Description:
5 | */
6 | public interface IAlbumClickListener {
7 |
8 | void onAlbumClick(ImageFolder folder);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/ImageFolder.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | import java.util.ArrayList;
4 |
5 | /**
6 | * Description:
7 | */
8 | public class ImageFolder {
9 |
10 | private String dir; //文件路径
11 | private String firstImagePath; //第一张图片的路径
12 | private String name; //文件夹显示名称
13 | private int count; //图片的数量
14 | private String id; //文件夹在数据库中的id
15 | private ArrayList datas; //文件夹中图片
16 |
17 | public void setId(String id) {
18 | this.id = id;
19 | }
20 |
21 | public String getId() {
22 | return id;
23 | }
24 |
25 | public String getDir() {
26 | return dir;
27 | }
28 |
29 | public void setDir(String dir) {
30 | this.dir = dir;
31 | int lastIndexOf = this.dir.lastIndexOf("/");
32 | this.name = this.dir.substring(lastIndexOf + 1);
33 | }
34 |
35 | public void setName(String name) {
36 | this.name = name;
37 | }
38 |
39 | public String getFirstImagePath() {
40 | return firstImagePath;
41 | }
42 |
43 | public void setFirstImagePath(String firstImagePath) {
44 | this.firstImagePath = firstImagePath;
45 | }
46 |
47 | public String getName() {
48 | return name;
49 | }
50 |
51 | public int getCount() {
52 | return count;
53 | }
54 |
55 | public void setCount(int count) {
56 | this.count = count;
57 | }
58 |
59 | public void setDatas(ArrayList datas){
60 | this.datas=datas;
61 | }
62 |
63 | public ArrayList getDatas(){
64 | return datas;
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/album/ImageInfo.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.album;
2 |
3 | /**
4 | * Description:
5 | */
6 | public class ImageInfo {
7 |
8 | public int state=0;
9 | public String path;
10 | public long time;
11 | public String displayName;
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/crop/ACropCoverDrawable.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.crop;
2 |
3 | import android.graphics.drawable.Drawable;
4 |
5 | /**
6 | * Description:
7 | */
8 | public abstract class ACropCoverDrawable extends Drawable implements CropPath{
9 |
10 | public ACropCoverDrawable(int control){
11 |
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/crop/CropActivity.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.crop;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.FragmentActivity;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.MenuItem;
10 | import android.view.View;
11 |
12 | import com.wuwang.imagechooser.ChooserSetting;
13 | import com.wuwang.imagechooser.IcFinal;
14 | import com.wuwang.imagechooser.R;
15 | import com.wuwang.utils.LogUtils;
16 |
17 | import java.io.IOException;
18 |
19 | /**
20 | * Description:
21 | */
22 | public class CropActivity extends FragmentActivity {
23 |
24 | private Toolbar toolbar;
25 | private CropFragment cropFragment;
26 | private int shape;
27 | private int width;
28 | private int height;
29 | private String drawableName;
30 | private int drawableParam;
31 |
32 | @Override
33 | protected void onCreate(@Nullable Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.image_chooser_activity_crop);
36 | setTitle();
37 | initByIntent();
38 | }
39 |
40 | public void initByIntent(){
41 | Intent intent=getIntent();
42 | String data=intent.getStringExtra(IcFinal.INTENT_CROP_DATA);
43 | shape=intent.getIntExtra(IcFinal.INTENT_CROP_SHAPE,0);
44 | if(shape==0){
45 | drawableName= intent.getStringExtra(IcFinal.INTENT_CROP_COVER);
46 | drawableParam=intent.getIntExtra(IcFinal.INTENT_CROP_PARAM,0);
47 | cropFragment=CropFragment.newFragment(data,drawableName,drawableParam);
48 | }else if(shape==CropPath.SHAPE_CIRCLE||shape==CropPath.SHAPE_RECT){
49 | width=intent.getIntExtra(IcFinal.INTENT_CROP_WIDTH,400);
50 | height=intent.getIntExtra(IcFinal.INTENT_CROP_HEIGHT,400);
51 | cropFragment=CropFragment.newFragment(data,shape,width,height);
52 | }
53 | cropFragment.setOnReadyRunnable(new Runnable() {
54 | @Override
55 | public void run() {
56 | toolbar.getMenu().getItem(0).setEnabled(true);
57 | }
58 | });
59 | getSupportFragmentManager().beginTransaction()
60 | .add(R.id.mContainer,cropFragment)
61 | .commit();
62 | }
63 |
64 | public void setTitle(){
65 | toolbar= (Toolbar) findViewById(R.id.mTitle);
66 | toolbar.setBackgroundColor(ChooserSetting.TITLE_COLOR);
67 | toolbar.setTitle("裁剪图片");
68 | toolbar.setNavigationIcon(R.mipmap.image_chooser_back);
69 | toolbar.setContentInsetStartWithNavigation(0);
70 | toolbar.inflateMenu(R.menu.menu_crop);
71 | toolbar.getMenu().getItem(0).setEnabled(false);
72 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
73 | @Override
74 | public void onClick(View v) {
75 | finish();
76 | }
77 | });
78 | toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
79 | @Override
80 | public boolean onMenuItemClick(MenuItem item) {
81 | if(item.getItemId()==R.id.mSure){
82 | String file=getFilesDir().getAbsolutePath()+"/temp.jpg";
83 | try {
84 | cropFragment.crop(file);
85 | Intent intent=new Intent();
86 | intent.putExtra(IcFinal.RESULT_DATA_IMG,file);
87 | setResult(RESULT_OK,intent);
88 | finish();
89 | } catch (IOException e) {
90 | e.printStackTrace();
91 | }
92 | }
93 | return false;
94 | }
95 | });
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/crop/CropCoverDrawable.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.crop;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.ColorFilter;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.graphics.PixelFormat;
9 | import android.graphics.PorterDuff;
10 | import android.graphics.PorterDuffXfermode;
11 | import android.graphics.Rect;
12 | import android.graphics.drawable.Drawable;
13 | import android.os.Build;
14 | import android.support.annotation.NonNull;
15 |
16 | /**
17 | * Created by wuwang on 2016/10/25
18 | */
19 |
20 | public class CropCoverDrawable extends ACropCoverDrawable {
21 |
22 | private Paint paint;
23 | private Rect rect;
24 | private int width,height;
25 | private int shape;
26 | private Path cropPath;
27 |
28 | public CropCoverDrawable(int width,int height){
29 | super(0);
30 | this.width=width;
31 | this.height=height;
32 | paintInit();
33 | }
34 |
35 | public CropCoverDrawable(int shape,int x,int y,int width,int height){
36 | super(0);
37 | this.shape=shape;
38 | rect=new Rect(x-width/2,y-height/2,x+width/2,y+height/2);
39 | paintInit();
40 | }
41 |
42 | private void paintInit(){
43 | paint=new Paint();
44 | paint.setAntiAlias(true);
45 | paint.setColor(0x88000000);
46 | }
47 |
48 | public CropCoverDrawable setShape(int shape){
49 | this.shape=shape;
50 | return this;
51 | }
52 |
53 | public void setShadowColor(int color){
54 | paint.setColor(color);
55 | }
56 |
57 | @Override
58 | public void draw(@NonNull Canvas canvas) {
59 | int cWidth=canvas.getWidth();
60 | int cHeight=canvas.getHeight();
61 | if(rect==null){
62 | rect=new Rect(cWidth/2-width/2,cHeight/2-height/2,cWidth/2+width/2,cHeight/2+height/2);
63 | }
64 | canvas.drawColor(Color.TRANSPARENT);
65 | Path path=new Path();
66 | path.addRect(0,0,cWidth,cHeight, Path.Direction.CW);
67 | cropPath=new Path();
68 | if(shape==SHAPE_RECT){
69 | cropPath.addRect(rect.left,rect.top,rect.right,rect.bottom, Path.Direction.CW);
70 | }else if(shape==SHAPE_CIRCLE){
71 | cropPath.addCircle(rect.centerX(),rect.centerY(),rect.width()/2, Path.Direction.CW);
72 | }
73 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
74 | path.op(cropPath, Path.Op.DIFFERENCE); //可以抗锯齿
75 | canvas.drawPath(path,paint);
76 | }else{
77 | //此方法可以去掉锯齿
78 | //在这里saveLayer然后restoreToCount的操作不能少,否则不会得到想要的效果
79 | int layerId = canvas.saveLayer(0, 0, cWidth, cHeight, null, Canvas.ALL_SAVE_FLAG);
80 | canvas.drawPath(path,paint);
81 | //已经绘制的可以看做为目标图
82 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
83 | canvas.drawPath(cropPath,paint);
84 | paint.setXfermode(null);
85 | canvas.restoreToCount(layerId);
86 | //裁剪的方式会有锯齿,没找到方法去掉锯齿
87 | //canvas.clipPath(opPath, Region.Op.DIFFERENCE);
88 | //canvas.drawRect(0,0,cWidth,cHeight,paint);
89 | }
90 | }
91 |
92 | @Override
93 | public void setAlpha(int alpha) {
94 | paint.setAlpha(alpha);
95 | }
96 |
97 | @Override
98 | public void setColorFilter(ColorFilter colorFilter) {
99 | paint.setColorFilter(colorFilter);
100 | }
101 |
102 | @Override
103 | public int getOpacity() {
104 | return PixelFormat.TRANSPARENT;
105 | }
106 |
107 | @Override
108 | public Rect limit() {
109 | return rect;
110 | }
111 |
112 | @Override
113 | public Path path() {
114 | return cropPath;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/crop/CropFragment.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.crop;
2 |
3 | import android.graphics.Bitmap;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ImageView;
11 |
12 | import com.bumptech.glide.Glide;
13 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
14 | import com.bumptech.glide.load.resource.drawable.GlideDrawable;
15 | import com.bumptech.glide.request.RequestListener;
16 | import com.bumptech.glide.request.animation.GlideAnimation;
17 | import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
18 | import com.bumptech.glide.request.target.Target;
19 | import com.wuwang.imagechooser.R;
20 |
21 | import java.io.File;
22 | import java.io.IOException;
23 | import java.lang.reflect.Constructor;
24 |
25 | /**
26 | * Created by wuwang on 2016/11/4
27 | */
28 |
29 | public class CropFragment extends Fragment {
30 |
31 | private View rootView;
32 | private ImageView mImage;
33 | private View mCover;
34 |
35 | private ACropCoverDrawable bg;
36 | private CropHelper helper;
37 | private Runnable ready;
38 |
39 | public static CropFragment newFragment(String path,int shape,int width,int height){
40 | CropFragment f=new CropFragment();
41 | Bundle b=new Bundle();
42 | b.putString("path",path);
43 | b.putInt("shape",shape);
44 | b.putInt("width",width);
45 | b.putInt("height",height);
46 | f.setArguments(b);
47 | return f;
48 | }
49 |
50 | public static CropFragment newFragment(String path,String dName,int dParam){
51 | CropFragment f=new CropFragment();
52 | Bundle b=new Bundle();
53 | b.putString("path",path);
54 | // b.putSerializable("cover",cover);
55 | b.putString("name",dName);
56 | b.putInt("param",dParam);
57 | f.setArguments(b);
58 | return f;
59 | }
60 |
61 | @Nullable
62 | @Override
63 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
64 | if(rootView==null){
65 | rootView=inflater.inflate(R.layout.image_chooser_fragment_crop,container,false);
66 | mImage= (ImageView) rootView.findViewById(R.id.mImage);
67 | mCover=rootView.findViewById(R.id.mCover);
68 | initData();
69 | }
70 | return rootView;
71 | }
72 |
73 | private void initData(){
74 | Bundle b=getArguments();
75 | String src=b.getString("path");
76 | if(src!=null){
77 | Glide.with(this).load(src).skipMemoryCache(true)
78 | .diskCacheStrategy(DiskCacheStrategy.NONE)
79 | .dontTransform()
80 | .dontAnimate()
81 | .into(new GlideDrawableImageViewTarget(mImage){
82 | @Override
83 | public void onResourceReady(GlideDrawable resource, GlideAnimation super GlideDrawable> animation) {
84 | super.onResourceReady(resource, animation);
85 | if(ready!=null){
86 | ready.run();
87 | }
88 | }
89 | });
90 | }
91 | if(b.getInt("shape",-1)!=-1){
92 | bg=new CropCoverDrawable(b.getInt("width",500),b.getInt("height",500))
93 | .setShape(b.getInt("shape"));
94 | }else{
95 | try {
96 | Class clazz= (Class) Class.forName(b.getString("name"));
97 | Constructor constructor=clazz.getConstructor(int.class);
98 | bg= constructor.newInstance(b.getInt("param"));
99 | } catch (Exception e) {
100 | throw new RuntimeException("Please set INTENT_CROP_COVER with a object name extends ACropCoverDrawable",e);
101 | }
102 | }
103 | mCover.setBackgroundDrawable(bg);
104 | helper=new CropHelper().attractTo(mImage);
105 | helper.setCropPath(bg);
106 | }
107 |
108 | public void setOnReadyRunnable(Runnable runnable){
109 | this.ready=runnable;
110 | }
111 |
112 | public void crop(String path) throws IOException {
113 | helper.cropAndSave(path);
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/imagechooser/crop/CropHelper.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser.crop;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Matrix;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.graphics.PointF;
10 | import android.graphics.PorterDuff;
11 | import android.graphics.PorterDuffXfermode;
12 | import android.graphics.Rect;
13 | import android.os.Build;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.view.ViewTreeObserver;
17 | import android.widget.ImageView;
18 |
19 | import java.io.File;
20 | import java.io.FileOutputStream;
21 | import java.io.IOException;
22 |
23 |
24 | /**
25 | * Description:
26 | */
27 | public class CropHelper implements View.OnTouchListener {
28 |
29 | private static final String TAG = "Touch";
30 |
31 | private Matrix matrix = new Matrix();
32 | private Matrix savedMatrix = new Matrix();
33 | private Rect limit;
34 |
35 | // We can be in one of these 3 states
36 | private final int NONE = 0;
37 | private final int DRAG = 1;
38 | private final int ZOOM = 2;
39 | private int mode = NONE;
40 |
41 | private PointF start = new PointF();
42 | private PointF mid = new PointF();
43 | private float oldDist = 1f;
44 | private ImageView imageView;
45 | private CropPath cropPath;
46 |
47 | public CropHelper(Rect limit){
48 | this.limit=limit;
49 | }
50 |
51 | public CropHelper(){
52 |
53 | }
54 |
55 | public CropHelper attractTo(final ImageView iv){
56 | this.imageView=iv;
57 | iv.setOnTouchListener(new View.OnTouchListener() {
58 | @Override
59 | public boolean onTouch(View v, MotionEvent event) {
60 | iv.setOnTouchListener(CropHelper.this);
61 | matrix.set(iv.getImageMatrix());
62 | iv.setScaleType(ImageView.ScaleType.MATRIX);
63 | iv.setImageMatrix(matrix);
64 | CropHelper.this.onTouch(v,event);
65 | return true;
66 | }
67 | });
68 | return this;
69 | }
70 |
71 | public void setCropPath(CropPath cp){
72 | this.cropPath=cp;
73 | }
74 |
75 | private float[] values=new float[9];
76 |
77 | @Override
78 | public boolean onTouch(View v, MotionEvent event) {
79 |
80 | if(v!=null&&((ImageView) v).getDrawable()!=null){
81 | ImageView view = (ImageView) v;
82 | Rect rect=view.getDrawable().getBounds();
83 | //事件处理
84 | switch (event.getAction() & MotionEvent.ACTION_MASK) {
85 | //一个手指按下时,标记为移动模式
86 | case MotionEvent.ACTION_DOWN:
87 | matrix.set(view.getImageMatrix());
88 | savedMatrix.set(matrix);
89 | start.set(event.getX(), event.getY());
90 | mode = DRAG;
91 | break;
92 | //第二个手指按下时,标记为缩放模式
93 | case MotionEvent.ACTION_POINTER_DOWN:
94 | oldDist = distance(event);
95 | if (oldDist > 10f) {
96 | savedMatrix.set(matrix);
97 | midPoint(mid, event);
98 | mode = ZOOM;
99 | }
100 | break;
101 | case MotionEvent.ACTION_UP:
102 | case MotionEvent.ACTION_POINTER_UP:
103 | checkMatrix(rect);
104 | mode = NONE;
105 | break;
106 | //手指移动时,根据当前是移动模式还是缩放模式做相应处理
107 | case MotionEvent.ACTION_MOVE:
108 | if (mode == DRAG) {
109 | matrix.set(savedMatrix);
110 | matrix.postTranslate(event.getX() - start.x, event.getY()
111 | - start.y);
112 | } else if (mode == ZOOM) {
113 | float newDist = distance(event);
114 | if (newDist > 10f) {
115 | matrix.set(savedMatrix);
116 | float scale = newDist / oldDist;
117 | matrix.postScale(scale, scale, mid.x, mid.y);
118 | }
119 | }
120 | break;
121 | }
122 | view.setImageMatrix(matrix);
123 | }
124 | return true;
125 | }
126 |
127 | public Bitmap crop(){
128 | if(imageView!=null&&cropPath!=null){
129 | if(limit==null){
130 | limit=cropPath.limit();
131 | }
132 | Paint paint=new Paint();
133 | paint.setAntiAlias(true);
134 | imageView.setDrawingCacheEnabled(true);
135 | Bitmap bmp=Bitmap.createBitmap(limit.width(),limit.height(), Bitmap.Config.ARGB_8888);
136 | Canvas canvas=new Canvas(bmp);
137 | canvas.drawColor(Color.TRANSPARENT);
138 | int lId=canvas.saveLayer(0,0,limit.width(),limit.height(),null,Canvas.ALL_SAVE_FLAG);
139 | Path path=new Path();
140 | path.addPath(cropPath.path(),-limit.left,-limit.top);
141 | canvas.drawPath(path,paint);
142 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
143 | canvas.drawBitmap(imageView.getDrawingCache(),-limit.left,-limit.top,paint);
144 | paint.setXfermode(null);
145 | canvas.restoreToCount(lId);
146 | imageView.setDrawingCacheEnabled(false);
147 | return bmp;
148 | }
149 | return null;
150 | }
151 |
152 | public String cropAndSave(String path) throws IOException {
153 | Bitmap bmp=crop();
154 | if(bmp==null)return null;
155 | File file=new File(path);
156 | if(!file.getParentFile().exists()){
157 | boolean b=file.mkdirs();
158 | if(!b)return null;
159 | }
160 | if(file.exists()){
161 | boolean c=file.delete();
162 | if(!c)return null;
163 | }
164 | FileOutputStream fos=new FileOutputStream(file);
165 | bmp.compress(Bitmap.CompressFormat.PNG,100,fos);
166 | fos.flush();
167 | fos.close();
168 | bmp.recycle();
169 | return file.getAbsolutePath();
170 | }
171 |
172 | private void checkMatrix(Rect rect){
173 | if(limit==null&&cropPath!=null){
174 | limit=cropPath.limit();
175 | }
176 | if(limit!=null){
177 | if(mode==ZOOM){
178 | matrix.getValues(values);
179 | if(rect.width()*values[0]=limit.left){
191 | matrix.postTranslate(limit.left-values[2],0);
192 | }
193 | matrix.getValues(values);
194 | if(values[2]+rect.width()*values[0]limit.top){
199 | matrix.postTranslate(0,limit.top-values[5]);
200 | }
201 | matrix.getValues(values);
202 | if(values[5]+rect.height()*values[4] drawables;
26 |
27 | public IChooseDrawable(){
28 | paint=new Paint();
29 | paint.setAntiAlias(true);
30 | paint.setColor(0x88000000);
31 | drawables=new SparseArray<>();
32 | }
33 |
34 | public Drawable get(int state){
35 | if(drawables.indexOfKey(state)>=0){
36 | return drawables.get(state);
37 | }else{
38 | InDrawable drawable=new InDrawable(state);
39 | drawables.put(state,drawable);
40 | return drawable;
41 | }
42 | }
43 |
44 | public void clear(){
45 | drawables.clear();
46 | }
47 |
48 | public int getBaseline(Paint paint,int top,int bottom){
49 | Paint.FontMetrics i=paint.getFontMetrics();
50 | return (int) ((bottom+top-i.top-i.bottom)/2);
51 | }
52 |
53 | public abstract void draw(Canvas canvas,Paint paint,int state);
54 |
55 | private class InDrawable extends Drawable{
56 |
57 | private int state=0;
58 |
59 | InDrawable(int state){
60 | this.state=state;
61 | }
62 |
63 | @Override
64 | public void draw(@NonNull Canvas canvas) {
65 | IChooseDrawable.this.draw(canvas,paint,state);
66 | }
67 |
68 | @Override
69 | public void setAlpha(int alpha) {
70 |
71 | }
72 |
73 | @Override
74 | public void setColorFilter(ColorFilter colorFilter) {
75 |
76 | }
77 |
78 | @Override
79 | public int getOpacity() {
80 | return PixelFormat.TRANSPARENT;
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/utils/DensityUtils.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.utils;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by wuwang on 2016/11/6
7 | */
8 |
9 | public class DensityUtils {
10 |
11 | /**
12 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
13 | */
14 | public static int dip2px(Context context, float dpValue) {
15 | final float scale = context.getResources().getDisplayMetrics().density;
16 | return (int) (dpValue * scale + 0.5f);
17 | }
18 |
19 | /**
20 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
21 | */
22 | public static int px2dip(Context context, float pxValue) {
23 | final float scale = context.getResources().getDisplayMetrics().density;
24 | return (int) (pxValue / scale + 0.5f);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/utils/LogUtils.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.utils;
2 |
3 | import android.util.Log;
4 |
5 | import java.util.Map;
6 |
7 | /**
8 | * Description:
9 | */
10 | public class LogUtils {
11 |
12 | public static boolean DEBUG = true;
13 | public static String TAG="LOG";
14 |
15 | public static void setDebug(boolean isDebug) {
16 | DEBUG = isDebug;
17 | }
18 |
19 | public static void d(String msg){
20 | if(DEBUG)
21 | Log.d(TAG,msg);
22 | }
23 |
24 | public static void d(String tag, String msg) {
25 | if (DEBUG)
26 | Log.d(tag, msg);
27 | }
28 |
29 | public static void d(String tag, String msg,Throwable throwable) {
30 | if (DEBUG)
31 | Log.d(tag, msg,throwable);
32 | }
33 |
34 | public static void i(String msg){
35 | if(DEBUG)
36 | Log.i(TAG,msg);
37 | }
38 |
39 | public static void i(String tag, String msg) {
40 | if (DEBUG)
41 | Log.i(tag, msg);
42 | }
43 |
44 | public static void w(String tag, String msg) {
45 | if (DEBUG)
46 | Log.w(tag, msg);
47 | }
48 |
49 | public static void w(String msg){
50 | if(DEBUG)
51 | Log.w(TAG,msg);
52 | }
53 |
54 | public static void w(String tag, String msg,Throwable throwable) {
55 | if (DEBUG)
56 | Log.w(tag, msg,throwable);
57 | }
58 |
59 | public static void e(String msg){
60 | if(DEBUG)
61 | Log.e(TAG,msg);
62 | }
63 |
64 | public static void e(String tag, String msg) {
65 | if (DEBUG)
66 | Log.e(tag, msg);
67 | }
68 |
69 | public static void e(String tag, String msg,Throwable throwable) {
70 | if (DEBUG)
71 | Log.e(tag, msg,throwable);
72 | }
73 |
74 | public static void v(String msg){
75 | if(DEBUG)
76 | Log.v(TAG,msg);
77 | }
78 |
79 | public static void v(String tag, String msg) {
80 | if (DEBUG)
81 | Log.v(tag, msg);
82 | }
83 |
84 | public static void v(String tag, String msg,Throwable throwable) {
85 | if (DEBUG)
86 | Log.e(tag, msg,throwable);
87 | }
88 |
89 | public static void eLogMap(String tag,Map map){
90 | if(DEBUG){
91 | for (Map.Entry entry:map.entrySet()) {
92 | if(entry!=null){
93 | Log.e(tag,entry.getKey()+":"+entry.getValue());
94 | }
95 | }
96 | }
97 | }
98 |
99 | }
100 |
101 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/widget/SquareImageView.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.ImageView;
6 |
7 | /**
8 | * Created by wuwang on 2016/11/6
9 | */
10 |
11 | public class SquareImageView extends ImageView {
12 | public SquareImageView(Context context) {
13 | super(context);
14 | }
15 |
16 | public SquareImageView(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr) {
21 | super(context, attrs, defStyleAttr);
22 | }
23 |
24 | @Override
25 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
26 | super.onMeasure(widthMeasureSpec, widthMeasureSpec);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/chooser/src/main/java/com/wuwang/widget/SquareRelativeLayout.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.RelativeLayout;
6 |
7 | /**
8 | * Description:
9 | */
10 | public class SquareRelativeLayout extends RelativeLayout {
11 |
12 | public SquareRelativeLayout(Context context) {
13 | super(context);
14 | }
15 |
16 | public SquareRelativeLayout(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
21 | super(context, attrs, defStyleAttr);
22 | }
23 |
24 | @Override
25 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
26 | super.onMeasure(widthMeasureSpec, widthMeasureSpec);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/chooser/src/main/res/drawable/image_chooser_folder_item_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 | -
9 |
10 |
11 |
12 |
13 | -
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/chooser/src/main/res/drawable/left_back.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_activity_crop.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_activity_entry.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
8 |
13 |
14 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_default_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_fragment_album.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
14 |
20 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_fragment_crop.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
10 |
14 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_fragment_folder.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_item_album.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
24 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_item_camera.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/chooser/src/main/res/layout/image_chooser_item_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
17 |
--------------------------------------------------------------------------------
/chooser/src/main/res/menu/menu_album.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/chooser/src/main/res/menu/menu_crop.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/chooser/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/chooser/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/chooser/src/main/res/mipmap-xhdpi/image_chooser_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/chooser/src/main/res/mipmap-xhdpi/image_chooser_back.png
--------------------------------------------------------------------------------
/chooser/src/main/res/mipmap-xhdpi/image_chooser_camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/chooser/src/main/res/mipmap-xhdpi/image_chooser_camera.png
--------------------------------------------------------------------------------
/chooser/src/main/res/mipmap-xhdpi/image_chooser_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/chooser/src/main/res/mipmap-xhdpi/image_chooser_down.png
--------------------------------------------------------------------------------
/chooser/src/main/res/mipmap-xhdpi/image_chooser_placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/chooser/src/main/res/mipmap-xhdpi/image_chooser_placeholder.png
--------------------------------------------------------------------------------
/chooser/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFFFF
4 | #FFDDDDDD
5 | #FFFF8800
6 |
7 | #FF25c2e6
8 |
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/chooser/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ImageChooser
3 | 相册
4 | 确定
5 |
6 |
7 |
--------------------------------------------------------------------------------
/chooser/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/chooser/src/test/java/com/wuwang/imagechooser/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.wuwang.imagechooser;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/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 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doggycoder/ImageChooser/da0385175adde6ae50de7cf55d66ebb0785654c2/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # 说明
2 | 项目功能为图片选择器,当前已有功能及后续计划见更新说明,如有其它建议和意见,请mail至1558183202@qq.com。
3 | 围绕此项目写的相关博客:[相册基本实现](http://blog.csdn.net/junzia/article/details/53091606)、[图片裁剪](http://blog.csdn.net/junzia/article/details/52950210)
4 | ## 简单使用示例
5 | 如需使用图片选择器功能,将chooser加入为依赖工程,然后使用指定功能:
6 | ### 选择单张图片
7 | 如果需要选择单张图片,调用:
8 | ```java
9 | Intent intent=new Intent(IcFinal.ACTION_ALBUM);
10 | intent.putExtra(IcFinal.INTENT_MAX_IMG,1);
11 | startActivityForResult(intent,1);
12 | ```
13 | ### 选择多张图片
14 | 多选时,只需将IcFinal.INTENT_MAX_IMG的值设置你需要的值即可:
15 | ```java
16 | Intent intent=new Intent(IcFinal.ACTION_ALBUM);
17 | intent.putExtra(IcFinal.INTENT_MAX_IMG,9);
18 | startActivityForResult(intent,1);
19 | ```
20 | 如果你需要支持选择完成后,可以再次对之前选择的内容做修改,你可以增加:
21 | ```java
22 | intent.putStringArrayListExtra(IcFinal.INTENT_EXIST_DATA,data); //data为你之前所选的图片路径的ArrayList
23 | ```
24 | ### 裁剪
25 | 如果需要选择单张图片并且裁剪,调用:
26 | ```java
27 | Intent intent=new Intent(IcFinal.ACTION_ALBUM);
28 | intent.putExtra(IcFinal.INTENT_IS_CROP,true);
29 | startActivityForResult(intent,1);
30 | ```
31 | 默认为圆形图片,大小为500*500。如果需要自行设定,给intent增加以下参数:
32 | ```java
33 | intent.putExtra(IcFinal.INTENT_CROP_SHAPE,CropPath.SHAPE_RECT); //矩形,默认为CropPath.SHAPE_CIRCEL圆形
34 | intent.putExtra(IcFinal.INTENT_CROP_WIDTH,512); //裁剪宽度
35 | intent.putExtra(IcFinal.INTENT_CROP_HEIGHT,280); //裁剪高度
36 | ```
37 | 或者,你要的是其他不规则的形状,那么你可以选择继承ACropCoverDrawable类,自己来控制你需要的裁剪形状,然后使用以下代码来启动裁剪:
38 | ```java
39 | Intent intent=new Intent(IcFinal.ACTION_ALBUM);
40 | intent.putExtra(IcFinal.INTENT_IS_CROP,true);
41 | intent.putExtra(IcFinal.INTENT_CROP_COVER,ExampleCropPath.class.getName());
42 | intent.putExtra(IcFinal.INTENT_CROP_PARAM,1); //参数
43 | startActivityForResult(intent,1);
44 | ```
45 | 你所实现的ACropCoverDrawable类,只能使用一个int参数来控制它的反射出来的实体。其实一个int已经可以做很多事了。
46 |
47 | ## 更多设置
48 | 也许图片选择器默认的UI不符合你的要求,你可以选择利用ChooserSetting中的静态参数来更改图片选择器的效果:
49 | ```java
50 | /**标题的背景颜色*/
51 | public static int TITLE_COLOR=0xFF584512;
52 | /**图片选择页,每行显示数*/
53 | public static int NUM_COLUMNS=3;
54 | /**图片加载失败的图片*/
55 | public static int errorResId=0;
56 | /**图片加载的占位图片*/
57 | public static int placeResId=R.mipmap.image_chooser_placeholder;
58 | /**图片加载的动画*/
59 | public static int loadAnimateResId=0;
60 | /**选中图片的滤镜颜色*/
61 | public static int chooseFilter=0x55000000;
62 | /**未被选中的图片的滤镜颜色*/
63 | public static int unChooseFilter=0;
64 | /**最新的图片集合显示名字*/
65 | public static String newestAlbumName="最新图片";
66 | /**最新图片集合的最大数量*/
67 | public static int newestAlbumSize=100;
68 | public static int albumPopupHeight=600;
69 | public static String tantoToast="";
70 | /**照片选择指示器*/
71 | public static IChooseDrawable chooseDrawable=new CircleChooseDrawable(true,0xFF25c2e6);
72 | ```
73 | 如果这些也无法满足你的UI要求,你也可以参照EntryActivity重新写相册的入口Activity,参照CropActivity重写裁剪的入口Activity。
74 |
75 | # 更新说明
76 |
77 | ## 已完成功能
78 | 1. 图片单选多选功能
79 | 2. 多图选择指示器
80 | 3. 图片裁剪功能
81 | 4. 拍照功能
82 | 5. 裁剪形状的完全定制
83 |
84 | ## 待完成工作
85 | 1. ~~图片单选多选~~
86 | 2. ~~多图选择指示器~~
87 | 3. ~~图片裁剪~~
88 | 4. ~~裁剪形状的完全定制~~
89 | 4. 多图选择时的大图浏览
90 | 5. ~~拍照功能~~
91 | 6. UI让使用者可高度定制
92 | 7. 加入到jcenter和maven
93 | 8. 拍照的美颜及其他滤镜
94 |
95 | ## 20161111更新
96 | 基本完成相册选择、拍照、裁剪功能
97 |
98 | ## 20161113更新
99 | 1. 实现裁剪形状的完全定制入口
100 | 2. 完成对多选后再次修改的支持
101 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':chooser'
2 |
--------------------------------------------------------------------------------