From f652b432da94e377170d79f1f5dbd230fb31abff Mon Sep 17 00:00:00 2001 From: Nereo Date: Wed, 18 May 2016 14:22:56 +0800 Subject: [PATCH] support android M --- .idea/misc.xml | 27 +++ app/app.iml | 45 ++-- app/build.gradle | 8 +- app/src/main/AndroidManifest.xml | 2 - .../multiimageselector/MainActivity.java | 115 +++++++---- app/src/main/res/values/styles.xml | 4 + multi-image-selector/build.gradle | 8 +- multi-image-selector/multi-image-selector.iml | 31 +-- .../MultiImageSelector.java | 101 +++++++++ .../MultiImageSelectorActivity.java | 163 +++++++++------ .../MultiImageSelectorFragment.java | 193 +++++++++--------- .../adapter/FolderAdapter.java | 18 +- .../multi_image_selector/bean/Image.java | 4 +- .../res/layout-v14/fragment_multi_image.xml | 23 --- .../src/main/res/layout/activity_default.xml | 34 ++- .../main/res/layout/fragment_multi_image.xml | 23 --- .../src/main/res/values-zh/strings.xml | 7 + .../src/main/res/values/colors.xml | 4 + .../src/main/res/values/strings.xml | 8 + .../src/main/res/values/styles.xml | 4 + 20 files changed, 520 insertions(+), 302 deletions(-) create mode 100644 multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelector.java create mode 100644 multi-image-selector/src/main/res/values/colors.xml create mode 100644 multi-image-selector/src/main/res/values/styles.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index fb50338..671fecf 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,8 @@ + + + + + + + diff --git a/app/app.iml b/app/app.iml index 79503c2..ab0e9d3 100644 --- a/app/app.iml +++ b/app/app.iml @@ -64,14 +64,6 @@ - - - - - - - - @@ -80,29 +72,54 @@ + + + + + + + + + + + - - + + + + + + + + + + + + + + - + - + + + - - + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 5c156f5..6536c30 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 23 + buildToolsVersion "23.0.3" defaultConfig { applicationId "me.nereo.multiimageselector" minSdkVersion 12 - targetSdkVersion 22 + targetSdkVersion 23 versionCode 1 versionName "1.0" } @@ -21,6 +21,6 @@ android { dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:appcompat-v7:22.0.0' + compile 'com.android.support:appcompat-v7:23.4.0' compile project(':multi-image-selector') } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f8fd7c9..f0fbd7c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,8 +24,6 @@ android:configChanges="orientation|screenSize" android:name="me.nereo.multi_image_selector.MultiImageSelectorActivity" /> - - diff --git a/app/src/main/java/me/nereo/multiimageselector/MainActivity.java b/app/src/main/java/me/nereo/multiimageselector/MainActivity.java index 2b7d23f..61d2622 100644 --- a/app/src/main/java/me/nereo/multiimageselector/MainActivity.java +++ b/app/src/main/java/me/nereo/multiimageselector/MainActivity.java @@ -1,10 +1,16 @@ package me.nereo.multiimageselector; +import android.Manifest; +import android.content.DialogInterface; import android.content.Intent; -import android.support.v7.app.ActionBarActivity; +import android.content.pm.PackageManager; +import android.os.Build; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v7.app.AlertDialog; +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; @@ -13,14 +19,15 @@ import android.widget.TextView; import java.util.ArrayList; -import java.util.List; -import me.nereo.multi_image_selector.MultiImageSelectorActivity; +import me.nereo.multi_image_selector.MultiImageSelector; -public class MainActivity extends ActionBarActivity { +public class MainActivity extends AppCompatActivity { private static final int REQUEST_IMAGE = 2; + protected static final int REQUEST_STORAGE_READ_ACCESS_PERMISSION = 101; + protected static final int REQUEST_STORAGE_WRITE_ACCESS_PERMISSION = 102; private TextView mResultText; private RadioGroup mChoiceMode, mShowCamera; @@ -50,48 +57,76 @@ public void onCheckedChanged(RadioGroup radioGroup, int checkedId) { } }); - 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; + View button = findViewById(R.id.button); + if (button != null) { + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + pickImage(); } + }); + } - boolean showCamera = mShowCamera.getCheckedRadioButtonId() == R.id.show; + } - int maxNum = 9; - if(!TextUtils.isEmpty(mRequestNum.getText())){ + private void pickImage() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN // Permission was added in API Level 16 + && ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + requestPermission(Manifest.permission.READ_EXTERNAL_STORAGE, + getString(R.string.permission_rationale), + REQUEST_STORAGE_READ_ACCESS_PERMISSION); + }else { + boolean showCamera = mShowCamera.getCheckedRadioButtonId() == R.id.show; + int maxNum = 9; + + if (!TextUtils.isEmpty(mRequestNum.getText())) { + try { maxNum = Integer.valueOf(mRequestNum.getText().toString()); + } catch (NumberFormatException e) { + e.printStackTrace(); } - - 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); - } - }); + MultiImageSelector selector = MultiImageSelector.create(MainActivity.this); + selector.showCamera(showCamera); + selector.count(maxNum); + if (mChoiceMode.getCheckedRadioButtonId() == R.id.single) { + selector.single(); + } else { + selector.multi(); + } + selector.origin(mSelectPath); + selector.start(MainActivity.this, 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); + private void requestPermission(final String permission, String rationale, final int requestCode){ + if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){ + new AlertDialog.Builder(this) + .setTitle(R.string.permission_dialog_title) + .setMessage(rationale) + .setPositiveButton(R.string.permission_dialog_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode); + } + }) + .setNegativeButton(R.string.permission_dialog_cancel, null) + .create().show(); + }else{ + ActivityCompat.requestPermissions(this, new String[]{permission}, requestCode); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if(requestCode == REQUEST_STORAGE_READ_ACCESS_PERMISSION){ + if(grantResults[0] == PackageManager.PERMISSION_GRANTED){ + pickImage(); } - });*/ + } else { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } } @Override @@ -99,7 +134,7 @@ 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); + mSelectPath = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); StringBuilder sb = new StringBuilder(); for(String p: mSelectPath){ sb.append(p); diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 766ab99..410551f 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -5,4 +5,8 @@ + + diff --git a/multi-image-selector/build.gradle b/multi-image-selector/build.gradle index 397c989..a0016bc 100644 --- a/multi-image-selector/build.gradle +++ b/multi-image-selector/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 23 + buildToolsVersion "23.0.3" defaultConfig { minSdkVersion 12 - targetSdkVersion 22 + targetSdkVersion 23 versionCode 1 versionName "1.0" } @@ -20,6 +20,6 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:22.0.0' + compile 'com.android.support:appcompat-v7:23.4.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 index 6606864..85878f9 100644 --- a/multi-image-selector/multi-image-selector.iml +++ b/multi-image-selector/multi-image-selector.iml @@ -65,14 +65,6 @@ - - - - - - - - @@ -81,26 +73,41 @@ + + + + + + + + + + + + + - + - + + + - - + + \ No newline at end of file diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelector.java b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelector.java new file mode 100644 index 0000000..a23c2cd --- /dev/null +++ b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelector.java @@ -0,0 +1,101 @@ +package me.nereo.multi_image_selector; + +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.widget.Toast; + +import java.util.ArrayList; + +/** + * 图片选择器 + * Created by nereo on 16/3/17. + */ +public class MultiImageSelector { + + public static final String EXTRA_RESULT = MultiImageSelectorActivity.EXTRA_RESULT; + + private boolean mShowCamera = true; + private int mMaxCount = 9; + private int mMode = MultiImageSelectorActivity.MODE_MULTI; + private ArrayList mOriginData; + private static MultiImageSelector sSelector; + private Context mContext; + + private MultiImageSelector(Context context){ + mContext = context; + } + + public static MultiImageSelector create(Context context){ + if(sSelector == null){ + sSelector = new MultiImageSelector(context); + } + return sSelector; + } + + public MultiImageSelector showCamera(boolean show){ + mShowCamera = show; + return sSelector; + } + + public MultiImageSelector count(int count){ + mMaxCount = count; + return sSelector; + } + + public MultiImageSelector single(){ + mMode = MultiImageSelectorActivity.MODE_SINGLE; + return sSelector; + } + + public MultiImageSelector multi(){ + mMode = MultiImageSelectorActivity.MODE_MULTI; + return sSelector; + } + + public MultiImageSelector origin(ArrayList images){ + mOriginData = images; + return sSelector; + } + + public void start(Activity activity, int requestCode){ + if(hasPermission()) { + activity.startActivityForResult(createIntent(), requestCode); + }else{ + Toast.makeText(mContext, R.string.error_no_permission, Toast.LENGTH_SHORT).show(); + } + } + + public void start(Fragment fragment, int requestCode){ + if(hasPermission()) { + fragment.startActivityForResult(createIntent(), requestCode); + }else{ + Toast.makeText(mContext, R.string.error_no_permission, Toast.LENGTH_SHORT).show(); + } + } + + private boolean hasPermission(){ + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){ + // Permission was added in API Level 16 + return ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED; + } + return true; + } + + private Intent createIntent(){ + Intent intent = new Intent(mContext, MultiImageSelectorActivity.class); + intent.putExtra(MultiImageSelectorActivity.EXTRA_SHOW_CAMERA, mShowCamera); + intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_COUNT, mMaxCount); + if(mOriginData != null){ + intent.putStringArrayListExtra(MultiImageSelectorActivity.EXTRA_DEFAULT_SELECTED_LIST, mOriginData); + } + intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_MODE, mMode); + return intent; + } +} diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java index 7e62f04..268bd46 100644 --- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java +++ b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorActivity.java @@ -1,10 +1,15 @@ package me.nereo.multi_image_selector; import android.content.Intent; +import android.graphics.Color; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.MenuItem; import android.view.View; import android.widget.Button; @@ -12,90 +17,126 @@ import java.util.ArrayList; /** - * 多图选择 + * Multi image selector * Created by Nereo on 2015/4/7. * Updated by nereo on 2016/1/19. + * Updated by nereo on 2016/5/18. */ -public class MultiImageSelectorActivity extends FragmentActivity implements MultiImageSelectorFragment.Callback{ +public class MultiImageSelectorActivity extends AppCompatActivity + implements MultiImageSelectorFragment.Callback{ - /** 最大图片选择次数,int类型,默认9 */ + // Single choice + public static final int MODE_SINGLE = 0; + // Multi choice + public static final int MODE_MULTI = 1; + + /** Max image size,int,{@link #DEFAULT_IMAGE_SIZE} by default */ public static final String EXTRA_SELECT_COUNT = "max_select_count"; - /** 图片选择模式,默认多选 */ + /** Select mode,{@link #MODE_MULTI} by default */ public static final String EXTRA_SELECT_MODE = "select_count_mode"; - /** 是否显示相机,默认显示 */ + /** Whether show camera,true by default */ public static final String EXTRA_SHOW_CAMERA = "show_camera"; - /** 选择结果,返回为 ArrayList<String> 图片路径集合 */ + /** Result data set,ArrayList<String>*/ public static final String EXTRA_RESULT = "select_result"; - /** 默认选择集 */ + /** Original data set */ public static final String EXTRA_DEFAULT_SELECTED_LIST = "default_list"; - - /** 单选 */ - public static final int MODE_SINGLE = 0; - /** 多选 */ - public static final int MODE_MULTI = 1; + // Default image size + private static final int DEFAULT_IMAGE_SIZE = 9; private ArrayList resultList = new ArrayList<>(); private Button mSubmitButton; - private int mDefaultCount; + private int mDefaultCount = DEFAULT_IMAGE_SIZE; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setTheme(R.style.NO_ACTIONBAR); setContentView(R.layout.activity_default); - Intent intent = getIntent(); - mDefaultCount = intent.getIntExtra(EXTRA_SELECT_COUNT, 9); - int mode = intent.getIntExtra(EXTRA_SELECT_MODE, MODE_MULTI); - boolean isShow = intent.getBooleanExtra(EXTRA_SHOW_CAMERA, true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + getWindow().setStatusBarColor(Color.BLACK); + } + + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + if(toolbar != null){ + setSupportActionBar(toolbar); + } + + final ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + + final Intent intent = getIntent(); + mDefaultCount = intent.getIntExtra(EXTRA_SELECT_COUNT, DEFAULT_IMAGE_SIZE); + final int mode = intent.getIntExtra(EXTRA_SELECT_MODE, MODE_MULTI); + final boolean isShow = intent.getBooleanExtra(EXTRA_SHOW_CAMERA, true); if(mode == MODE_MULTI && intent.hasExtra(EXTRA_DEFAULT_SELECTED_LIST)) { resultList = intent.getStringArrayListExtra(EXTRA_DEFAULT_SELECTED_LIST); } - 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); - bundle.putStringArrayList(MultiImageSelectorFragment.EXTRA_DEFAULT_SELECTED_LIST, resultList); + mSubmitButton = (Button) findViewById(R.id.commit); + if(mode == MODE_MULTI){ + updateDoneText(resultList); + mSubmitButton.setVisibility(View.VISIBLE); + mSubmitButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if(resultList != null && resultList.size() >0){ + // Notify success + Intent data = new Intent(); + data.putStringArrayListExtra(EXTRA_RESULT, resultList); + setResult(RESULT_OK, data); + }else{ + setResult(RESULT_CANCELED); + } + finish(); + } + }); + }else{ + mSubmitButton.setVisibility(View.GONE); + } + + if(savedInstanceState == null){ + 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); + bundle.putStringArrayList(MultiImageSelectorFragment.EXTRA_DEFAULT_SELECTED_LIST, resultList); - getSupportFragmentManager().beginTransaction() - .add(R.id.image_grid, Fragment.instantiate(this, MultiImageSelectorFragment.class.getName(), bundle)) - .commit(); + 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) { + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: setResult(RESULT_CANCELED); finish(); - } - }); + return true; + } + return super.onOptionsItemSelected(item); + } - // 完成按钮 - mSubmitButton = (Button) findViewById(R.id.commit); + /** + * Update done button by select image data + * @param resultList selected image data + */ + private void updateDoneText(ArrayList resultList){ + int size = 0; if(resultList == null || resultList.size()<=0){ mSubmitButton.setText(R.string.action_done); mSubmitButton.setEnabled(false); }else{ - updateDoneText(); + size = resultList.size(); 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(EXTRA_RESULT, resultList); - setResult(RESULT_OK, data); - finish(); - } - } - }); - } - - private void updateDoneText(){ - mSubmitButton.setText(String.format("%s(%d/%d)", - getString(R.string.action_done), resultList.size(), mDefaultCount)); + mSubmitButton.setText(getString(R.string.action_button_string, + getString(R.string.action_done), size, mDefaultCount)); } @Override @@ -112,13 +153,7 @@ public void onImageSelected(String path) { if(!resultList.contains(path)) { resultList.add(path); } - // 有图片之后,改变按钮状态 - if(resultList.size() > 0){ - updateDoneText(); - if(!mSubmitButton.isEnabled()){ - mSubmitButton.setEnabled(true); - } - } + updateDoneText(resultList); } @Override @@ -126,19 +161,13 @@ public void onImageUnselected(String path) { if(resultList.contains(path)){ resultList.remove(path); } - updateDoneText(); - // 当为选择图片时候的状态 - if(resultList.size() == 0){ - mSubmitButton.setText(R.string.action_done); - mSubmitButton.setEnabled(false); - } + updateDoneText(resultList); } @Override public void onCameraShot(File imageFile) { if(imageFile != null) { - - // notify system + // notify system the image has change sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageFile))); Intent data = new Intent(); diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java index d9d075e..950374e 100644 --- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java +++ b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/MultiImageSelectorFragment.java @@ -1,7 +1,11 @@ package me.nereo.multi_image_selector; +import android.Manifest; import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Color; @@ -11,11 +15,14 @@ import android.os.Bundle; import android.os.Handler; import android.provider.MediaStore; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; +import android.support.v4.content.ContextCompat; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.ListPopupWindow; import android.text.TextUtils; import android.view.LayoutInflater; @@ -23,7 +30,6 @@ import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; -import android.widget.Button; import android.widget.GridView; import android.widget.TextView; import android.widget.Toast; @@ -43,40 +49,44 @@ import me.nereo.multi_image_selector.utils.ScreenUtils; /** - * 图片选择Fragment + * Multi image selector Fragment * Created by Nereo on 2015/4/7. + * Updated by nereo on 2016/5/18. */ public class MultiImageSelectorFragment extends Fragment { - public static final String TAG = "me.nereo.multi_image_selector.MultiImageSelectorFragment"; + public static final String TAG = "MultiImageSelectorFragment"; + + private static final int REQUEST_STORAGE_WRITE_ACCESS_PERMISSION = 110; + private static final int REQUEST_CAMERA = 100; private static final String KEY_TEMP_FILE = "key_temp_file"; - /** 最大图片选择次数,int类型 */ + // Single choice + public static final int MODE_SINGLE = 0; + // Multi choice + public static final int MODE_MULTI = 1; + + /** Max image size,int,*/ public static final String EXTRA_SELECT_COUNT = "max_select_count"; - /** 图片选择模式,int类型 */ + /** Select mode,{@link #MODE_MULTI} by default */ public static final String EXTRA_SELECT_MODE = "select_count_mode"; - /** 是否显示相机,boolean类型 */ + /** Whether show camera,true by default */ 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定义 + /** Result data set,ArrayList<String>*/ + public static final String EXTRA_RESULT = "select_result"; + /** Original data set */ + public static final String EXTRA_DEFAULT_SELECTED_LIST = "default_list"; + + // loaders private static final int LOADER_ALL = 0; private static final int LOADER_CATEGORY = 1; - // 请求加载系统照相机 - private static final int REQUEST_CAMERA = 100; - - // 结果数据 + // image result data set private ArrayList resultList = new ArrayList<>(); - // 文件夹数据 + // folder result data set private ArrayList mResultFolder = new ArrayList<>(); - // 图片Grid private GridView mGridView; private Callback mCallback; @@ -85,11 +95,7 @@ public class MultiImageSelectorFragment extends Fragment { private ListPopupWindow mFolderPopupWindow; - // 类别 private TextView mCategoryText; - // 预览按钮 - private Button mPreviewBtn; - // 底部View private View mPopupAnchorView; private int mDesireImageCount; @@ -100,10 +106,10 @@ public class MultiImageSelectorFragment extends Fragment { private File mTmpFile; @Override - public void onAttach(Activity activity) { - super.onAttach(activity); + public void onAttach(Context context) { + super.onAttach(context); try { - mCallback = (Callback) activity; + mCallback = (Callback) getActivity(); }catch (ClassCastException e){ throw new ClassCastException("The Activity must implement MultiImageSelectorFragment.Callback interface..."); } @@ -118,13 +124,10 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - // 选择图片数量 mDesireImageCount = getArguments().getInt(EXTRA_SELECT_COUNT); - // 图片选择模式 final int mode = getArguments().getInt(EXTRA_SELECT_MODE); - // 默认选择 if(mode == MODE_MULTI) { ArrayList tmp = getArguments().getStringArrayList(EXTRA_DEFAULT_SELECTED_LIST); if(tmp != null && tmp.size()>0) { @@ -132,16 +135,13 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { } } - // 是否显示照相机 mIsShowCamera = getArguments().getBoolean(EXTRA_SHOW_CAMERA, true); mImageAdapter = new ImageGridAdapter(getActivity(), mIsShowCamera, 3); - // 是否显示选择指示器 mImageAdapter.showSelectIndicator(mode == MODE_MULTI); mPopupAnchorView = view.findViewById(R.id.footer); mCategoryText = (TextView) view.findViewById(R.id.category_btn); - // 初始化,加载所有图片 mCategoryText.setText(R.string.folder_all); mCategoryText.setOnClickListener(new View.OnClickListener() { @Override @@ -162,35 +162,19 @@ public void onClick(View view) { } }); - mPreviewBtn = (Button) view.findViewById(R.id.preview); - // 初始化,按钮状态初始化 - if(resultList == null || resultList.size()<=0){ - mPreviewBtn.setText(R.string.preview); - mPreviewBtn.setEnabled(false); - } - mPreviewBtn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - // TODO 预览 - } - }); - mGridView = (GridView) view.findViewById(R.id.grid); mGridView.setAdapter(mImageAdapter); mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { if (mImageAdapter.isShowCamera()) { - // 如果显示照相机,则第一个Grid显示为照相机,处理特殊逻辑 if (i == 0) { showCameraAction(); } else { - // 正常操作 Image image = (Image) adapterView.getAdapter().getItem(i); selectImageFromGrid(image, mode); } } else { - // 正常操作 Image image = (Image) adapterView.getAdapter().getItem(i); selectImageFromGrid(image, mode); } @@ -216,7 +200,7 @@ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCoun } /** - * 创建弹出的ListView + * Create popup ListView */ private void createPopupFolderList() { Point point = ScreenUtils.getScreenSize(getActivity()); @@ -257,7 +241,6 @@ public void run() { if (null != folder) { mImageAdapter.setData(folder.images); mCategoryText.setText(folder.name); - // 设定默认选择 if (resultList != null && resultList.size() > 0) { mImageAdapter.setDefaultSelected(resultList); } @@ -265,7 +248,6 @@ public void run() { mImageAdapter.setShowCamera(false); } - // 滑动到最初始位置 mGridView.smoothScrollToPosition(0); } }, 100); @@ -291,15 +273,13 @@ public void onViewStateRestored(@Nullable Bundle savedInstanceState) { @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - // 首次加载所有图片 - //new LoadImageTask().execute(); + // load image data 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) { @@ -329,67 +309,87 @@ public void onConfigurationChanged(Configuration newConfig) { } /** - * 选择相机 + * Open camera */ private void showCameraAction() { - // 跳转到系统照相机 - Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - if(cameraIntent.resolveActivity(getActivity().getPackageManager()) != null){ - // 设置系统相机拍照后的输出路径 - // 创建临时文件 - 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(), "图片错误", Toast.LENGTH_SHORT).show(); + if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED){ + requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, + getString(R.string.permission_rationale_write_storage), + REQUEST_STORAGE_WRITE_ACCESS_PERMISSION); + }else { + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (intent.resolveActivity(getActivity().getPackageManager()) != null) { + try { + mTmpFile = FileUtils.createTmpFile(getActivity()); + } catch (IOException e) { + e.printStackTrace(); + } + if (mTmpFile != null && mTmpFile.exists()) { + intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile)); + startActivityForResult(intent, REQUEST_CAMERA); + } else { + Toast.makeText(getActivity(), R.string.error_image_not_exist, Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(getActivity(), R.string.msg_no_camera, Toast.LENGTH_SHORT).show(); } + } + } + + private void requestPermission(final String permission, String rationale, final int requestCode){ + if(shouldShowRequestPermissionRationale(permission)){ + new AlertDialog.Builder(getContext()) + .setTitle(R.string.permission_dialog_title) + .setMessage(rationale) + .setPositiveButton(R.string.permission_dialog_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + requestPermissions(new String[]{permission}, requestCode); + } + }) + .setNegativeButton(R.string.permission_dialog_cancel, null) + .create().show(); }else{ - Toast.makeText(getActivity(), R.string.msg_no_camera, Toast.LENGTH_SHORT).show(); + requestPermissions(new String[]{permission}, requestCode); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if(requestCode == REQUEST_STORAGE_WRITE_ACCESS_PERMISSION){ + if(grantResults[0] == PackageManager.PERMISSION_GRANTED){ + showCameraAction(); + } + } else { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } /** - * 选择图片操作 - * @param image + * notify callback + * @param image image data */ private void selectImageFromGrid(Image image, int mode) { if(image != null) { - // 多选模式 if(mode == MODE_MULTI) { if (resultList.contains(image.path)) { resultList.remove(image.path); - if(resultList.size() != 0) { - mPreviewBtn.setEnabled(true); - mPreviewBtn.setText(getResources().getString(R.string.preview) + "(" + resultList.size() + ")"); - }else{ - mPreviewBtn.setEnabled(false); - mPreviewBtn.setText(R.string.preview); - } if (mCallback != null) { mCallback.onImageUnselected(image.path); } } else { - // 判断选择数量问题 if(mDesireImageCount == resultList.size()){ Toast.makeText(getActivity(), R.string.msg_amount_limit, Toast.LENGTH_SHORT).show(); return; } - resultList.add(image.path); - mPreviewBtn.setEnabled(true); - mPreviewBtn.setText(getResources().getString(R.string.preview) + "(" + resultList.size() + ")"); if (mCallback != null) { mCallback.onImageSelected(image.path); } } mImageAdapter.select(image); }else if(mode == MODE_SINGLE){ - // 单选模式 if(mCallback != null){ mCallback.onSingleImageSelected(image.path); } @@ -409,21 +409,19 @@ private void selectImageFromGrid(Image image, int mode) { @Override public Loader onCreateLoader(int id, Bundle args) { + CursorLoader cursorLoader = null; if(id == LOADER_ALL) { - CursorLoader cursorLoader = new CursorLoader(getActivity(), + cursorLoader = 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"); - return cursorLoader; }else if(id == LOADER_CATEGORY){ - CursorLoader cursorLoader = new CursorLoader(getActivity(), + cursorLoader = 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"); - return cursorLoader; } - - return null; + return cursorLoader; } private boolean fileExist(String path){ @@ -444,12 +442,12 @@ public void onLoadFinished(Loader loader, Cursor data) { String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1])); long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2])); Image image = null; - if (fileExist(path)) { + if (fileExist(path) && !TextUtils.isEmpty(name)) { image = new Image(path, name, dateTime); images.add(image); } - if( !hasFolderGened ) { - // 获取文件夹名称 + if( !hasFolderGened && fileExist(path)) { + // get all folder data File folderFile = new File(path).getParentFile(); if(folderFile != null && folderFile.exists()){ String fp = folderFile.getAbsolutePath(); @@ -472,16 +470,13 @@ public void onLoadFinished(Loader loader, Cursor data) { }while(data.moveToNext()); mImageAdapter.setData(images); - // 设定默认选择 if(resultList != null && resultList.size()>0){ mImageAdapter.setDefaultSelected(resultList); } - if(!hasFolderGened) { mFolderAdapter.setData(mResultFolder); hasFolderGened = true; } - } } } @@ -504,7 +499,7 @@ private Folder getFolderByPath(String path){ } /** - * 回调接口 + * Callback for host activity */ public interface Callback{ void onSingleImageSelected(String path); diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java index c51bd4c..bd09053 100644 --- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java +++ b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/adapter/FolderAdapter.java @@ -85,12 +85,16 @@ public View getView(int i, View view, ViewGroup viewGroup) { getTotalImageSize(), mContext.getResources().getString(R.string.photo_unit))); if(mFolders.size()>0){ Folder f = mFolders.get(0); - Picasso.with(mContext) - .load(new File(f.cover.path)) - .error(R.drawable.default_error) - .resizeDimen(R.dimen.folder_cover_size, R.dimen.folder_cover_size) - .centerCrop() - .into(holder.cover); + if (f != null) { + Picasso.with(mContext) + .load(new File(f.cover.path)) + .error(R.drawable.default_error) + .resizeDimen(R.dimen.folder_cover_size, R.dimen.folder_cover_size) + .centerCrop() + .into(holder.cover); + }else{ + holder.cover.setImageResource(R.drawable.default_error); + } } }else { holder.bindData(getItem(i)); @@ -151,8 +155,8 @@ void bindData(Folder data) { }else{ size.setText("*"+mContext.getResources().getString(R.string.photo_unit)); } - // 显示图片 if (data.cover != null) { + // 显示图片 Picasso.with(mContext) .load(new File(data.cover.path)) .placeholder(R.drawable.default_error) diff --git a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Image.java b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Image.java index 101746f..a06c0fb 100644 --- a/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Image.java +++ b/multi-image-selector/src/main/java/me/nereo/multi_image_selector/bean/Image.java @@ -1,5 +1,7 @@ package me.nereo.multi_image_selector.bean; +import android.text.TextUtils; + /** * 图片实体 * Created by Nereo on 2015/4/7. @@ -19,7 +21,7 @@ public Image(String path, String name, long time){ public boolean equals(Object o) { try { Image other = (Image) o; - return this.path.equalsIgnoreCase(other.path); + return TextUtils.equals(this.path, other.path); }catch (ClassCastException e){ e.printStackTrace(); } diff --git a/multi-image-selector/src/main/res/layout-v14/fragment_multi_image.xml b/multi-image-selector/src/main/res/layout-v14/fragment_multi_image.xml index a3373a5..ba19155 100644 --- a/multi-image-selector/src/main/res/layout-v14/fragment_multi_image.xml +++ b/multi-image-selector/src/main/res/layout-v14/fragment_multi_image.xml @@ -42,29 +42,6 @@ android:layout_width="wrap_content" android:layout_height="match_parent" /> - - -