提交 15230b0d 编写于 作者: N Nereo

fix issue#1, fixed issue#2

上级 4676bb68
......@@ -8,6 +8,10 @@ Image selector for Android device. Support single choice and multi-choice.
-------------------
###Run Demo
>./gradlew installDebug
###Quick Start
* Step 0
Add module `multi-image-selector` as your dependence.
......@@ -15,6 +19,11 @@ 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
<activity
android:configChanges="orientation|screenSize"
android:name="me.nereo.multi_image_selector.MultiImageSelectorActivity" />
```
* Step 2
Call image selector activity in your code, eg.
......@@ -101,6 +110,12 @@ class CustomerActivity extends Activity implements MultiImageSelectorFragment.Ca
1. Fixed. When set `EXTRA_SHOW_CAMERA` to `true`, the first grid item onclick event were messed.
2. Add. Support initial selected image list.
* 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.
-------------------
###Thanks
......
......@@ -8,6 +8,10 @@
-------------------
###运行DEMO
>./gradlew installDebug
###快速开始
* 第0步
把模块 `multi-image-selector` 作为你的项目依赖添加到工程中.
......@@ -15,6 +19,11 @@
* 第1步
在你的 `AndroidManifest.xml` 文件中添加权限 `android.permission.READ_EXTERNAL_STORAGE`.
别忘了同时在 `AndroidManifest.xml` 中声明 `MultiImageSelectorActivity` 这个Activity.
```xml
<activity
android:configChanges="orientation|screenSize"
android:name="me.nereo.multi_image_selector.MultiImageSelectorActivity" />
```
* 第2步
代码中调用,例如:
......@@ -101,6 +110,12 @@ class CustomerActivity extends Activity implements MultiImageSelectorFragment.Ca
1. 修复. 当设置 `EXTRA_SHOW_CAMERA``true` 时, 点击第一个Item会混乱的问题.
2. 新增. 支持初始化图片选择设定。
* 2015-4-16
1. 修复. 旋转设备时,程序会崩溃. (Issue by [@Leminity](https://github.com/Leminity))
2. 修复. 文件夹PopupListView位置错误. (Issue by [@Slock](https://github.com/Slock))
3. 更改. 演示程序截图.
4. 更改. Readme 文件.
-------------------
###感谢
......
<resources>
<string name="app_name">MultiImageSelector</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
</resources>
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="MultiImageSelector" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<module external.linked.project.id=":multi-image-selector" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="MultiImageSelector" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
......@@ -12,8 +12,9 @@
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
......@@ -86,10 +87,9 @@
</content>
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="appcompat-v7-22.0.0" level="project" />
<orderEntry type="library" exported="" name="picasso-2.5.2" level="project" />
<orderEntry type="library" exported="" name="support-v4-22.0.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-22.0.0" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-22.0.0" level="project" />
<orderEntry type="library" exported="" name="picasso-2.5.2" level="project" />
</component>
</module>
</module>
\ No newline at end of file
......@@ -3,6 +3,7 @@ package me.nereo.multi_image_selector;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
......@@ -14,6 +15,7 @@ import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.widget.ListPopupWindow;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
......@@ -44,6 +46,8 @@ import me.nereo.multi_image_selector.utils.TimeUtils;
*/
public class MultiImageSelectorFragment extends Fragment {
private static final String TAG = "MultiImageSelector";
/** 最大图片选择次数,int类型 */
public static final String EXTRA_SELECT_COUNT = "max_select_count";
/** 图片选择模式,int类型 */
......@@ -62,6 +66,7 @@ public class MultiImageSelectorFragment extends Fragment {
// 请求加载系统照相机
private static final int REQUEST_CAMERA = 100;
// 结果数据
private ArrayList<String> resultList = new ArrayList<>();
// 文件夹数据
......@@ -143,7 +148,7 @@ public class MultiImageSelectorFragment extends Fragment {
mCategoryText = (TextView) view.findViewById(R.id.category_btn);
// 初始化,加载所有图片
mCategoryText.setText("所有图片");
mCategoryText.setText(R.string.folder_all);
mCategoryText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
......@@ -161,7 +166,7 @@ public class MultiImageSelectorFragment extends Fragment {
mPreviewBtn = (Button) view.findViewById(R.id.preview);
// 初始化,按钮状态初始化
if(resultList == null || resultList.size()<=0){
mPreviewBtn.setText("预览");
mPreviewBtn.setText(R.string.preview);
mPreviewBtn.setEnabled(false);
}
mPreviewBtn.setOnClickListener(new View.OnClickListener() {
......@@ -206,10 +211,20 @@ public class MultiImageSelectorFragment extends Fragment {
mGridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onGlobalLayout() {
final int numCount = mGridView.getNumColumns();
final int width = mGridView.getWidth();
final int height = mGridView.getHeight();
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 = (mGridView.getWidth() - columnSpace*(numCount-1)) / numCount;
int columnWidth = (width - columnSpace*(numCount-1)) / numCount;
mImageAdapter.setItemSize(columnWidth);
if(mFolderPopupWindow == null){
createPopupFolderList(width, height);
}
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){
mGridView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}else{
......@@ -238,30 +253,26 @@ public class MultiImageSelectorFragment extends Fragment {
});
mFolderAdapter = new FolderAdapter(getActivity());
createPopupFolderList();
}
/**
* 创建弹出的ListView
*/
private void createPopupFolderList() {
private void createPopupFolderList(int width, int height) {
mFolderPopupWindow = new ListPopupWindow(getActivity());
// mFolderPopupWindow.getListView().setDividerHeight(1);
// mFolderPopupWindow.getListView().setDivider(new ColorDrawable(Color.parseColor("#CCCCCC")));
mFolderPopupWindow.setAdapter(mFolderAdapter);
int sWidthPix = getResources().getDisplayMetrics().widthPixels;
mFolderPopupWindow.setContentWidth(sWidthPix);
mFolderPopupWindow.setHeight(sWidthPix);
mFolderPopupWindow.setContentWidth(width);
mFolderPopupWindow.setHeight(height * 5/8);
mFolderPopupWindow.setAnchorView(mPopupAnchorView);
mFolderPopupWindow.setModal(true);
mFolderPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if(i == 0){
if (i == 0) {
getActivity().getSupportLoaderManager().restartLoader(LOADER_ALL, null, mLoaderCallback);
mCategoryText.setText("所有照片");
mCategoryText.setText(R.string.folder_all);
mImageAdapter.setShowCamera(true);
}else {
} else {
Folder folder = (Folder) adapterView.getAdapter().getItem(i);
if (null != folder) {
Bundle args = new Bundle();
......@@ -303,6 +314,49 @@ public class MultiImageSelectorFragment extends Fragment {
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.d(TAG, "on change");
final int orientation = newConfig.orientation;
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);
}
/**
* 选择相机
*/
......@@ -314,7 +368,7 @@ public class MultiImageSelectorFragment extends Fragment {
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile));
startActivityForResult(cameraIntent, REQUEST_CAMERA);
}else{
Toast.makeText(getActivity(), "没有系统相机", Toast.LENGTH_SHORT).show();
Toast.makeText(getActivity(), R.string.msg_no_camera, Toast.LENGTH_SHORT).show();
}
}
......@@ -330,10 +384,10 @@ public class MultiImageSelectorFragment extends Fragment {
resultList.remove(image.path);
if(resultList.size() != 0) {
mPreviewBtn.setEnabled(true);
mPreviewBtn.setText("预览(" + resultList.size() + ")");
mPreviewBtn.setText(getResources().getString(R.string.preview) + "(" + resultList.size() + ")");
}else{
mPreviewBtn.setEnabled(false);
mPreviewBtn.setText("预览");
mPreviewBtn.setText(R.string.preview);
}
if (mCallback != null) {
mCallback.onImageUnselected(image.path);
......@@ -341,13 +395,13 @@ public class MultiImageSelectorFragment extends Fragment {
} else {
// 判断选择数量问题
if(mDesireImageCount == resultList.size()){
Toast.makeText(getActivity(), "已经达到最高选择数量了…", Toast.LENGTH_SHORT).show();
Toast.makeText(getActivity(), R.string.msg_amount_limit, Toast.LENGTH_SHORT).show();
return;
}
resultList.add(image.path);
mPreviewBtn.setEnabled(true);
mPreviewBtn.setText("预览(" + resultList.size() + ")");
mPreviewBtn.setText(getResources().getString(R.string.preview) + "(" + resultList.size() + ")");
if (mCallback != null) {
mCallback.onImageSelected(image.path);
}
......@@ -432,8 +486,6 @@ public class MultiImageSelectorFragment extends Fragment {
mFolderAdapter.setData(mResultFolder);
hasFolderGened = true;
} else {
System.out.println("no image found");
}
}
}
......
......@@ -174,32 +174,11 @@ public class ImageGridAdapter extends BaseAdapter {
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
/* ViewHolde holde = null;
if(showCamera){
int type = getItemViewType(i);
if(view == null){
view = mInflater.inflate(R.layout.list_item_camera, viewGroup, false);
}else{
}
}else{
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) {
holde.bindData(getItem(i));
}*/
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){
......@@ -216,10 +195,13 @@ public class ImageGridAdapter extends BaseAdapter {
holde.bindData(getItem(i));
}
}
/** Fixed View Size */
GridView.LayoutParams lp = (GridView.LayoutParams) view.getLayoutParams();
if(lp.height != mItemSize){
view.setLayoutParams(mItemLayoutParams);
}
return view;
}
......@@ -249,14 +231,17 @@ public class ImageGridAdapter extends BaseAdapter {
indicator.setVisibility(View.GONE);
}
File imageFile = new File(data.path);
// 显示图片
Picasso.with(mContext)
.load(imageFile)
.placeholder(R.drawable.default_error)
//.error(R.drawable.default_error)
.resize(mItemSize, mItemSize)
.centerCrop()
.into(image);
if(mItemSize > 0) {
// 显示图片
Picasso.with(mContext)
.load(imageFile)
.placeholder(R.drawable.default_error)
//.error(R.drawable.default_error)
.resize(mItemSize, mItemSize)
.centerCrop()
.into(image);
}
}
}
......
......@@ -20,7 +20,7 @@ public class TimeUtils {
}
public static String formatPhotoDate(long time){
return timeFormat(time, "yyyy年MM月dd日");
return timeFormat(time, "yyyy-MM-dd");
}
public static String formatPhotoDate(String path){
......
package me.nereo.multi_image_selector.view;
import android.content.Context;
import android.graphics.Matrix;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ScaleGestureDetectorCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ViewConfiguration;
import android.widget.ImageView;
import android.widget.Toast;
/**
* 支持手势的ImageView
* Created by Nereo on 2015/4/10.
*/
public class GestureImageView extends ImageView{
private static final String TAG = "GestureImageView";
public GestureImageView(Context context) {
super(context);
init(context);
}
public GestureImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GestureImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private ScaleGestureDetector mScaleGesture;
private Matrix mImageMatrix;
private GestureDetectorCompat mGestureDetector;
// 最大缩放比例
private static final float MAX_SCALE_FACTOR = 3.0f;
// 最小缩放比例
private static final float MIN_SCALE_FACTOR = 0.3f;
// 系统常量,系统认为手指是否移动的最小距离
private int mTouchSlop;
private float mCurrentFactor = 1.0f;
private float mFirstPointerX, mFirstPointerY;
private float mSecondPointerX, mSecondPointerY;
private int mCenterX, mCenterY;
/**
* 初始化
* @param context
*/
private void init(final Context context){
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
setScaleType(ScaleType.MATRIX);
mImageMatrix = new Matrix();
mScaleGesture = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener(){
@Override
public boolean onScale(ScaleGestureDetector detector) {
float factor = detector.getScaleFactor();
mImageMatrix.postScale(factor, factor, mCenterX, mCenterY);
setImageMatrix(mImageMatrix);
return true;
}
});
mGestureDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onDoubleTap(MotionEvent e) {
mImageMatrix.postScale(1.f, 1.f, mCenterX, mCenterY);
setImageMatrix(mImageMatrix);
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//mImageMatrix.setTranslate(0, 0);
//setImageMatrix(mImageMatrix);
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
});
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if( w != oldw || h != oldh){
int cx = (w - getDrawable().getIntrinsicWidth()) / 2 ;
int cy = (h - getDrawable().getIntrinsicHeight()) / 2;
mImageMatrix.setTranslate(cx, cy);
setImageMatrix(mImageMatrix);
mCenterX = w / 2;
mCenterY = h / 2;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean retValue = mScaleGesture.onTouchEvent(event);
retValue = mGestureDetector.onTouchEvent(event) || retValue;
return retValue || super.onTouchEvent(event);
}
}
package me.nereo.multi_image_selector.view;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
/**
* 自定义ViewPager
* Created by Nereo on 2015/4/10.
*/
public class SuperViewPager extends ViewPager {
public SuperViewPager(Context context) {
super(context);
}
public SuperViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="@android:color/black"
android:layout_width="match_parent"
android:layout_height="match_parent">
......@@ -10,9 +11,10 @@
android:layout_height="match_parent"
android:horizontalSpacing="@dimen/space_size"
android:verticalSpacing="@dimen/space_size"
android:paddingBottom="48dp"
android:paddingBottom="?android:attr/actionBarSize"
android:clipToPadding="false"
android:numColumns="3"/>
android:numColumns="auto_fit"
android:columnWidth="@dimen/image_size"/>
<TextView
android:id="@+id/timeline_area"
......@@ -34,7 +36,7 @@
android:background="#cc000000"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="48dp">
android:layout_height="?android:attr/actionBarSize">
<TextView
android:id="@+id/category_btn"
......@@ -44,7 +46,7 @@
android:textColor="#CDCECE"
tools:text="所有图片"
android:textSize="16sp"
android:gravity="center"
android:gravity="center_vertical"
android:drawableRight="@drawable/text_indicator"
android:drawablePadding="5dp"
android:layout_width="wrap_content"
......
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="image_size">96dp</dimen>
<dimen name="space_size">2dp</dimen>
<dimen name="folder_cover_size">72dp</dimen>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="image_size">100dp</dimen>
<dimen name="space_size">2dp</dimen>
<dimen name="folder_cover_size">72dp</dimen>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="image_size">120dp</dimen>
<dimen name="space_size">3dp</dimen>
<dimen name="folder_cover_size">82dp</dimen>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">多图选择器</string>
<string name="folder_all">所有照片</string>
<string name="preview">预览</string>
<string name="msg_no_camera">没有系统相机</string>
<string name="msg_amount_limit">已经达到最高选择数量</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="image_size">120dp</dimen>
<dimen name="space_size">2dp</dimen>
<dimen name="folder_cover_size">72dp</dimen>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">multi-image-selector</string>
<string name="folder_all">All Images</string>
<string name="preview">Preview</string>
<string name="msg_no_camera">No system camera found</string>
<string name="msg_amount_limit">Select images amount is limit</string>
</resources>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册