+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..3b31283
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 9076de5..bd62ec5 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,8 +3,47 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 16aeed6..c1e8f28 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -4,8 +4,7 @@
-
+
-
-
+
\ No newline at end of file
diff --git a/.idea/qaplug_profiles.xml b/.idea/qaplug_profiles.xml
new file mode 100644
index 0000000..2cf250a
--- /dev/null
+++ b/.idea/qaplug_profiles.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml
deleted file mode 100644
index 922003b..0000000
--- a/.idea/scopes/scope_settings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index def6a6a..94a25f7 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,7 +1,6 @@
-
+
-
-
+
\ No newline at end of file
diff --git a/MultiImageSelector.iml b/MultiImageSelector.iml
index 8935ebd..f4dae0c 100644
--- a/MultiImageSelector.iml
+++ b/MultiImageSelector.iml
@@ -1,19 +1,19 @@
-
+
+
-
+
-
+
-
-
+
\ No newline at end of file
diff --git a/README.md b/README.md
index f901482..5ea3ace 100644
--- a/README.md
+++ b/README.md
@@ -1,135 +1,116 @@
# MultiImageSelector
-Image selector for Android device. Support single choice and multi-choice.
+Image selector for Android which supports single and multiple choices.
+This library developed by [lovetuzitong](https://github.com/lovetuzitong) originally but in Chinese language and poor English. I continue the development to improve this great library.
-[中文文档](README_zh.md)
-
-###ART
+## Screenshots
![Example1](art/example_1.png) ![Select1](art/select_1.png) ![Select2](art/select_2.png) ![Select3](art/select_3.png)
--------------------
-
-###Run Demo
+## Features
+* Multiple and single choices
+* Take photo
+* Limit selecting photos
->./gradlew installDebug
+## Quick Start
+* Add module `multi-image-selector` as your dependence.
+* Declare permission `android.permission.READ_EXTERNAL_STORAGE` in your `AndroidManifest.xml`.
+* Declare `MultiImageSelectorActivity` in your `AndroidManifest.xml`.
-###Quick Start
-* Step 0
-Add module `multi-image-selector` as your dependence.
-
-* Step 1
-Declare permission `android.permission.READ_EXTERNAL_STORAGE` in your `AndroidManifest.xml` .
-Declare `MultiImageSelectorActivity` in your `AndroidManifest.xml` .
```xml
```
-* Step 2
-Call image selector activity in your code, eg.
-``` java
-Intent intent = new Intent(mContext, MultiImageSelectorActivity.class);
+* Call image selector activity in your code, eg.
+```java
+Intent intent = new Intent(context, MultiImageSelectorActivity.class);
-// whether show camera
+// Whether show camera
intent.putExtra(MultiImageSelectorActivity.EXTRA_SHOW_CAMERA, true);
-// max select image amount
+// Max select image amount
intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_COUNT, 9);
-// select mode (MultiImageSelectorActivity.MODE_SINGLE OR MultiImageSelectorActivity.MODE_MULTI)
+// Select mode (MultiImageSelectorActivity.MODE_SINGLE OR MultiImageSelectorActivity.MODE_MULTI)
intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_MODE, MultiImageSelectorActivity.MODE_MULTI);
+// Whether log (true by default)
+intent.putExtra(MultiImageSelectorActivity.EXTRA_LOG, false);
+
startActivityForResult(intent, REQUEST_IMAGE);
```
-* Step 3
-Receive result in your `onActivityResult` Method. eg.
+* Receive result in your `onActivityResult` method. eg.
```java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_IMAGE){
if(resultCode == RESULT_OK){
- // Get the result list of select image paths
- List path = data.getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
- // do your logic ....
+ // Get the list of selected images paths
+ List paths = data.getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
+ // Do your logic...
+ }
+ else {
+ // Result has canceled
}
}
}
```
-* Step 4
-No more steps, just enjoy. :)
-
--------------------
-
-###Custom Activity Style
-* Custome your own Activity
+## Extend MultiImageSelectorActivity
```java
-class CustomerActivity extends Activity implements MultiImageSelectorFragment.Callback{
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // customer logic here...
- Bundle bundle = new Bundle();
- bundle.putInt(MultiImageSelectorFragment.EXTRA_SELECT_COUNT, mDefaultCount);
- bundle.putInt(MultiImageSelectorFragment.EXTRA_SELECT_MODE, mode);
- bundle.putBoolean(MultiImageSelectorFragment.EXTRA_SHOW_CAMERA, isShow);
- // Add fragment to your Activity
- getSupportFragmentManager().beginTransaction()
- .add(R.id.image_grid, Fragment.instantiate(this, MultiImageSelectorFragment.class.getName(), bundle))
- .commit();
- }
- @Override
- public void onSingleImageSelected(String path) {
- // When select mode set to MODE_SINGLE, this method will received result from fragment
+public class MySelector extends MultiImageSelectorActivity {
+ @Override
+ public void onCameraShot(File imageFile) {
+ super.onCameraShot(imageFile);
}
@Override
public void onImageSelected(String path) {
- // You can specify your ActionBar behavior here
+ super.onImageSelected(path);
}
@Override
public void onImageUnselected(String path) {
- // You can specify your ActionBar behavior here
+ super.onImageUnselected(path);
}
@Override
- public void onCameraShot(File imageFile) {
- // When user take phone by camera, this method will be called.
+ public void onSingleImageSelected(String path) {
+ super.onSingleImageSelected(path);
}
}
```
-* Take a glance of `MultiImageSelectorActivity.java`
-
--------------------
-
-###Change Log
-* 2015-5-5
- 1. Fixed. Can't display some images. (Issue by[sd6352051](https://github.com/sd6352051), [larry](https://github.com/18611480882))
- 2. Fixed. `ListPopupWindow` can not fill parent
- 3. Added. Add checked mask.
+*Note:* When you extend `MultiImageSelectorActivity` you must declare your activity in the `AndroidManifest.xml` and step 3 of quick start can be ignored.
-* 2015-4-16
- 1. Fixed. Crack when rotate device. (Issue by [@Leminity](https://github.com/Leminity))
- 2. Fixed. PopupListView position error. (Issue by [@Slock](https://github.com/Slock))
- 3. Change. Demo application shortcut.
- 4. Change. Readme file.
+## Changelog
+* September 23, 2015
+ 1. Improve the sample application
-* 2015-4-9
- 1. Fixed. When set `EXTRA_SHOW_CAMERA` to `true`, the first grid item onclick event were messed.
- 2. Add. Support initial selected image list.
+* September 22, 2015
+ 1. Whether log or not
+ 2. Minor improvements
--------------------
+* May 5, 2015
+ 1. Fixed: Can't display some images. (Reported by [sd6352051](https://github.com/sd6352051), [larry](https://github.com/18611480882))
+ 2. Fixed: `ListPopupWindow` can not fill parent
+ 3. Added: Add checked mask.
-###Thanks
+* April 9, 2015
+ 1. Fixed: When set `EXTRA_SHOW_CAMERA` to `true`, the first grid item `onclick` event were messed.
+ 2. Added: Support initial selected image list.
-* [square-picasso](https://github.com/square/picasso) A powerful image downloading and caching library for Android
+* April 4, 2015
+ 1. Fixed: Crack when rotate device. (Reported by [@Leminity](https://github.com/Leminity))
+ 2. Fixed: `PopupListView` position error. (Reported by [@Slock](https://github.com/Slock))
+ 3. Changed: Demo application shortcut.
--------------------
+## Thanks
+* [square/picasso](https://github.com/square/picasso) A powerful image downloading and caching library for Android
-###License
+## License
>The MIT License (MIT)
>Copyright (c) 2015 Nereo
@@ -142,4 +123,4 @@ copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
>The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
\ No newline at end of file
+copies or substantial portions of the Software.
diff --git a/README_zh.md b/README_zh.md
deleted file mode 100644
index b6ba2cc..0000000
--- a/README_zh.md
+++ /dev/null
@@ -1,146 +0,0 @@
-# MultiImageSelector
-仿微信实现多图选择。支持单选和多选两种模式
-
-[English Doc](README.md)
-
-###截图
-![Example1](art/example_1.png) ![Select1](art/select_1.png) ![Select2](art/select_2.png) ![Select3](art/select_3.png)
-
--------------------
-
-###运行DEMO
-
->./gradlew installDebug
-
-###快速开始
-* 第0步
-把模块 `multi-image-selector` 作为你的项目依赖添加到工程中.
-
-* 第1步
-在你的 `AndroidManifest.xml` 文件中添加权限 `android.permission.READ_EXTERNAL_STORAGE`.
-别忘了同时在 `AndroidManifest.xml` 中声明 `MultiImageSelectorActivity` 这个Activity.
-```xml
-
-```
-
-* 第2步
-代码中调用,例如:
-```java
-Intent intent = new Intent(mContext, MultiImageSelectorActivity.class);
-
-// 是否显示调用相机拍照
-intent.putExtra(MultiImageSelectorActivity.EXTRA_SHOW_CAMERA, true);
-
-// 最大图片选择数量
-intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_COUNT, 9);
-
-// 设置模式 (支持 单选/MultiImageSelectorActivity.MODE_SINGLE 或者 多选/MultiImageSelectorActivity.MODE_MULTI)
-intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_MODE, MultiImageSelectorActivity.MODE_MULTI);
-
-startActivityForResult(intent, REQUEST_IMAGE);
-```
-
-* 第3步
-在你的 `onActivityResult` 方法中接受结果. 例如:
-```java
-@Override
-protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if(requestCode == REQUEST_IMAGE){
- if(resultCode == RESULT_OK){
- // 获取返回的图片列表
- List path = data.getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
- // 处理你自己的逻辑 ....
- }
- }
-}
-```
-
-* 第4步
-没第4步了,就这样就OK啦~ :)
-
--------------------
-
-###自定义显示
-* 自定义Activity
-```java
-class CustomerActivity extends Activity implements MultiImageSelectorFragment.Callback{
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // 你自己的逻辑...
- Bundle bundle = new Bundle();
- bundle.putInt(MultiImageSelectorFragment.EXTRA_SELECT_COUNT, mDefaultCount);
- bundle.putInt(MultiImageSelectorFragment.EXTRA_SELECT_MODE, mode);
- olean(MultiImageSelectorFragment.EXTRA_SHOW_CAMERA, isShow);
- // 添加主Fragment到Activity
- getSupportFragmentManager().beginTransaction()
- .add(R.id.image_grid, Fragment.instantiate(this, MultiImageSelectorFragment.class.getName(), bundle))
- .commit();
- }
- @Override
- public void onSingleImageSelected(String path) {
- // 当选择模式设定为 单选/MODE_SINGLE, 这个方法就会接受到Fragment返回的数据
- }
-
- @Override
- public void onImageSelected(String path) {
- // 一个图片被选择是触发,这里可以自定义的自己的Actionbar行为
- }
-
- @Override
- public void onImageUnselected(String path) {
- // 一个图片被反选是触发,这里可以自定义的自己的Actionbar行为
- }
-
- @Override
- public void onCameraShot(File imageFile) {
- // 当设置了使用摄像头,用户拍照后会返回照片文件
- }
-}
-```
-* 具体可以参考`MultiImageSelectorActivity.java`的实现
-
--------------------
-
-###更新日志
-
-* 2015-5-5
- 1. 修复. 某些图片无法显示. (Issue by[sd6352051](https://github.com/sd6352051), [larry](https://github.com/18611480882))
- 2. 修复. `ListPopupWindow` 无法填充父控件
- 3. 新增. 选中的遮罩效果.
-
-* 2015-4-16
- 1. 修复. 旋转设备时,程序会崩溃. (Issue by [@Leminity](https://github.com/Leminity))
- 2. 修复. 文件夹PopupListView位置错误. (Issue by [@Slock](https://github.com/Slock))
- 3. 更改. 演示程序截图.
- 4. 更改. Readme 文件.
-
-* 2015-4-9
- 1. 修复. 当设置 `EXTRA_SHOW_CAMERA` 为 `true` 时, 点击第一个Item会混乱的问题.
- 2. 新增. 支持初始化图片选择设定。
-
-
--------------------
-
-###感谢
-
-* [square-picasso](https://github.com/square/picasso) A powerful image downloading and caching library for Android
-
--------------------
-
-###License
->The MIT License (MIT)
-
->Copyright (c) 2015 Nereo
-
->Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
->The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
\ No newline at end of file
diff --git a/app/app.iml b/app/app.iml
index 46168ca..e497a9c 100644
--- a/app/app.iml
+++ b/app/app.iml
@@ -1,5 +1,5 @@
-
+
@@ -12,9 +12,9 @@
-
-
-
+
+ generateDebugSources
+
@@ -23,9 +23,9 @@
-
+
-
+
@@ -33,13 +33,13 @@
-
+
-
+
@@ -47,6 +47,13 @@
+
+
+
+
+
+
+
@@ -61,35 +68,41 @@
+
+
+
+
+
+
+
-
+
-
+
-
+
+
-
-
-
-
+
-
-
+
+
+
-
+
-
+
+
-
-
-
+
+
+
-
-
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 5c156f5..4534ad2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,15 +1,14 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 22
- buildToolsVersion "22.0.1"
-
+ compileSdkVersion 23
+ buildToolsVersion '23.0.2'
defaultConfig {
applicationId "me.nereo.multiimageselector"
minSdkVersion 12
- targetSdkVersion 22
- versionCode 1
- versionName "1.0"
+ targetSdkVersion 23
+ versionCode 5
+ versionName '1.4'
}
buildTypes {
release {
@@ -17,10 +16,13 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ productFlavors {
+ }
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
- compile 'com.android.support:appcompat-v7:22.0.0'
- compile project(':multi-image-selector')
+ compile 'com.android.support:appcompat-v7:23.1.1'
+ compile 'com.jakewharton:butterknife:7.0.1'
+ compile project(':library')
}
diff --git a/app/src/androidTest/java/me/nereo/multiimageselector/ApplicationTest.java b/app/src/androidTest/java/me/nereo/multiimageselector/ApplicationTest.java
deleted file mode 100644
index e8fcd41..0000000
--- a/app/src/androidTest/java/me/nereo/multiimageselector/ApplicationTest.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package me.nereo.multiimageselector;
-
-import android.app.Application;
-import android.test.ApplicationTestCase;
-
-/**
- * Testing Fundamentals
- */
-public class ApplicationTest extends ApplicationTestCase {
- public ApplicationTest() {
- super(Application.class);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index fdccbb1..b38db63 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,29 +1,29 @@
-
+
-
+
+
+ android:theme="@style/AppTheme">
+ android:label="@string/app_name">
-
+
-
+
-
-
+ android:name="me.nereo.multi_image_selector.MultiImageSelectorActivity"
+ android:configChanges="orientation|screenSize"/>
diff --git a/app/src/main/java/me/nereo/multiimageselector/MainActivity.java b/app/src/main/java/me/nereo/multiimageselector/MainActivity.java
index 2b7d23f..78e9991 100644
--- a/app/src/main/java/me/nereo/multiimageselector/MainActivity.java
+++ b/app/src/main/java/me/nereo/multiimageselector/MainActivity.java
@@ -1,134 +1,112 @@
package me.nereo.multiimageselector;
import android.content.Intent;
-import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
+import android.widget.Button;
import android.widget.EditText;
+import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import java.util.ArrayList;
-import java.util.List;
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
import me.nereo.multi_image_selector.MultiImageSelectorActivity;
+import me.nereo.multi_image_selector.utils.Constants;
-public class MainActivity extends ActionBarActivity {
+public class MainActivity extends AppCompatActivity {
private static final int REQUEST_IMAGE = 2;
-
- private TextView mResultText;
- private RadioGroup mChoiceMode, mShowCamera;
- private EditText mRequestNum;
-
+ @Bind(R.id.button)
+ Button button;
+ @Bind(R.id.choice_mode)
+ RadioGroup mChoiceMode;
+ @Bind(R.id.request_num)
+ EditText mRequestNum;
+ @Bind(R.id.result)
+ TextView mResult;
+ @Bind(R.id.show_camera)
+ RadioGroup mShowCamera;
+ @Bind(R.id.multi)
+ RadioButton multi;
+ @Bind(R.id.no_show)
+ RadioButton noShow;
+ @Bind(R.id.show)
+ RadioButton show;
+ @Bind(R.id.single)
+ RadioButton single;
private ArrayList mSelectPath;
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_IMAGE) {
+ if (resultCode == RESULT_OK) {
+ mSelectPath = data.getStringArrayListExtra(Constants.EXTRA_RESULT);
+ StringBuilder sb = new StringBuilder();
+ for (String p : mSelectPath) {
+ sb.append(p);
+ sb.append("\n");
+ }
+ mResult.setText(sb.toString());
+ }
+ }
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
-
- mResultText = (TextView) findViewById(R.id.result);
- mChoiceMode = (RadioGroup) findViewById(R.id.choice_mode);
- mShowCamera = (RadioGroup) findViewById(R.id.show_camera);
- mRequestNum = (EditText) findViewById(R.id.request_num);
+ ButterKnife.bind(this);
mChoiceMode.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
- if(checkedId == R.id.multi){
+ if (checkedId == R.id.multi) {
mRequestNum.setEnabled(true);
- }else{
+ } else {
mRequestNum.setEnabled(false);
mRequestNum.setText("");
}
}
});
-
- findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
-
- int selectedMode = MultiImageSelectorActivity.MODE_MULTI;
-
- if(mChoiceMode.getCheckedRadioButtonId() == R.id.single){
- selectedMode = MultiImageSelectorActivity.MODE_SINGLE;
- }else{
- selectedMode = MultiImageSelectorActivity.MODE_MULTI;
- }
-
- boolean showCamera = mShowCamera.getCheckedRadioButtonId() == R.id.show;
-
- int maxNum = 9;
- if(!TextUtils.isEmpty(mRequestNum.getText())){
- maxNum = Integer.valueOf(mRequestNum.getText().toString());
- }
-
- Intent intent = new Intent(MainActivity.this, MultiImageSelectorActivity.class);
- // 是否显示拍摄图片
- intent.putExtra(MultiImageSelectorActivity.EXTRA_SHOW_CAMERA, showCamera);
- // 最大可选择图片数量
- intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_COUNT, maxNum);
- // 选择模式
- intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_MODE, selectedMode);
- // 默认选择
- if(mSelectPath != null && mSelectPath.size()>0){
- intent.putExtra(MultiImageSelectorActivity.EXTRA_DEFAULT_SELECTED_LIST, mSelectPath);
- }
- startActivityForResult(intent, REQUEST_IMAGE);
-
- }
- });
-
-/* findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(MainActivity.this, GestureImageActivity.class);
- startActivity(intent);
- }
- });*/
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if(requestCode == REQUEST_IMAGE){
- if(resultCode == RESULT_OK){
- mSelectPath = data.getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
- StringBuilder sb = new StringBuilder();
- for(String p: mSelectPath){
- sb.append(p);
- sb.append("\n");
- }
- mResultText.setText(sb.toString());
- }
- }
- }
+ @OnClick(R.id.button)
+ public void onButtonClick() {
+ int selectedMode;
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_main, menu);
- return true;
- }
+ if (mChoiceMode.getCheckedRadioButtonId() == R.id.single) {
+ selectedMode = Constants.MODE_SINGLE;
+ } else {
+ selectedMode = Constants.MODE_MULTI;
+ }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
+ boolean showCamera = mShowCamera.getCheckedRadioButtonId() == R.id.show;
- //noinspection SimplifiableIfStatement
- if (id == R.id.action_settings) {
- return true;
+ int maxNum = 9;
+ if (!TextUtils.isEmpty(mRequestNum.getText())) {
+ maxNum = Integer.valueOf(mRequestNum.getText().toString());
}
- return super.onOptionsItemSelected(item);
+ Intent intent = new Intent(MainActivity.this, MultiImageSelectorActivity.class);
+ // 是否显示拍摄图片
+ intent.putExtra(Constants.EXTRA_SHOW_CAMERA, showCamera);
+ // 最大可选择图片数量
+ intent.putExtra(Constants.EXTRA_SELECT_COUNT, !mRequestNum.getText().toString().isEmpty() ?
+ Integer
+ .parseInt(mRequestNum.getText().toString()) : Constants.DEFAULT_SELECTING_COUNT);
+ // 选择模式
+ intent.putExtra(Constants.EXTRA_SELECT_MODE, selectedMode);
+ // 默认选择
+ if (mSelectPath != null && mSelectPath.size() > 0) {
+ intent.putExtra(Constants.EXTRA_DEFAULT_SELECTED_LIST, mSelectPath);
+ }
+ startActivityForResult(intent, REQUEST_IMAGE);
}
}
diff --git a/app/src/main/res/drawable-hdpi/ic_camera.png b/app/src/main/res/drawable-hdpi/ic_camera.png
new file mode 100644
index 0000000..558b547
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_camera.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_camera.png b/app/src/main/res/drawable-mdpi/ic_camera.png
new file mode 100644
index 0000000..8edb547
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_camera.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_camera.png b/app/src/main/res/drawable-xhdpi/ic_camera.png
new file mode 100644
index 0000000..e688ca9
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_camera.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_camera.png b/app/src/main/res/drawable-xxhdpi/ic_camera.png
new file mode 100644
index 0000000..1e5be05
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_camera.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_camera.png b/app/src/main/res/drawable-xxxhdpi/ic_camera.png
new file mode 100644
index 0000000..e94b235
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_camera.png differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index a87f667..b4e0f53 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,91 +1,96 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context=".MainActivity">
+ android:textSize="16sp"
+ android:textStyle="bold"/>
+ android:layout_height="wrap_content"
+ android:checkedButton="@+id/multi"
+ android:orientation="vertical">
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/mode_single"/>
+
+ android:layout_height="wrap_content"
+ android:text="@string/mode_multi"/>
-
+
+ android:textSize="16sp"
+ android:textStyle="bold"/>
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:hint="@string/hint_default_amount"
+ android:inputType="number"/>
+ android:textSize="16sp"
+ android:textStyle="bold"/>
+ android:layout_height="wrap_content"
+ android:checkedButton="@+id/show"
+ android:orientation="vertical">
+ android:layout_height="wrap_content"
+ android:text="@string/enable"/>
+
+ android:layout_height="wrap_content"
+ android:text="@string/disable"/>
+ android:text="@string/go_select"/>
+ android:layout_height="wrap_content"/>
-
+
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
index b1cb908..ae84c3c 100644
--- a/app/src/main/res/menu/menu_main.xml
+++ b/app/src/main/res/menu/menu_main.xml
@@ -1,6 +1,10 @@
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
deleted file mode 100644
index 1815366..0000000
--- a/app/src/main/res/values-zh/strings.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
- 多图选择
-
- 设置
-
- 选择模式
- 单选
- 多选
- 最大选择数量
- 默认数量为9
- 是否启用照相机
- 是
- 否
- 图片选择
-
-
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fd04af9..67bb8a6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3,13 +3,13 @@
SettingsSelect Mode
- Single-Choice
- Multi-Choice
+ Single choice
+ Multi choiceMax Selected Amount
- default amount is 9
- Enable Camera
- Enable
- Disable
- Select
+ Selecting items is unlimited by default.
+ Show Camera Option
+ Yes
+ No
+ Let\'s select
diff --git a/build.gradle b/build.gradle
index d3ff69d..a6fcfe1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.1.0'
+ classpath 'com.android.tools.build:gradle:1.5.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0c71e76..b551494 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Apr 10 15:27:10 PDT 2013
+#Wed Feb 24 11:28:39 IRST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
diff --git a/multi-image-selector/.gitignore b/library/.gitignore
similarity index 100%
rename from multi-image-selector/.gitignore
rename to library/.gitignore
diff --git a/library/build.gradle b/library/build.gradle
new file mode 100644
index 0000000..197ac84
--- /dev/null
+++ b/library/build.gradle
@@ -0,0 +1,26 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion '23.0.2'
+ defaultConfig {
+ minSdkVersion 12
+ targetSdkVersion 23
+ versionCode 5
+ versionName '2.0'
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ productFlavors {
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ compile 'com.android.support:appcompat-v7:23.1.1'
+ compile 'com.squareup.picasso:picasso:2.5.2'
+}
diff --git a/multi-image-selector/proguard-rules.pro b/library/proguard-rules.pro
similarity index 95%
rename from multi-image-selector/proguard-rules.pro
rename to library/proguard-rules.pro
index 65e16ee..84e8219 100644
--- a/multi-image-selector/proguard-rules.pro
+++ b/library/proguard-rules.pro
@@ -15,3 +15,5 @@
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
+
+-dontwarn com.squareup.okhttp.**
\ No newline at end of file
diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..7ab9898
--- /dev/null
+++ b/library/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/library/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java b/library/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java
new file mode 100644
index 0000000..21380ae
--- /dev/null
+++ b/library/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java
@@ -0,0 +1,157 @@
+package me.nereo.multi_image_selector;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import me.nereo.multi_image_selector.utils.Constants;
+
+/**
+ * 多图选择
+ * Created by Nereo on 2015/4/7.
+ */
+public class MultiImageSelectorActivity extends FragmentActivity
+ implements MultiImageSelectorFragment.Callbacks {
+
+ private int mDefaultCount = -1;
+ private Button mSubmitButton;
+ private ArrayList resultList = new ArrayList<>();
+
+ @Override
+ public void onCameraShot(File imageFile) {
+ if (imageFile != null) {
+
+ // notify system
+ sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageFile)));
+
+ Intent data = new Intent();
+ resultList.add(imageFile.getAbsolutePath());
+ data.putStringArrayListExtra(Constants.EXTRA_RESULT, resultList);
+ setResult(RESULT_OK, data);
+ finish();
+ }
+ }
+
+ @Override
+ public void onImageSelected(String path) {
+ if (!resultList.contains(path)) {
+ resultList.add(path);
+ }
+ // 有图片之后,改变按钮状态
+ if (resultList.size() > 0) {
+ // If selecting images is not unlimited, displays complete with size string.
+ if (mDefaultCount != -1) {
+ mSubmitButton.setText(String.format(getString(R.string.complete_with_size), resultList
+ .size(), mDefaultCount));
+ }
+ if (!mSubmitButton.isEnabled()) {
+ mSubmitButton.setEnabled(true);
+ }
+ }
+ }
+
+ @Override
+ public void onImageUnselected(String path) {
+ if (resultList.contains(path)) {
+ resultList.remove(path);
+ }
+ mSubmitButton.setText(String.format(getString(R.string.complete_with_size), resultList.size(), mDefaultCount));
+ // 当为选择图片时候的状态
+ if (resultList.size() == 0) {
+ mSubmitButton.setText(getString(R.string.complete));
+ mSubmitButton.setEnabled(false);
+ }
+ }
+
+ @Override
+ public void onSingleImageSelected(String path) {
+ Intent data = new Intent();
+ resultList.add(path);
+ data.putStringArrayListExtra(Constants.EXTRA_RESULT, resultList);
+ setResult(RESULT_OK, data);
+ finish();
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_default);
+
+ Intent intent = getIntent();
+ mDefaultCount = intent.getIntExtra(Constants.EXTRA_SELECT_COUNT, Constants.DEFAULT_SELECTING_COUNT);
+ int mode = intent.getIntExtra(Constants.EXTRA_SELECT_MODE, Constants.MODE_MULTI);
+
+ // If multi mode selected but pass 1 as default count, consider single mode
+ {
+ if (mode == Constants.MODE_MULTI) {
+ if (mDefaultCount == 1) {
+ mode = Constants.MODE_SINGLE;
+ }
+ // Throw an exception if multiple choice mode selected with 0 default count
+ else if (mDefaultCount == 0) {
+ throw new IllegalStateException(getString(R.string.zero_multi_illegal));
+ }
+ }
+ }
+
+ boolean isShow = intent.getBooleanExtra(Constants.EXTRA_SHOW_CAMERA, true);
+ if (mode == Constants.MODE_MULTI && intent.hasExtra(Constants.EXTRA_DEFAULT_SELECTED_LIST)) {
+ resultList = intent.getStringArrayListExtra(Constants.EXTRA_DEFAULT_SELECTED_LIST);
+ }
+
+ // Change title based on mode
+ TextView title = (TextView) findViewById(R.id.title);
+ title.setText(mode == Constants.MODE_MULTI ? getString(R.string.select_photos) : getString(R.string.select_photo));
+
+
+ Bundle bundle = new Bundle();
+ bundle.putInt(Constants.EXTRA_SELECT_COUNT, mDefaultCount);
+ bundle.putInt(Constants.EXTRA_SELECT_MODE, mode);
+ bundle.putBoolean(Constants.EXTRA_SHOW_CAMERA, isShow);
+ bundle.putStringArrayList(Constants.EXTRA_DEFAULT_SELECTED_LIST, resultList);
+
+ getSupportFragmentManager().beginTransaction()
+ .add(R.id.image_grid, Fragment.instantiate(this, MultiImageSelectorFragment.class
+ .getName(), bundle))
+ .commit();
+
+ // 返回按钮
+ findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ });
+
+ // 完成按钮
+ mSubmitButton = (Button) findViewById(R.id.commit);
+ if (resultList == null || resultList.size() <= 0 || mDefaultCount == -1) {
+ mSubmitButton.setText(getString(R.string.complete));
+ mSubmitButton.setEnabled(false);
+ } else {
+ mSubmitButton.setText(String.format(getString(R.string.complete_with_size), resultList.size(), mDefaultCount));
+ mSubmitButton.setEnabled(true);
+ }
+ mSubmitButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (resultList != null && resultList.size() > 0) {
+ // 返回已选择的图片数据
+ Intent data = new Intent();
+ data.putStringArrayListExtra(Constants.EXTRA_RESULT, resultList);
+ setResult(RESULT_OK, data);
+ finish();
+ }
+ }
+ });
+ }
+}
diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java b/library/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java
similarity index 53%
rename from multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java
rename to library/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java
index d1bc4b4..2e0b0a7 100644
--- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java
+++ b/library/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java
@@ -1,14 +1,14 @@
package me.nereo.multi_image_selector;
-import android.annotation.TargetApi;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Color;
+import android.graphics.Point;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
@@ -18,11 +18,11 @@
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.widget.ListPopupWindow;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.Button;
@@ -33,6 +33,7 @@
import com.squareup.picasso.Picasso;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -40,80 +41,173 @@
import me.nereo.multi_image_selector.adapter.ImageGridAdapter;
import me.nereo.multi_image_selector.bean.Folder;
import me.nereo.multi_image_selector.bean.Image;
+import me.nereo.multi_image_selector.utils.Constants;
import me.nereo.multi_image_selector.utils.FileUtils;
-import me.nereo.multi_image_selector.utils.TimeUtils;
+import me.nereo.multi_image_selector.utils.ScreenUtils;
/**
* 图片选择Fragment
* Created by Nereo on 2015/4/7.
*/
public class MultiImageSelectorFragment extends Fragment {
-
- private static final String TAG = "MultiImageSelector";
-
- /** 最大图片选择次数,int类型 */
- public static final String EXTRA_SELECT_COUNT = "max_select_count";
- /** 图片选择模式,int类型 */
- public static final String EXTRA_SELECT_MODE = "select_count_mode";
- /** 是否显示相机,boolean类型 */
- public static final String EXTRA_SHOW_CAMERA = "show_camera";
- /** 默认选择的数据集 */
- public static final String EXTRA_DEFAULT_SELECTED_LIST = "default_result";
- /** 单选 */
- public static final int MODE_SINGLE = 0;
- /** 多选 */
- public static final int MODE_MULTI = 1;
- // 不同loader定义
- private static final int LOADER_ALL = 0;
- private static final int LOADER_CATEGORY = 1;
- // 请求加载系统照相机
+ public static final String TAG = MultiImageSelectorFragment.class.getSimpleName();
+ private static final String KEY_TEMP_FILE = "key_temp_file";
private static final int REQUEST_CAMERA = 100;
-
-
- // 结果数据
- private ArrayList resultList = new ArrayList<>();
// 文件夹数据
- private ArrayList mResultFolder = new ArrayList<>();
-
+ private final ArrayList mResultFolder = new ArrayList<>();
+ private boolean hasFolderGened = false;
+ private Callbacks mCallback;
+ // 类别
+ private TextView mCategoryText;
+ private int mDesireImageCount;
+ private FolderAdapter mFolderAdapter;
+ private ListPopupWindow mFolderPopupWindow;
// 图片Grid
private GridView mGridView;
- private Callback mCallback;
-
private ImageGridAdapter mImageAdapter;
- private FolderAdapter mFolderAdapter;
-
- private ListPopupWindow mFolderPopupWindow;
-
- // 时间线
- private TextView mTimeLineText;
- // 类别
- private TextView mCategoryText;
- // 预览按钮
- private Button mPreviewBtn;
+ private boolean mIsShowCamera = false;
// 底部View
private View mPopupAnchorView;
+ // 预览按钮
+ private Button mPreviewBtn;
+ private File mTmpFile;
+ // 结果数据
+ private ArrayList resultList = new ArrayList<>();
+ private final LoaderManager.LoaderCallbacks mLoaderCallback = new LoaderManager.LoaderCallbacks() {
- private int mDesireImageCount;
+ private final String[] IMAGE_PROJECTION = {MediaStore.Images.Media.DATA,
+ MediaStore.Images.Media.DISPLAY_NAME,
+ MediaStore.Images.Media.DATE_ADDED,
+ MediaStore.Images.Media.MIME_TYPE,
+ MediaStore.Images.Media.SIZE,
+ MediaStore.Images.Media._ID};
- private boolean hasFolderGened = false;
- private boolean mIsShowCamera = false;
+ @Override
+ public Loader onCreateLoader(int id, Bundle args) {
+ if (id == Constants.LOADER_ALL) {
+ return new CursorLoader(getActivity(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[3] + "=? OR " + IMAGE_PROJECTION[3] + "=? ",
+ new String[]{"image/jpeg", "image/png"}, IMAGE_PROJECTION[2] + " DESC");
+ } else if (id == Constants.LOADER_CATEGORY) {
+ return new CursorLoader(getActivity(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[0] + " like '%" + args.getString("path") + "%'",
+ null, IMAGE_PROJECTION[2] + " DESC");
+ }
- private int mGridWidth, mGridHeight;
+ return null;
+ }
- private File mTmpFile;
+ @Override
+ public void onLoadFinished(Loader loader, Cursor data) {
+ if (data != null) {
+ if (data.getCount() > 0) {
+ List images = new ArrayList<>();
+ data.moveToFirst();
+ do {
+ String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
+ String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
+ long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
+ Image image = null;
+ if (fileExist(path)) {
+ image = new Image(path, name, dateTime);
+ images.add(image);
+ }
+ if (!hasFolderGened) {
+ // 获取文件夹名称
+ File folderFile = new File(path).getParentFile();
+ if (folderFile != null && folderFile.exists()) {
+ String fp = folderFile.getAbsolutePath();
+ Folder f = getFolderByPath(fp);
+ if (f == null) {
+ Folder folder = new Folder();
+ folder.name = folderFile.getName();
+ folder.path = fp;
+ folder.cover = image;
+ List imageList = new ArrayList<>();
+ imageList.add(image);
+ folder.images = imageList;
+ mResultFolder.add(folder);
+ } else {
+ f.images.add(image);
+ }
+ }
+ }
+
+ } while (data.moveToNext());
+
+ mImageAdapter.setData(images);
+ // 设定默认选择
+ if (resultList != null && resultList.size() > 0) {
+ mImageAdapter.setDefaultSelected(resultList);
+ }
+
+ if (!hasFolderGened) {
+ mFolderAdapter.setData(mResultFolder);
+ hasFolderGened = true;
+ }
+
+ }
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {
+
+ }
+
+ private boolean fileExist(String path) {
+ if (!TextUtils.isEmpty(path)) {
+ return new File(path).exists();
+ }
+ return false;
+ }
+
+ private Folder getFolderByPath(String path) {
+ if (mResultFolder != null) {
+ for (Folder folder : mResultFolder) {
+ if (TextUtils.equals(folder.path, path)) {
+ return folder;
+ }
+ }
+ }
+ return null;
+ }
+ };
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ // 相机拍照完成后,返回图片路径
+ if (requestCode == Constants.REQUEST_CAMERA) {
+ if (resultCode == Activity.RESULT_OK) {
+ if (mTmpFile != null) {
+ if (mCallback != null) {
+ mCallback.onCameraShot(mTmpFile);
+ }
+ }
+ } else {
+ while (mTmpFile != null && mTmpFile.exists()) {
+ boolean success = mTmpFile.delete();
+ if (success) {
+ mTmpFile = null;
+ }
+ }
+ }
+ }
+ }
@Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
+ public void onAttach(Context context) {
+ super.onAttach(context);
try {
- mCallback = (Callback) activity;
- }catch (ClassCastException e){
- throw new ClassCastException("The Activity must implement MultiImageSelectorFragment.Callback interface...");
+ mCallback = (Callbacks) context;
+ } catch (ClassCastException e) {
+ throw new ClassCastException("The Activity must implement MultiImageSelectorFragment.Callback interface.");
}
}
@Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ public View onCreateView(LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_multi_image, container, false);
}
@@ -122,31 +216,27 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// 选择图片数量
- mDesireImageCount = getArguments().getInt(EXTRA_SELECT_COUNT);
+ mDesireImageCount = getArguments().getInt(Constants.EXTRA_SELECT_COUNT);
// 图片选择模式
- final int mode = getArguments().getInt(EXTRA_SELECT_MODE);
+ final int mode = getArguments().getInt(Constants.EXTRA_SELECT_MODE);
// 默认选择
- if(mode == MODE_MULTI) {
- ArrayList tmp = getArguments().getStringArrayList(EXTRA_DEFAULT_SELECTED_LIST);
- if(tmp != null && tmp.size()>0) {
+ if (mode == Constants.MODE_MULTI) {
+ ArrayList tmp = getArguments().getStringArrayList(Constants.EXTRA_DEFAULT_SELECTED_LIST);
+ if (tmp != null && tmp.size() > 0) {
resultList = tmp;
}
}
// 是否显示照相机
- mIsShowCamera = getArguments().getBoolean(EXTRA_SHOW_CAMERA, true);
- mImageAdapter = new ImageGridAdapter(getActivity(), mIsShowCamera);
+ mIsShowCamera = getArguments().getBoolean(Constants.EXTRA_SHOW_CAMERA, true);
+ mImageAdapter = new ImageGridAdapter(getActivity(), mIsShowCamera, 3);
// 是否显示选择指示器
- mImageAdapter.showSelectIndicator(mode == MODE_MULTI);
+ mImageAdapter.showSelectIndicator(mode == Constants.MODE_MULTI);
mPopupAnchorView = view.findViewById(R.id.footer);
- mTimeLineText = (TextView) view.findViewById(R.id.timeline_area);
- // 初始化,先隐藏当前timeline
- mTimeLineText.setVisibility(View.GONE);
-
mCategoryText = (TextView) view.findViewById(R.id.category_btn);
// 初始化,加载所有图片
mCategoryText.setText(R.string.folder_all);
@@ -154,8 +244,8 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
@Override
public void onClick(View view) {
- if(mFolderPopupWindow == null){
- createPopupFolderList(mGridWidth, mGridHeight);
+ if (mFolderPopupWindow == null) {
+ createPopupFolderList();
}
if (mFolderPopupWindow.isShowing()) {
@@ -171,7 +261,7 @@ public void onClick(View view) {
mPreviewBtn = (Button) view.findViewById(R.id.preview);
// 初始化,按钮状态初始化
- if(resultList == null || resultList.size()<=0){
+ if (resultList == null || resultList.size() <= 0) {
mPreviewBtn.setText(R.string.preview);
mPreviewBtn.setEnabled(false);
}
@@ -183,79 +273,42 @@ public void onClick(View view) {
});
mGridView = (GridView) view.findViewById(R.id.grid);
- mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {
- @Override
- public void onScrollStateChanged(AbsListView absListView, int state) {
- final Picasso picasso = Picasso.with(getActivity());
- if(state == SCROLL_STATE_IDLE || state == SCROLL_STATE_TOUCH_SCROLL){
- picasso.resumeTag(getActivity());
- }else{
- picasso.pauseTag(getActivity());
- }
-
- if(state == SCROLL_STATE_IDLE){
- // 停止滑动,日期指示器消失
- mTimeLineText.setVisibility(View.GONE);
- }else if(state == SCROLL_STATE_FLING){
- mTimeLineText.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- if(mTimeLineText.getVisibility() == View.VISIBLE) {
- int index = firstVisibleItem + 1 == view.getAdapter().getCount() ? view.getAdapter().getCount() - 1 : firstVisibleItem + 1;
- Image image = (Image) view.getAdapter().getItem(index);
- if (image != null) {
- mTimeLineText.setText(TimeUtils.formatPhotoDate(image.path));
- }
- }
- }
- });
mGridView.setAdapter(mImageAdapter);
- mGridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- public void onGlobalLayout() {
-
- final int width = mGridView.getWidth();
- final int height = mGridView.getHeight();
-
- mGridWidth = width;
- mGridHeight = height;
-
- final int desireSize = getResources().getDimensionPixelOffset(R.dimen.image_size);
- final int numCount = width / desireSize;
- final int columnSpace = getResources().getDimensionPixelOffset(R.dimen.space_size);
- int columnWidth = (width - columnSpace*(numCount-1)) / numCount;
- mImageAdapter.setItemSize(columnWidth);
-
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){
- mGridView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- }else{
- mGridView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
- }
- }
- });
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
- if(mImageAdapter.isShowCamera()){
+ if (mImageAdapter.isShowCamera()) {
// 如果显示照相机,则第一个Grid显示为照相机,处理特殊逻辑
- if(i == 0){
+ if (i == 0) {
showCameraAction();
- }else{
+ } else {
// 正常操作
Image image = (Image) adapterView.getAdapter().getItem(i);
selectImageFromGrid(image, mode);
}
- }else{
+ } else {
// 正常操作
Image image = (Image) adapterView.getAdapter().getItem(i);
selectImageFromGrid(image, mode);
}
}
});
+ mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ if (scrollState == SCROLL_STATE_FLING) {
+ Picasso.with(view.getContext()).pauseTag(TAG);
+ } else {
+ Picasso.with(view.getContext()).resumeTag(TAG);
+ }
+ }
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+
+ }
+ });
mFolderAdapter = new FolderAdapter(getActivity());
}
@@ -263,13 +316,16 @@ public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
/**
* 创建弹出的ListView
*/
- private void createPopupFolderList(int width, int height) {
+ private void createPopupFolderList() {
+ Point point = ScreenUtils.getScreenSize(getActivity());
+ int width = point.x;
+ int height = (int) (point.y * (4.5f / 8.0f));
mFolderPopupWindow = new ListPopupWindow(getActivity());
- mFolderPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+ mFolderPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.WHITE));
mFolderPopupWindow.setAdapter(mFolderAdapter);
mFolderPopupWindow.setContentWidth(width);
mFolderPopupWindow.setWidth(width);
- mFolderPopupWindow.setHeight(height * 5 / 8);
+ mFolderPopupWindow.setHeight(height);
mFolderPopupWindow.setAnchorView(mPopupAnchorView);
mFolderPopupWindow.setModal(true);
mFolderPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@@ -287,7 +343,8 @@ public void run() {
mFolderPopupWindow.dismiss();
if (index == 0) {
- getActivity().getSupportLoaderManager().restartLoader(LOADER_ALL, null, mLoaderCallback);
+ getActivity().getSupportLoaderManager()
+ .restartLoader(Constants.LOADER_ALL, null, mLoaderCallback);
mCategoryText.setText(R.string.folder_all);
if (mIsShowCamera) {
mImageAdapter.setShowCamera(true);
@@ -316,106 +373,47 @@ public void run() {
});
}
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- // 首次加载所有图片
- //new LoadImageTask().execute();
- getActivity().getSupportLoaderManager().initLoader(LOADER_ALL, null, mLoaderCallback);
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- // 相机拍照完成后,返回图片路径
- if(requestCode == REQUEST_CAMERA){
- if(resultCode == Activity.RESULT_OK) {
- if (mTmpFile != null) {
- if (mCallback != null) {
- mCallback.onCameraShot(mTmpFile);
- }
- }
- }else{
- if(mTmpFile != null && mTmpFile.exists()){
- mTmpFile.delete();
- }
- }
- }
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- Log.d(TAG, "on change");
-
- if(mFolderPopupWindow != null){
- if(mFolderPopupWindow.isShowing()){
- mFolderPopupWindow.dismiss();
- }
- }
-
- mGridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- public void onGlobalLayout() {
-
- final int height = mGridView.getHeight();
-
- final int desireSize = getResources().getDimensionPixelOffset(R.dimen.image_size);
- Log.d(TAG, "Desire Size = " + desireSize);
- final int numCount = mGridView.getWidth() / desireSize;
- Log.d(TAG, "Grid Size = " + mGridView.getWidth());
- Log.d(TAG, "num count = " + numCount);
- final int columnSpace = getResources().getDimensionPixelOffset(R.dimen.space_size);
- int columnWidth = (mGridView.getWidth() - columnSpace * (numCount - 1)) / numCount;
- mImageAdapter.setItemSize(columnWidth);
-
- if (mFolderPopupWindow != null) {
- mFolderPopupWindow.setHeight(height * 5 / 8);
- }
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- mGridView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- } else {
- mGridView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
- }
- }
- });
-
- super.onConfigurationChanged(newConfig);
-
- }
-
/**
* 选择相机
*/
private void showCameraAction() {
// 跳转到系统照相机
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- if(cameraIntent.resolveActivity(getActivity().getPackageManager()) != null){
+ if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) {
// 设置系统相机拍照后的输出路径
// 创建临时文件
- mTmpFile = FileUtils.createTmpFile(getActivity());
- cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile));
- startActivityForResult(cameraIntent, REQUEST_CAMERA);
- }else{
+ try {
+ mTmpFile = FileUtils.createTmpFile(getActivity());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ if (mTmpFile != null && mTmpFile.exists()) {
+ cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile));
+ startActivityForResult(cameraIntent, REQUEST_CAMERA);
+ } else {
+ Toast.makeText(getActivity(), R.string.picture_error, Toast.LENGTH_SHORT).show();
+ }
+ } else {
Toast.makeText(getActivity(), R.string.msg_no_camera, Toast.LENGTH_SHORT).show();
}
- }
+ }// 请求加载系统照相机
/**
* 选择图片操作
+ *
* @param image
*/
private void selectImageFromGrid(Image image, int mode) {
- if(image != null) {
+ if (image != null) {
// 多选模式
- if(mode == MODE_MULTI) {
+ if (mode == Constants.MODE_MULTI) {
if (resultList.contains(image.path)) {
resultList.remove(image.path);
- if(resultList.size() != 0) {
+ if (resultList.size() != 0) {
mPreviewBtn.setEnabled(true);
- mPreviewBtn.setText(getResources().getString(R.string.preview) + "(" + resultList.size() + ")");
- }else{
+ mPreviewBtn.setText(String.format(getString(R.string.preview_with_size), resultList
+ .size()));
+ } else {
mPreviewBtn.setEnabled(false);
mPreviewBtn.setText(R.string.preview);
}
@@ -424,115 +422,83 @@ private void selectImageFromGrid(Image image, int mode) {
}
} else {
// 判断选择数量问题
- if(mDesireImageCount == resultList.size()){
- Toast.makeText(getActivity(), R.string.msg_amount_limit, Toast.LENGTH_SHORT).show();
+ // If mDesireImageCount is -1, it means unlimited
+ if (mDesireImageCount != -1 && mDesireImageCount == resultList.size()) {
+ Toast.makeText(getActivity(), String.format(getString(R.string.msg_amount_limit), mDesireImageCount), Toast.LENGTH_SHORT)
+ .show();
return;
}
resultList.add(image.path);
mPreviewBtn.setEnabled(true);
- mPreviewBtn.setText(getResources().getString(R.string.preview) + "(" + resultList.size() + ")");
+ mPreviewBtn.setText(String.format(getString(R.string.preview_with_size), resultList
+ .size()));
if (mCallback != null) {
mCallback.onImageSelected(image.path);
}
}
mImageAdapter.select(image);
- }else if(mode == MODE_SINGLE){
+ } else if (mode == Constants.MODE_SINGLE) {
// 单选模式
- if(mCallback != null){
+ if (mCallback != null) {
mCallback.onSingleImageSelected(image.path);
}
}
}
}
- private LoaderManager.LoaderCallbacks mLoaderCallback = new LoaderManager.LoaderCallbacks() {
-
- private final String[] IMAGE_PROJECTION = {
- MediaStore.Images.Media.DATA,
- MediaStore.Images.Media.DISPLAY_NAME,
- MediaStore.Images.Media.DATE_ADDED,
- MediaStore.Images.Media._ID };
-
- @Override
- public Loader onCreateLoader(int id, Bundle args) {
- if(id == LOADER_ALL) {
- CursorLoader cursorLoader = new CursorLoader(getActivity(),
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
- null, null, IMAGE_PROJECTION[2] + " DESC");
- return cursorLoader;
- }else if(id == LOADER_CATEGORY){
- CursorLoader cursorLoader = new CursorLoader(getActivity(),
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
- IMAGE_PROJECTION[0]+" like '%"+args.getString("path")+"%'", null, IMAGE_PROJECTION[2] + " DESC");
- return cursorLoader;
- }
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ // 首次加载所有图片
+ //new LoadImageTask().execute();
+ getActivity().getSupportLoaderManager()
+ .initLoader(Constants.LOADER_ALL, null, mLoaderCallback);
+ }
- return null;
+ @Override
+ public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
+ super.onViewStateRestored(savedInstanceState);
+ if (savedInstanceState != null) {
+ mTmpFile = (File) savedInstanceState.getSerializable(KEY_TEMP_FILE);
}
+ }
- @Override
- public void onLoadFinished(Loader loader, Cursor data) {
- if (data != null) {
- List images = new ArrayList<>();
- int count = data.getCount();
- if (count > 0) {
- data.moveToFirst();
- do{
- String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
- String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
- long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
- Image image = new Image(path, name, dateTime);
- images.add(image);
- if( !hasFolderGened ) {
- // 获取文件夹名称
- File imageFile = new File(path);
- File folderFile = imageFile.getParentFile();
- Folder folder = new Folder();
- folder.name = folderFile.getName();
- folder.path = folderFile.getAbsolutePath();
- folder.cover = image;
- if (!mResultFolder.contains(folder)) {
- List imageList = new ArrayList<>();
- imageList.add(image);
- folder.images = imageList;
- mResultFolder.add(folder);
- } else {
- // 更新
- Folder f = mResultFolder.get(mResultFolder.indexOf(folder));
- f.images.add(image);
- }
- }
-
- }while(data.moveToNext());
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putSerializable(KEY_TEMP_FILE, mTmpFile);
+ }
- mImageAdapter.setData(images);
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
- // 设定默认选择
- if(resultList != null && resultList.size()>0){
- mImageAdapter.setDefaultSelected(resultList);
- }
+ final boolean log = getArguments().getBoolean(Constants.EXTRA_LOG, true);
- mFolderAdapter.setData(mResultFolder);
- hasFolderGened = true;
+ if (log) {
+ Log.d(Constants.TAG, "on change");
+ }
- }
+ if (mFolderPopupWindow != null) {
+ if (mFolderPopupWindow.isShowing()) {
+ mFolderPopupWindow.dismiss();
}
}
- @Override
- public void onLoaderReset(Loader loader) {
+ super.onConfigurationChanged(newConfig);
- }
- };
+ }
/**
* 回调接口
*/
- public interface Callback{
- void onSingleImageSelected(String path);
+ public interface Callbacks {
+ void onCameraShot(File imageFile);
+
void onImageSelected(String path);
+
void onImageUnselected(String path);
- void onCameraShot(File imageFile);
+
+ void onSingleImageSelected(String path);
}
}
diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java b/library/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java
similarity index 55%
rename from multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java
rename to library/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java
index 7e5a237..5896db6 100644
--- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java
+++ b/library/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java
@@ -23,43 +23,29 @@
*/
public class FolderAdapter extends BaseAdapter {
- private Context mContext;
- private LayoutInflater mInflater;
-
+ private final Context mContext;
+ private final int mImageSize;
+ private final LayoutInflater mInflater;
+ private int lastSelected = 0;
private List mFolders = new ArrayList<>();
- int mImageSize;
-
- int lastSelected = 0;
-
- public FolderAdapter(Context context){
+ public FolderAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mImageSize = mContext.getResources().getDimensionPixelOffset(R.dimen.folder_cover_size);
}
- /**
- * 设置数据集
- * @param folders
- */
- public void setData(List folders) {
- if(folders != null && folders.size()>0){
- mFolders = folders;
- }else{
- mFolders.clear();
- }
- notifyDataSetChanged();
- }
-
@Override
public int getCount() {
- return mFolders.size()+1;
+ return mFolders.size() + 1;
}
@Override
public Folder getItem(int i) {
- if(i == 0) return null;
- return mFolders.get(i-1);
+ if (i == 0) {
+ return null;
+ }
+ return mFolders.get(i - 1);
}
@Override
@@ -70,82 +56,116 @@ public long getItemId(int i) {
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder;
- if(view == null){
+ if (view == null) {
view = mInflater.inflate(R.layout.list_item_folder, viewGroup, false);
holder = new ViewHolder(view);
- }else{
+ } else {
holder = (ViewHolder) view.getTag();
}
if (holder != null) {
- if(i == 0){
- holder.name.setText("所有图片");
- holder.size.setText(getTotalImageSize()+"张");
- if(mFolders.size()>0){
+ if (i == 0) {
+ holder.name.setText(R.string.folder_all);
+ holder.path.setText("/sdcard");
+ holder.size.setText(String.format("%d %s",
+ getTotalImageSize(), "Photos"));
+ if (mFolders.size() > 0) {
Folder f = mFolders.get(0);
Picasso.with(mContext)
.load(new File(f.cover.path))
.error(R.drawable.default_error)
- .resize(mImageSize, mImageSize)
+ .resizeDimen(R.dimen.folder_cover_size, R.dimen.folder_cover_size)
.centerCrop()
.into(holder.cover);
}
- }else {
+ } else {
holder.bindData(getItem(i));
}
- if(lastSelected == i){
+ if (lastSelected == i) {
holder.indicator.setVisibility(View.VISIBLE);
- }else{
+ } else {
holder.indicator.setVisibility(View.INVISIBLE);
}
}
return view;
}
- private int getTotalImageSize(){
+ private int getTotalImageSize() {
int result = 0;
- if(mFolders != null && mFolders.size()>0){
- for (Folder f: mFolders){
+ if (mFolders != null && mFolders.size() > 0) {
+ for (Folder f : mFolders) {
result += f.images.size();
}
}
return result;
}
+ public int getSelectIndex() {
+ return lastSelected;
+ }
+
public void setSelectIndex(int i) {
- if(lastSelected == i) return;
+ if (lastSelected == i) {
+ return;
+ }
lastSelected = i;
notifyDataSetChanged();
}
- public int getSelectIndex(){
- return lastSelected;
+ /**
+ * 设置数据集
+ *
+ * @param folders
+ */
+ public void setData(List folders) {
+ if (folders != null && folders.size() > 0) {
+ mFolders = folders;
+ } else {
+ mFolders.clear();
+ }
+ notifyDataSetChanged();
}
- class ViewHolder{
- ImageView cover;
- TextView name;
- TextView size;
- ImageView indicator;
- ViewHolder(View view){
- cover = (ImageView)view.findViewById(R.id.cover);
+ class ViewHolder {
+ final ImageView cover;
+ final ImageView indicator;
+ final TextView name;
+ final TextView size;
+ TextView path;
+
+ ViewHolder(View view) {
+ cover = (ImageView) view.findViewById(R.id.cover);
name = (TextView) view.findViewById(R.id.name);
size = (TextView) view.findViewById(R.id.size);
+ path = (TextView) view.findViewById(R.id.path);
indicator = (ImageView) view.findViewById(R.id.indicator);
view.setTag(this);
}
void bindData(Folder data) {
+
+ if (data == null) {
+ return;
+ }
+
name.setText(data.name);
- size.setText(data.images.size()+"张");
+ path.setText(data.path);
+ if (data.images != null) {
+ size.setText(String.format("%d %s", data.images.size(), "Photos"));
+ } else {
+ size.setText("* Photos");
+ }
// 显示图片
- Picasso.with(mContext)
- .load(new File(data.cover.path))
- .placeholder(R.drawable.default_error)
- .resize(mImageSize, mImageSize)
- .centerCrop()
- .into(cover);
- // TODO 选择标识
+ if (data.cover != null) {
+ Picasso.with(mContext)
+ .load(new File(data.cover.path))
+ .placeholder(R.drawable.default_error)
+ .resizeDimen(R.dimen.folder_cover_size, R.dimen.folder_cover_size)
+ .centerCrop()
+ .into(cover);
+ } else {
+ cover.setImageResource(R.drawable.default_error);
+ }
}
}
diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/ImageGridAdapter.java b/library/src/main/java/me/nereo/multi_image_selector/adapter/ImageGridAdapter.java
similarity index 54%
rename from multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/ImageGridAdapter.java
rename to library/src/main/java/me/nereo/multi_image_selector/adapter/ImageGridAdapter.java
index 23bed9d..7883be0 100644
--- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/ImageGridAdapter.java
+++ b/library/src/main/java/me/nereo/multi_image_selector/adapter/ImageGridAdapter.java
@@ -1,21 +1,22 @@
package me.nereo.multi_image_selector.adapter;
import android.content.Context;
-import android.text.TextUtils;
+import android.graphics.Point;
+import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.BaseAdapter;
-import android.widget.GridView;
import android.widget.ImageView;
-import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import me.nereo.multi_image_selector.MultiImageSelectorFragment;
import me.nereo.multi_image_selector.R;
import me.nereo.multi_image_selector.bean.Image;
@@ -27,224 +28,212 @@ public class ImageGridAdapter extends BaseAdapter {
private static final int TYPE_CAMERA = 0;
private static final int TYPE_NORMAL = 1;
-
- private Context mContext;
-
- private LayoutInflater mInflater;
+ final int mGridWidth;
+ private final Context mContext;
+ private final LayoutInflater mInflater;
+ private int mItemSize;
private boolean showCamera = true;
private boolean showSelectIndicator = true;
-
private List mImages = new ArrayList<>();
private List mSelectedImages = new ArrayList<>();
- private int mItemSize;
- private GridView.LayoutParams mItemLayoutParams;
-
- public ImageGridAdapter(Context context, boolean showCamera){
+ public ImageGridAdapter(Context context, boolean showCamera, int column) {
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.showCamera = showCamera;
- mItemLayoutParams = new GridView.LayoutParams(GridView.LayoutParams.MATCH_PARENT, GridView.LayoutParams.MATCH_PARENT);
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ int width = 0;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
+ Point size = new Point();
+ wm.getDefaultDisplay().getSize(size);
+ width = size.x;
+ } else {
+ width = wm.getDefaultDisplay().getWidth();
+ }
+ mGridWidth = width / column;
}
- /**
- * 显示选择指示器
- * @param b
- */
- public void showSelectIndicator(boolean b) {
- showSelectIndicator = b;
+
+ @Override
+ public int getCount() {
+ return showCamera ? mImages.size() + 1 : mImages.size();
+ }
+
+ @Override
+ public Image getItem(int i) {
+ if (showCamera) {
+ if (i == 0) {
+ return null;
+ }
+ return mImages.get(i - 1);
+ } else {
+ return mImages.get(i);
+ }
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+
+ if (isShowCamera()) {
+ if (i == 0) {
+ view = mInflater.inflate(R.layout.list_item_camera, viewGroup, false);
+ return view;
+ }
+ }
+
+ /** Fixed View Size */
+ ViewHolder holder;
+ if (view == null) {
+ view = mInflater.inflate(R.layout.list_item_image, viewGroup, false);
+ holder = new ViewHolder(view);
+ } else {
+ holder = (ViewHolder) view.getTag();
+ }
+
+ if (holder != null) {
+ holder.bindData(getItem(i));
+ }
+
+ return view;
}
- public void setShowCamera(boolean b){
- if(showCamera == b) return;
+ public boolean isShowCamera() {
+ return showCamera;
+ }
+
+ public void setShowCamera(boolean b) {
+ if (showCamera == b) {
+ return;
+ }
showCamera = b;
notifyDataSetChanged();
}
- public boolean isShowCamera(){
- return showCamera;
+ @Override
+ public int getItemViewType(int position) {
+ if (showCamera) {
+ return position == 0 ? TYPE_CAMERA : TYPE_NORMAL;
+ }
+ return TYPE_NORMAL;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 2;
}
/**
* 选择某个图片,改变选择状态
+ *
* @param image
*/
public void select(Image image) {
- if(mSelectedImages.contains(image)){
+ if (mSelectedImages.contains(image)) {
mSelectedImages.remove(image);
- }else{
+ } else {
mSelectedImages.add(image);
}
notifyDataSetChanged();
}
- /**
- * 通过图片路径设置默认选择
- * @param resultList
- */
- public void setDefaultSelected(ArrayList resultList) {
- for(String path : resultList){
- Image image = getImageByPath(path);
- if(image != null){
- mSelectedImages.add(image);
- }
- }
- if(mSelectedImages.size() > 0){
- notifyDataSetChanged();
- }
- }
-
- private Image getImageByPath(String path){
- if(mImages != null && mImages.size()>0){
- for(Image image : mImages){
- if(image.path.equalsIgnoreCase(path)){
- return image;
- }
- }
- }
- return null;
- }
-
/**
* 设置数据集
+ *
* @param images
*/
public void setData(List images) {
mSelectedImages.clear();
- if(images != null && images.size()>0){
+ if (images != null && images.size() > 0) {
mImages = images;
- }else{
+ } else {
mImages.clear();
}
notifyDataSetChanged();
}
/**
- * 重置每个Column的Size
- * @param columnWidth
+ * 通过图片路径设置默认选择
+ *
+ * @param resultList
*/
- public void setItemSize(int columnWidth) {
-
- if(mItemSize == columnWidth){
- return;
- }
-
- mItemSize = columnWidth;
-
- mItemLayoutParams = new GridView.LayoutParams(mItemSize, mItemSize);
-
- notifyDataSetChanged();
- }
-
- @Override
- public int getViewTypeCount() {
- return 2;
- }
-
- @Override
- public int getItemViewType(int position) {
- if(showCamera){
- return position==0 ? TYPE_CAMERA : TYPE_NORMAL;
- }
- return TYPE_NORMAL;
- }
-
- @Override
- public int getCount() {
- return showCamera ? mImages.size()+1 : mImages.size();
- }
-
- @Override
- public Image getItem(int i) {
- if(showCamera){
- if(i == 0){
- return null;
+ public void setDefaultSelected(ArrayList resultList) {
+ for (String path : resultList) {
+ Image image = getImageByPath(path);
+ if (image != null) {
+ mSelectedImages.add(image);
}
- return mImages.get(i-1);
- }else{
- return mImages.get(i);
+ }
+ if (mSelectedImages.size() > 0) {
+ notifyDataSetChanged();
}
}
- @Override
- public long getItemId(int i) {
- return i;
- }
-
- @Override
- public View getView(int i, View view, ViewGroup viewGroup) {
-
- int type = getItemViewType(i);
- if(type == TYPE_CAMERA){
- view = mInflater.inflate(R.layout.list_item_camera, viewGroup, false);
- view.setTag(null);
- }else if(type == TYPE_NORMAL){
- ViewHolde holde;
- if(view == null){
- view = mInflater.inflate(R.layout.list_item_image, viewGroup, false);
- holde = new ViewHolde(view);
- }else{
- holde = (ViewHolde) view.getTag();
- if(holde == null){
- view = mInflater.inflate(R.layout.list_item_image, viewGroup, false);
- holde = new ViewHolde(view);
+ private Image getImageByPath(String path) {
+ if (mImages != null && mImages.size() > 0) {
+ for (Image image : mImages) {
+ if (image.path.equalsIgnoreCase(path)) {
+ return image;
}
}
- if(holde != null) {
- holde.bindData(getItem(i));
- }
- }
-
- /** Fixed View Size */
- GridView.LayoutParams lp = (GridView.LayoutParams) view.getLayoutParams();
- if(lp.height != mItemSize){
- view.setLayoutParams(mItemLayoutParams);
}
+ return null;
+ }
- return view;
+ /**
+ * 显示选择指示器
+ *
+ * @param b
+ */
+ public void showSelectIndicator(boolean b) {
+ showSelectIndicator = b;
}
- class ViewHolde {
- ImageView image;
- ImageView indicator;
- View mask;
+ class ViewHolder {
+ final ImageView image;
+ final ImageView indicator;
+ final View mask;
- ViewHolde(View view){
+ ViewHolder(View view) {
image = (ImageView) view.findViewById(R.id.image);
indicator = (ImageView) view.findViewById(R.id.checkmark);
mask = view.findViewById(R.id.mask);
view.setTag(this);
}
- void bindData(final Image data){
- if(data == null) return;
+ void bindData(final Image data) {
+ if (data == null) {
+ return;
+ }
// 处理单选和多选状态
- if(showSelectIndicator){
+ if (showSelectIndicator) {
indicator.setVisibility(View.VISIBLE);
- if(mSelectedImages.contains(data)){
+ if (mSelectedImages.contains(data)) {
// 设置选中状态
indicator.setImageResource(R.drawable.btn_selected);
mask.setVisibility(View.VISIBLE);
- }else{
+ } else {
// 未选择
indicator.setImageResource(R.drawable.btn_unselected);
mask.setVisibility(View.GONE);
}
- }else{
+ } else {
indicator.setVisibility(View.GONE);
}
File imageFile = new File(data.path);
- if(mItemSize > 0) {
+ if (imageFile.exists()) {
// 显示图片
- Picasso.with(mContext)
- .load(imageFile)
- .placeholder(R.drawable.default_error)
- //.error(R.drawable.default_error)
- .resize(mItemSize, mItemSize)
- .centerCrop()
- .into(image);
+ Picasso.with(mContext).load(imageFile).placeholder(R.drawable.default_error)
+ .tag(MultiImageSelectorFragment.TAG)
+ .resize(mGridWidth, mGridWidth).centerCrop().into(image);
+ } else {
+ image.setImageResource(R.drawable.default_error);
}
}
}
diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Folder.java b/library/src/main/java/me/nereo/multi_image_selector/bean/Folder.java
similarity index 77%
rename from multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Folder.java
rename to library/src/main/java/me/nereo/multi_image_selector/bean/Folder.java
index c917790..ca0edbe 100644
--- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Folder.java
+++ b/library/src/main/java/me/nereo/multi_image_selector/bean/Folder.java
@@ -1,5 +1,7 @@
package me.nereo.multi_image_selector.bean;
+import android.text.TextUtils;
+
import java.util.List;
/**
@@ -7,17 +9,17 @@
* Created by Nereo on 2015/4/7.
*/
public class Folder {
- public String name;
- public String path;
public Image cover;
public List images;
+ public String name;
+ public String path;
@Override
public boolean equals(Object o) {
try {
Folder other = (Folder) o;
- return this.path.equalsIgnoreCase(other.path);
- }catch (ClassCastException e){
+ return TextUtils.equals(other.path, path);
+ } catch (ClassCastException e) {
e.printStackTrace();
}
return super.equals(o);
diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Image.java b/library/src/main/java/me/nereo/multi_image_selector/bean/Image.java
similarity index 84%
rename from multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Image.java
rename to library/src/main/java/me/nereo/multi_image_selector/bean/Image.java
index 101746f..e800df7 100644
--- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Image.java
+++ b/library/src/main/java/me/nereo/multi_image_selector/bean/Image.java
@@ -9,7 +9,7 @@ public class Image {
public String name;
public long time;
- public Image(String path, String name, long time){
+ public Image(String path, String name, long time) {
this.path = path;
this.name = name;
this.time = time;
@@ -20,9 +20,9 @@ public boolean equals(Object o) {
try {
Image other = (Image) o;
return this.path.equalsIgnoreCase(other.path);
- }catch (ClassCastException e){
+ } catch (ClassCastException e) {
e.printStackTrace();
}
return super.equals(o);
}
-}
+}
\ No newline at end of file
diff --git a/library/src/main/java/me/nereo/multi_image_selector/utils/Constants.java b/library/src/main/java/me/nereo/multi_image_selector/utils/Constants.java
new file mode 100644
index 0000000..efffa3e
--- /dev/null
+++ b/library/src/main/java/me/nereo/multi_image_selector/utils/Constants.java
@@ -0,0 +1,42 @@
+package me.nereo.multi_image_selector.utils;
+
+public class Constants {
+ public static final String DATE_PATTERN = "yyyy-MM-dd";
+ /**
+ * 默认选择的数据集
+ */
+ public static final String EXTRA_DEFAULT_SELECTED_LIST = "default_result";
+ public static final String EXTRA_LOG = "log";
+ /**
+ * 选择结果,返回为 ArrayList<String> 图片路径集合
+ */
+ public static final String EXTRA_RESULT = "select_result";
+ /**
+ * 最大图片选择次数,int类型
+ */
+ public static final String EXTRA_SELECT_COUNT = "max_select_count";
+ /**
+ * 图片选择模式,int类型
+ */
+ public static final String EXTRA_SELECT_MODE = "select_count_mode";
+ /**
+ * 是否显示相机,boolean类型
+ */
+ public static final String EXTRA_SHOW_CAMERA = "show_camera";
+ // 不同loader定义
+ public static final int LOADER_ALL = 0;
+ public static final int LOADER_CATEGORY = 1;
+ /**
+ * 多选
+ */
+ public static final int MODE_MULTI = 1;
+ /**
+ * 单选
+ */
+ public static final int MODE_SINGLE = 0;
+ // 请求加载系统照相机
+ public static final int REQUEST_CAMERA = 100;
+ public static final String TAG = "MultiImageSelector";
+ // Default selecting images count
+ public static final int DEFAULT_SELECTING_COUNT = -1;
+}
diff --git a/library/src/main/java/me/nereo/multi_image_selector/utils/FileUtils.java b/library/src/main/java/me/nereo/multi_image_selector/utils/FileUtils.java
new file mode 100644
index 0000000..1ffdd98
--- /dev/null
+++ b/library/src/main/java/me/nereo/multi_image_selector/utils/FileUtils.java
@@ -0,0 +1,127 @@
+package me.nereo.multi_image_selector.utils;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Environment;
+import android.text.TextUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+import static android.os.Environment.MEDIA_MOUNTED;
+
+/**
+ * 文件操作类
+ * Created by Nereo on 2015/4/8.
+ */
+public class FileUtils {
+
+ private static final String JPEG_FILE_PREFIX = "IMG_";
+ private static final String JPEG_FILE_SUFFIX = ".jpg";
+ private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";
+
+ public static File createTmpFile(Context context) throws IOException {
+ File dir = null;
+ if (TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)) {
+ dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
+ if (!dir.exists()) {
+ dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM + "/Camera");
+ if (!dir.exists()) {
+ dir = getCacheDirectory(context, true);
+ }
+ }
+ } else {
+ dir = getCacheDirectory(context, true);
+ }
+ return File.createTempFile(JPEG_FILE_PREFIX, JPEG_FILE_SUFFIX, dir);
+ }
+
+ /**
+ * Returns application cache directory. Cache directory will be created on SD card
+ * ("/Android/data/[app_package_name]/cache") (if card is mounted and app has appropriate permission) or
+ * on device's file system depending incoming parameters.
+ *
+ * @param context Application context
+ * @param preferExternal Whether prefer external location for cache
+ * @return Cache {@link File directory}.
+ * NOTE: Can be null in some unpredictable cases (if SD card is unmounted and
+ * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
+ */
+ public static File getCacheDirectory(Context context, boolean preferExternal) {
+ File appCacheDir = null;
+ String externalStorageState;
+ try {
+ externalStorageState = Environment.getExternalStorageState();
+ } catch (NullPointerException e) { // (sh)it happens (Issue #660)
+ externalStorageState = "";
+ } catch (IncompatibleClassChangeError e) { // (sh)it happens too (Issue #989)
+ externalStorageState = "";
+ }
+ if (preferExternal && MEDIA_MOUNTED.equals(externalStorageState) && hasExternalStoragePermission(context)) {
+ appCacheDir = getExternalCacheDir(context);
+ }
+ if (appCacheDir == null) {
+ appCacheDir = context.getCacheDir();
+ }
+ if (appCacheDir == null) {
+ String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
+ appCacheDir = new File(cacheDirPath);
+ }
+ return appCacheDir;
+ }
+
+ private static boolean hasExternalStoragePermission(Context context) {
+ int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);
+ return perm == PackageManager.PERMISSION_GRANTED;
+ }
+
+ private static File getExternalCacheDir(Context context) {
+ File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
+ File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
+ if (!appCacheDir.exists()) {
+ if (!appCacheDir.mkdirs()) {
+ return null;
+ }
+ try {
+ new File(appCacheDir, ".nomedia").createNewFile();
+ } catch (IOException e) {
+ }
+ }
+ return appCacheDir;
+ }
+
+ /**
+ * Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be
+ * created on SD card ("/Android/data/[app_package_name]/cache/uil-images") if card is mounted and app has
+ * appropriate permission. Else - Android defines cache directory on device's file system.
+ *
+ * @param context Application context
+ * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
+ * @return Cache {@link File directory}
+ */
+ public static File getIndividualCacheDirectory(Context context, String cacheDir) {
+ File appCacheDir = getCacheDirectory(context);
+ File individualCacheDir = new File(appCacheDir, cacheDir);
+ if (!individualCacheDir.exists()) {
+ if (!individualCacheDir.mkdir()) {
+ individualCacheDir = appCacheDir;
+ }
+ }
+ return individualCacheDir;
+ }
+
+ /**
+ * Returns application cache directory. Cache directory will be created on SD card
+ * ("/Android/data/[app_package_name]/cache") if card is mounted and app has appropriate permission. Else -
+ * Android defines cache directory on device's file system.
+ *
+ * @param context Application context
+ * @return Cache {@link File directory}.
+ * NOTE: Can be null in some unpredictable cases (if SD card is unmounted and
+ * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
+ */
+ public static File getCacheDirectory(Context context) {
+ return getCacheDirectory(context, true);
+ }
+
+}
\ No newline at end of file
diff --git a/library/src/main/java/me/nereo/multi_image_selector/utils/ScreenUtils.java b/library/src/main/java/me/nereo/multi_image_selector/utils/ScreenUtils.java
new file mode 100644
index 0000000..5b6a9b6
--- /dev/null
+++ b/library/src/main/java/me/nereo/multi_image_selector/utils/ScreenUtils.java
@@ -0,0 +1,29 @@
+package me.nereo.multi_image_selector.utils;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.os.Build;
+import android.view.Display;
+import android.view.WindowManager;
+
+/**
+ * 屏幕工具
+ * Created by nereo on 15/11/19.
+ * Updated by nereo on 2016/1/19.
+ */
+public class ScreenUtils {
+
+ public static Point getScreenSize(Context context) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ Point out = new Point();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
+ display.getSize(out);
+ } else {
+ int width = display.getWidth();
+ int height = display.getHeight();
+ out.set(width, height);
+ }
+ return out;
+ }
+}
\ No newline at end of file
diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/utils/TimeUtils.java b/library/src/main/java/me/nereo/multi_image_selector/utils/TimeUtils.java
similarity index 54%
rename from multi-image-selector/src/main/java/me/nereo/multi_image_selector/utils/TimeUtils.java
rename to library/src/main/java/me/nereo/multi_image_selector/utils/TimeUtils.java
index 95740eb..9d5a0de 100644
--- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/utils/TimeUtils.java
+++ b/library/src/main/java/me/nereo/multi_image_selector/utils/TimeUtils.java
@@ -1,9 +1,6 @@
package me.nereo.multi_image_selector.utils;
-import android.media.ExifInterface;
-
import java.io.File;
-import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
@@ -14,21 +11,21 @@
*/
public class TimeUtils {
- public static String timeFormat(long timeMillis, String pattern){
- SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.CHINA);
- return format.format(new Date(timeMillis));
- }
-
- public static String formatPhotoDate(long time){
- return timeFormat(time, "yyyy-MM-dd");
- }
-
- public static String formatPhotoDate(String path){
+ public static String formatPhotoDate(String path) {
File file = new File(path);
- if(file.exists()){
+ if (file.exists()) {
long time = file.lastModified();
return formatPhotoDate(time);
}
return "1970-01-01";
}
+
+ private static String formatPhotoDate(long time) {
+ return timeFormat(time);
+ }
+
+ private static String timeFormat(long timeMillis) {
+ SimpleDateFormat format = new SimpleDateFormat(Constants.DATE_PATTERN, Locale.getDefault());
+ return format.format(new Date(timeMillis));
+ }
}
diff --git a/library/src/main/java/me/nereo/multi_image_selector/view/SquareFrameLayout.java b/library/src/main/java/me/nereo/multi_image_selector/view/SquareFrameLayout.java
new file mode 100644
index 0000000..35a8a70
--- /dev/null
+++ b/library/src/main/java/me/nereo/multi_image_selector/view/SquareFrameLayout.java
@@ -0,0 +1,24 @@
+package me.nereo.multi_image_selector.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * Created by nereo on 15/11/10.
+ */
+public class SquareFrameLayout extends FrameLayout {
+ public SquareFrameLayout(Context context) {
+ super(context);
+ }
+
+ public SquareFrameLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/me/nereo/multi_image_selector/view/SquaredImageView.java b/library/src/main/java/me/nereo/multi_image_selector/view/SquaredImageView.java
new file mode 100644
index 0000000..fd56f98
--- /dev/null
+++ b/library/src/main/java/me/nereo/multi_image_selector/view/SquaredImageView.java
@@ -0,0 +1,24 @@
+package me.nereo.multi_image_selector.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+/**
+ * An image view which always remains square with respect to its width.
+ */
+class SquaredImageView extends ImageView {
+ public SquaredImageView(Context context) {
+ super(context);
+ }
+
+ public SquaredImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/res/color/default_text_color.xml b/library/src/main/res/color/default_text_color.xml
new file mode 100644
index 0000000..b8d73b3
--- /dev/null
+++ b/library/src/main/res/color/default_text_color.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/color/folder_text_color.xml b/library/src/main/res/color/folder_text_color.xml
new file mode 100644
index 0000000..c55ec34
--- /dev/null
+++ b/library/src/main/res/color/folder_text_color.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/drawable-hdpi/ic_camera.png b/library/src/main/res/drawable-hdpi/ic_camera.png
new file mode 100644
index 0000000..558b547
Binary files /dev/null and b/library/src/main/res/drawable-hdpi/ic_camera.png differ
diff --git a/library/src/main/res/drawable-mdpi/ic_camera.png b/library/src/main/res/drawable-mdpi/ic_camera.png
new file mode 100644
index 0000000..8edb547
Binary files /dev/null and b/library/src/main/res/drawable-mdpi/ic_camera.png differ
diff --git a/multi-image-selector/src/main/res/drawable-xhdpi/btn_back.png b/library/src/main/res/drawable-xhdpi/btn_back.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xhdpi/btn_back.png
rename to library/src/main/res/drawable-xhdpi/btn_back.png
diff --git a/multi-image-selector/src/main/res/drawable-xhdpi/default_check_s.png b/library/src/main/res/drawable-xhdpi/default_check_s.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xhdpi/default_check_s.png
rename to library/src/main/res/drawable-xhdpi/default_check_s.png
diff --git a/library/src/main/res/drawable-xhdpi/ic_camera.png b/library/src/main/res/drawable-xhdpi/ic_camera.png
new file mode 100644
index 0000000..e688ca9
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/ic_camera.png differ
diff --git a/multi-image-selector/src/main/res/drawable-xhdpi/ic_menu_back.png b/library/src/main/res/drawable-xhdpi/ic_menu_back.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xhdpi/ic_menu_back.png
rename to library/src/main/res/drawable-xhdpi/ic_menu_back.png
diff --git a/multi-image-selector/src/main/res/drawable-xhdpi/selector_indicator.png b/library/src/main/res/drawable-xhdpi/selector_indicator.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xhdpi/selector_indicator.png
rename to library/src/main/res/drawable-xhdpi/selector_indicator.png
diff --git a/multi-image-selector/src/main/res/drawable-xxhdpi/asv.png b/library/src/main/res/drawable-xxhdpi/asv.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xxhdpi/asv.png
rename to library/src/main/res/drawable-xxhdpi/asv.png
diff --git a/multi-image-selector/src/main/res/drawable-xxhdpi/btn_selected.png b/library/src/main/res/drawable-xxhdpi/btn_selected.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xxhdpi/btn_selected.png
rename to library/src/main/res/drawable-xxhdpi/btn_selected.png
diff --git a/multi-image-selector/src/main/res/drawable-xxhdpi/btn_unselected.png b/library/src/main/res/drawable-xxhdpi/btn_unselected.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xxhdpi/btn_unselected.png
rename to library/src/main/res/drawable-xxhdpi/btn_unselected.png
diff --git a/multi-image-selector/src/main/res/drawable-xxhdpi/default_check.png b/library/src/main/res/drawable-xxhdpi/default_check.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xxhdpi/default_check.png
rename to library/src/main/res/drawable-xxhdpi/default_check.png
diff --git a/multi-image-selector/src/main/res/drawable-xxhdpi/default_error.png b/library/src/main/res/drawable-xxhdpi/default_error.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xxhdpi/default_error.png
rename to library/src/main/res/drawable-xxhdpi/default_error.png
diff --git a/library/src/main/res/drawable-xxhdpi/ic_camera.png b/library/src/main/res/drawable-xxhdpi/ic_camera.png
new file mode 100644
index 0000000..1e5be05
Binary files /dev/null and b/library/src/main/res/drawable-xxhdpi/ic_camera.png differ
diff --git a/multi-image-selector/src/main/res/drawable-xxhdpi/text_indicator.png b/library/src/main/res/drawable-xxhdpi/text_indicator.png
similarity index 100%
rename from multi-image-selector/src/main/res/drawable-xxhdpi/text_indicator.png
rename to library/src/main/res/drawable-xxhdpi/text_indicator.png
diff --git a/library/src/main/res/drawable-xxxhdpi/ic_camera.png b/library/src/main/res/drawable-xxxhdpi/ic_camera.png
new file mode 100644
index 0000000..e94b235
Binary files /dev/null and b/library/src/main/res/drawable-xxxhdpi/ic_camera.png differ
diff --git a/multi-image-selector/src/main/res/drawable/action_btn.xml b/library/src/main/res/drawable/action_btn.xml
similarity index 59%
rename from multi-image-selector/src/main/res/drawable/action_btn.xml
rename to library/src/main/res/drawable/action_btn.xml
index dcd2cbb..09651db 100644
--- a/multi-image-selector/src/main/res/drawable/action_btn.xml
+++ b/library/src/main/res/drawable/action_btn.xml
@@ -3,29 +3,29 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/multi-image-selector/src/main/res/layout-v14/fragment_multi_image.xml b/library/src/main/res/layout-v14/fragment_multi_image.xml
similarity index 64%
rename from multi-image-selector/src/main/res/layout-v14/fragment_multi_image.xml
rename to library/src/main/res/layout-v14/fragment_multi_image.xml
index 1b41929..7e28d42 100644
--- a/multi-image-selector/src/main/res/layout-v14/fragment_multi_image.xml
+++ b/library/src/main/res/layout-v14/fragment_multi_image.xml
@@ -1,82 +1,70 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/black">
-
-
+ android:paddingBottom="?android:attr/actionBarSize"
+ android:verticalSpacing="@dimen/space_size"/>
+ android:layout_height="?android:attr/actionBarSize"
+ android:layout_alignParentBottom="true"
+ android:background="#cc000000"
+ android:clickable="true">
+ android:textColor="@color/folder_text_color"
+ android:textSize="16sp"
+ tools:text="All photos"/>
+ android:visibility="gone"/>
+ android:visibility="gone"
+ tools:text="Preview (1)"/>
-
+
diff --git a/library/src/main/res/layout/activity_default.xml b/library/src/main/res/layout/activity_default.xml
new file mode 100644
index 0000000..9dc628f
--- /dev/null
+++ b/library/src/main/res/layout/activity_default.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
diff --git a/multi-image-selector/src/main/res/layout/cmp_customer_actionbar.xml b/library/src/main/res/layout/cmp_customer_actionbar.xml
similarity index 53%
rename from multi-image-selector/src/main/res/layout/cmp_customer_actionbar.xml
rename to library/src/main/res/layout/cmp_customer_actionbar.xml
index e2266e7..9422d50 100644
--- a/multi-image-selector/src/main/res/layout/cmp_customer_actionbar.xml
+++ b/library/src/main/res/layout/cmp_customer_actionbar.xml
@@ -1,43 +1,51 @@
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#21282C"
+ android:orientation="vertical">
+ android:src="@drawable/btn_back"/>
+ android:textSize="20sp"/>
+ android:textSize="14sp"/>
\ No newline at end of file
diff --git a/multi-image-selector/src/main/res/layout/fragment_multi_image.xml b/library/src/main/res/layout/fragment_multi_image.xml
similarity index 62%
rename from multi-image-selector/src/main/res/layout/fragment_multi_image.xml
rename to library/src/main/res/layout/fragment_multi_image.xml
index b41e16e..bdd1a9e 100644
--- a/multi-image-selector/src/main/res/layout/fragment_multi_image.xml
+++ b/library/src/main/res/layout/fragment_multi_image.xml
@@ -1,81 +1,71 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/black">
-
-
+ android:verticalSpacing="@dimen/space_size"/>
+ android:layout_height="?android:attr/actionBarSize"
+ android:layout_alignParentBottom="true"
+ android:background="#cc000000"
+ android:clickable="true">
+ tools:text="All photos"/>
+ android:visibility="gone"/>
+ android:visibility="gone"
+ tools:text="Preview (1)"/>
-
+
diff --git a/library/src/main/res/layout/list_item_camera.xml b/library/src/main/res/layout/list_item_camera.xml
new file mode 100644
index 0000000..9eb725e
--- /dev/null
+++ b/library/src/main/res/layout/list_item_camera.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/layout/list_item_folder.xml b/library/src/main/res/layout/list_item_folder.xml
new file mode 100644
index 0000000..d903f48
--- /dev/null
+++ b/library/src/main/res/layout/list_item_folder.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/layout/list_item_image.xml b/library/src/main/res/layout/list_item_image.xml
new file mode 100644
index 0000000..d694e53
--- /dev/null
+++ b/library/src/main/res/layout/list_item_image.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/multi-image-selector/src/main/res/values-sw360dp/dimens.xml b/library/src/main/res/values-sw360dp/dimens.xml
similarity index 100%
rename from multi-image-selector/src/main/res/values-sw360dp/dimens.xml
rename to library/src/main/res/values-sw360dp/dimens.xml
diff --git a/multi-image-selector/src/main/res/values-sw480dp/dimens.xml b/library/src/main/res/values-sw480dp/dimens.xml
similarity index 100%
rename from multi-image-selector/src/main/res/values-sw480dp/dimens.xml
rename to library/src/main/res/values-sw480dp/dimens.xml
diff --git a/multi-image-selector/src/main/res/values-sw720dp/dimens.xml b/library/src/main/res/values-sw720dp/dimens.xml
similarity index 100%
rename from multi-image-selector/src/main/res/values-sw720dp/dimens.xml
rename to library/src/main/res/values-sw720dp/dimens.xml
diff --git a/multi-image-selector/src/main/res/values/dimens.xml b/library/src/main/res/values/dimens.xml
similarity index 100%
rename from multi-image-selector/src/main/res/values/dimens.xml
rename to library/src/main/res/values/dimens.xml
diff --git a/library/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml
new file mode 100644
index 0000000..eb6c555
--- /dev/null
+++ b/library/src/main/res/values/strings.xml
@@ -0,0 +1,17 @@
+
+ multi-image-selector
+ All Images
+ Preview
+ No system camera found
+ Select images amount is limit (limited to %1$d)
+ Complete
+ Complete (%1$d/%2$d)
+ Preview (%1$d)
+ Take Photo
+ Select photo(s)
+ Back.
+ Select.
+ Select photo
+ Multiple choice with 0 count is illegal.
+ Picture Error
+
diff --git a/multi-image-selector/build.gradle b/multi-image-selector/build.gradle
deleted file mode 100644
index 397c989..0000000
--- a/multi-image-selector/build.gradle
+++ /dev/null
@@ -1,25 +0,0 @@
-apply plugin: 'com.android.library'
-
-android {
- compileSdkVersion 22
- buildToolsVersion "22.0.1"
-
- defaultConfig {
- minSdkVersion 12
- targetSdkVersion 22
- versionCode 1
- versionName "1.0"
- }
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
- }
-}
-
-dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- compile 'com.android.support:appcompat-v7:22.0.0'
- compile 'com.squareup.picasso:picasso:2.4.0'
-}
diff --git a/multi-image-selector/multi-image-selector.iml b/multi-image-selector/multi-image-selector.iml
deleted file mode 100644
index 325fdde..0000000
--- a/multi-image-selector/multi-image-selector.iml
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
-
-