This commit is contained in:
2020-08-03 09:11:54 +08:00
parent 537441d239
commit 06952bab00
737 changed files with 52091 additions and 0 deletions

View File

@@ -0,0 +1,174 @@
package imageselector;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import com.sl.house_property.R;
import java.io.File;
import java.util.ArrayList;
import imageselector.utils.ImageSelector;
import imageselector.utils.ImageUtil;
import imageselector.utils.StringUtils;
import imageselector.view.ClipImageView;
public class ClipImageActivity extends Activity {
private FrameLayout btnConfirm;
private FrameLayout btnBack;
private ClipImageView imageView;
private int mRequestCode;
private boolean isCameraImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_clip_image);
Intent intent = getIntent();
mRequestCode = intent.getIntExtra("requestCode", 0);
setStatusBarColor();
ImageSelectorActivity.openActivity(this, mRequestCode, true,
intent.getBooleanExtra(ImageSelector.IS_VIEW_IMAGE, true),
intent.getBooleanExtra(ImageSelector.USE_CAMERA, true), 0,
intent.getStringArrayListExtra(ImageSelector.SELECTED));
initView();
}
/**
* 修改状态栏颜色
*/
private void setStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.parseColor("#373c3d"));
}
}
private void initView() {
imageView = (ClipImageView) findViewById(R.id.process_img);
btnConfirm = (FrameLayout) findViewById(R.id.btn_confirm);
btnBack = (FrameLayout) findViewById(R.id.btn_back);
btnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (imageView.getDrawable() != null) {
btnConfirm.setEnabled(false);
confirm(imageView.clipImage());
}
}
});
btnBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data != null && requestCode == mRequestCode) {
ArrayList<String> images = data.getStringArrayListExtra(ImageSelector.SELECT_RESULT);
isCameraImage = data.getBooleanExtra(ImageSelector.IS_CAMERA_IMAGE, false);
Bitmap bitmap = ImageUtil.decodeSampledBitmapFromFile(images.get(0), 720, 1080);
if (bitmap != null) {
imageView.setBitmapData(bitmap);
} else {
finish();
}
} else {
finish();
}
}
private void confirm(Bitmap bitmap) {
String imagePath = null;
if (bitmap != null) {
imagePath = ImageUtil.saveImage(bitmap, getCacheDir().getPath() + File.separator + "image_select");
bitmap.recycle();
bitmap = null;
}
if (StringUtils.isNotEmptyString(imagePath)) {
ArrayList<String> selectImages = new ArrayList<>();
selectImages.add(imagePath);
Intent intent = new Intent();
intent.putStringArrayListExtra(ImageSelector.SELECT_RESULT, selectImages);
intent.putExtra(ImageSelector.IS_CAMERA_IMAGE,isCameraImage);
setResult(RESULT_OK, intent);
}
finish();
}
public static void openActivity(Activity context, int requestCode, boolean isViewImage,
boolean useCamera, ArrayList<String> selected) {
Intent intent = new Intent(context, ClipImageActivity.class);
intent.putExtras(dataPackages(requestCode, isViewImage, useCamera, selected));
context.startActivityForResult(intent, requestCode);
}
public static void openActivity(Fragment fragment, int requestCode, boolean isViewImage,
boolean useCamera, ArrayList<String> selected) {
Intent intent = new Intent(fragment.getContext(), ClipImageActivity.class);
intent.putExtras(dataPackages(requestCode, isViewImage, useCamera, selected));
fragment.startActivityForResult(intent, requestCode);
}
public static void openActivity(android.app.Fragment fragment, int requestCode, boolean isViewImage,
boolean useCamera, ArrayList<String> selected) {
Intent intent = new Intent(fragment.getActivity(), ClipImageActivity.class);
intent.putExtras(dataPackages(requestCode, isViewImage, useCamera, selected));
fragment.startActivityForResult(intent, requestCode);
}
public static Bundle dataPackages(int requestCode, boolean isViewImage, boolean useCamera,
ArrayList<String> selected) {
Bundle bundle = new Bundle();
bundle.putInt("requestCode", requestCode);
bundle.putBoolean(ImageSelector.IS_VIEW_IMAGE, isViewImage);
bundle.putBoolean(ImageSelector.USE_CAMERA, useCamera);
bundle.putStringArrayList(ImageSelector.SELECTED, selected);
return bundle;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
//非默认值
if (newConfig.fontScale != 1){
getResources();
}
super.onConfigurationChanged(newConfig);
}
@Override
public Resources getResources() {//还原字体大小
Resources res = super.getResources();
//非默认值
if (res.getConfiguration().fontScale != 1) {
Configuration newConfig = new Configuration();
newConfig.setToDefaults();//设置默认
res.updateConfiguration(newConfig, res.getDisplayMetrics());
}
return res;
}
}

View File

@@ -0,0 +1,199 @@
package imageselector;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import com.sl.house_property.R;
import java.io.File;
import java.util.ArrayList;
import imageselector.adapter.FullScreenImagePagerAdapter;
import imageselector.adapter.FullScreenOnlineImagePagerAdapter;
import imageselector.entry.Image;
import imageselector.utils.ImageSelector;
import imageselector.view.MyViewPager;
public class FullScreenOnlinePreviewActivity extends AppCompatActivity {
private MyViewPager vpImage;
private TextView tvIndicator;
//tempImages和tempSelectImages用于图片列表数据的页面传输。
//之所以不要Intent传输这两个图片列表因为要保证两位页面操作的是同一个列表数据同时可以避免数据量大时
// 用Intent传输发生的错误问题。
private static ArrayList<String> tempImages;
private ArrayList<String> mImages;
private boolean isShowBar = true;
private boolean isConfirm = false;
public static void openActivity(Activity activity, ArrayList<String> images, int position) {
tempImages = images;
Intent intent = new Intent(activity, FullScreenOnlinePreviewActivity.class);
intent.putExtra(ImageSelector.POSITION, position);
activity.startActivityForResult(intent, ImageSelector.RESULT_CODE);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_full_screen_preview);
setStatusBarVisible(true);
mImages = tempImages;
tempImages = null;
Intent intent = getIntent();
setStatusBarColor();
initView();
initListener();
initViewPager();
tvIndicator.setText(1 + "/" + mImages.size());
vpImage.setCurrentItem(intent.getIntExtra(ImageSelector.POSITION, 0));
}
private void initView() {
vpImage = (MyViewPager) findViewById(R.id.vp_image);
tvIndicator = (TextView) findViewById(R.id.tv_indicator);
}
private void initListener() {
findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
/**
* 初始化ViewPager
*/
private void initViewPager() {
FullScreenOnlineImagePagerAdapter adapter = new FullScreenOnlineImagePagerAdapter(this, mImages);
vpImage.setAdapter(adapter);
vpImage.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
tvIndicator.setText(position + 1 + "/" + mImages.size());
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 修改状态栏颜色
*/
private void setStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.parseColor("#373c3d"));
}
}
/**
* 获取状态栏高度
*
* @param context
* @return
*/
public static int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
/**
* 显示和隐藏状态栏
*
* @param show
*/
private void setStatusBarVisible(boolean show) {
if (show) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
/**
* 显示头部和尾部栏
*/
private void showBar() {
isShowBar = true;
}
/**
* 隐藏头部和尾部栏
*/
private void hideBar() {
isShowBar = false;
}
@Override
public void finish() {
//Activity关闭时通过Intent把用户的操作(确定/返回)传给ImageSelectActivity。
Intent intent = new Intent();
intent.putExtra(ImageSelector.IS_CONFIRM, isConfirm);
setResult(ImageSelector.RESULT_CODE, intent);
super.finish();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
//非默认值
if (newConfig.fontScale != 1){
getResources();
}
super.onConfigurationChanged(newConfig);
}
@Override
public Resources getResources() {//还原字体大小
Resources res = super.getResources();
//非默认值
if (res.getConfiguration().fontScale != 1) {
Configuration newConfig = new Configuration();
newConfig.setToDefaults();//设置默认
res.updateConfiguration(newConfig, res.getDisplayMetrics());
}
return res;
}
}

View File

@@ -0,0 +1,219 @@
package imageselector;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.sl.house_property.R;
import java.io.File;
import java.util.ArrayList;
import imageselector.adapter.FullScreenImagePagerAdapter;
import imageselector.adapter.ImagePagerAdapter;
import imageselector.entry.Image;
import imageselector.utils.ImageSelector;
import imageselector.view.MyViewPager;
import static android.animation.ObjectAnimator.ofFloat;
public class FullScreenPreviewActivity extends AppCompatActivity {
private MyViewPager vpImage;
private TextView tvIndicator;
//tempImages和tempSelectImages用于图片列表数据的页面传输。
//之所以不要Intent传输这两个图片列表因为要保证两位页面操作的是同一个列表数据同时可以避免数据量大时
// 用Intent传输发生的错误问题。
private static ArrayList<File> tempImages;
private ArrayList<File> mImages;
private boolean isShowBar = true;
private boolean isConfirm = false;
public static void openActivity(Activity activity, ArrayList<File> images, int position) {
tempImages = images;
Intent intent = new Intent(activity, FullScreenPreviewActivity.class);
intent.putExtra(ImageSelector.POSITION, position);
activity.startActivityForResult(intent, ImageSelector.RESULT_CODE);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_full_screen_preview);
setStatusBarVisible(true);
mImages = tempImages;
tempImages = null;
Intent intent = getIntent();
setStatusBarColor();
initView();
initListener();
initViewPager();
tvIndicator.setText(1 + "/" + mImages.size());
vpImage.setCurrentItem(intent.getIntExtra(ImageSelector.POSITION, 0));
}
private void initView() {
vpImage = (MyViewPager) findViewById(R.id.vp_image);
tvIndicator = (TextView) findViewById(R.id.tv_indicator);
}
private void initListener() {
findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
/**
* 初始化ViewPager
*/
private void initViewPager() {
FullScreenImagePagerAdapter adapter = new FullScreenImagePagerAdapter(this, mImages);
vpImage.setAdapter(adapter);
adapter.setOnItemClickListener(new FullScreenImagePagerAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position, Image image) {
if (isShowBar) {
hideBar();
} else {
showBar();
}
}
});
vpImage.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
tvIndicator.setText(position + 1 + "/" + mImages.size());
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 修改状态栏颜色
*/
private void setStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.parseColor("#373c3d"));
}
}
/**
* 获取状态栏高度
*
* @param context
* @return
*/
public static int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
/**
* 显示和隐藏状态栏
*
* @param show
*/
private void setStatusBarVisible(boolean show) {
if (show) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
/**
* 显示头部和尾部栏
*/
private void showBar() {
isShowBar = true;
}
/**
* 隐藏头部和尾部栏
*/
private void hideBar() {
isShowBar = false;
}
@Override
public void finish() {
//Activity关闭时通过Intent把用户的操作(确定/返回)传给ImageSelectActivity。
Intent intent = new Intent();
intent.putExtra(ImageSelector.IS_CONFIRM, isConfirm);
setResult(ImageSelector.RESULT_CODE, intent);
super.finish();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
//非默认值
if (newConfig.fontScale != 1){
getResources();
}
super.onConfigurationChanged(newConfig);
}
@Override
public Resources getResources() {//还原字体大小
Resources res = super.getResources();
//非默认值
if (res.getConfiguration().fontScale != 1) {
Configuration newConfig = new Configuration();
newConfig.setToDefaults();//设置默认
res.updateConfiguration(newConfig, res.getDisplayMetrics());
}
return res;
}
}

View File

@@ -0,0 +1,743 @@
package imageselector;
import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v4.os.EnvironmentCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SimpleItemAnimator;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.sl.house_property.R;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import imageselector.adapter.FolderAdapter;
import imageselector.adapter.ImageAdapter;
import imageselector.entry.Folder;
import imageselector.entry.Image;
import imageselector.model.ImageModel;
import imageselector.utils.DateUtils;
import imageselector.utils.ImageSelector;
public class ImageSelectorActivity extends AppCompatActivity {
private TextView tvTime;
private TextView tvFolderName;
private TextView tvConfirm;
private TextView tvPreview;
private FrameLayout btnConfirm;
private FrameLayout btnPreview;
private RecyclerView rvImage;
private RecyclerView rvFolder;
private View masking;
private ImageAdapter mAdapter;
private GridLayoutManager mLayoutManager;
private ArrayList<Folder> mFolders;
private Folder mFolder;
private boolean applyLoadImage = false;
private static final int PERMISSION_WRITE_EXTERNAL_REQUEST_CODE = 0x00000011;
private static final int PERMISSION_CAMERA_REQUEST_CODE = 0x00000012;
private static final int CAMERA_REQUEST_CODE = 0x00000010;
private boolean isOpenFolder;
private boolean isShowTime;
private boolean isInitFolder;
private boolean isSingle;
private boolean isViewImage = true;
private int mMaxCount;
private boolean useCamera = true;
private String mPhotoPath;
private Handler mHideHandler = new Handler();
private Runnable mHide = new Runnable() {
@Override
public void run() {
hideTime();
}
};
//用于接收从外面传进来的已选择的图片列表。当用户原来已经有选择过图片,现在重新打开选择器,允许用
// 户把先前选过的图片传进来,并把这些图片默认为选中状态。
private ArrayList<String> mSelectedImages;
/**
* 启动图片选择器
*
* @param activity
* @param requestCode
* @param isSingle 是否单选
* @param isViewImage 是否点击放大图片查看
* @param useCamera 是否使用拍照功能
* @param maxSelectCount 图片的最大选择数量小于等于0时不限数量isSingle为false时才有用。
* @param selected 接收从外面传进来的已选择的图片列表。当用户原来已经有选择过图片,现在重新打开
* 选择器,允许用户把先前选过的图片传进来,并把这些图片默认为选中状态。
*/
public static void openActivity(Activity activity, int requestCode,
boolean isSingle, boolean isViewImage, boolean useCamera,
int maxSelectCount, ArrayList<String> selected) {
Intent intent = new Intent(activity, ImageSelectorActivity.class);
intent.putExtras(dataPackages(isSingle, isViewImage, useCamera, maxSelectCount, selected));
activity.startActivityForResult(intent, requestCode);
}
/**
* 启动图片选择器
*
* @param fragment
* @param requestCode
* @param isSingle 是否单选
* @param isViewImage 是否点击放大图片查看
* @param useCamera 是否使用拍照功能
* @param maxSelectCount 图片的最大选择数量小于等于0时不限数量isSingle为false时才有用。
* @param selected 接收从外面传进来的已选择的图片列表。当用户原来已经有选择过图片,现在重新打开
* 选择器,允许用户把先前选过的图片传进来,并把这些图片默认为选中状态。
*/
public static void openActivity(Fragment fragment, int requestCode,
boolean isSingle, boolean isViewImage, boolean useCamera,
int maxSelectCount, ArrayList<String> selected) {
Intent intent = new Intent(fragment.getContext(), ImageSelectorActivity.class);
intent.putExtras(dataPackages(isSingle, isViewImage, useCamera, maxSelectCount, selected));
fragment.startActivityForResult(intent, requestCode);
}
/**
* 启动图片选择器
*
* @param fragment
* @param requestCode
* @param isSingle 是否单选
* @param isViewImage 是否点击放大图片查看
* @param useCamera 是否使用拍照功能
* @param maxSelectCount 图片的最大选择数量小于等于0时不限数量isSingle为false时才有用。
* @param selected 接收从外面传进来的已选择的图片列表。当用户原来已经有选择过图片,现在重新打开
* 选择器,允许用户把先前选过的图片传进来,并把这些图片默认为选中状态。
*/
public static void openActivity(android.app.Fragment fragment, int requestCode,
boolean isSingle, boolean isViewImage, boolean useCamera,
int maxSelectCount, ArrayList<String> selected) {
Intent intent = new Intent(fragment.getActivity(), ImageSelectorActivity.class);
intent.putExtras(dataPackages(isSingle, isViewImage, useCamera, maxSelectCount, selected));
fragment.startActivityForResult(intent, requestCode);
}
public static Bundle dataPackages(boolean isSingle, boolean isViewImage, boolean useCamera,
int maxSelectCount, ArrayList<String> selected) {
Bundle bundle = new Bundle();
bundle.putBoolean(ImageSelector.IS_SINGLE, isSingle);
bundle.putBoolean(ImageSelector.IS_VIEW_IMAGE, isViewImage);
bundle.putBoolean(ImageSelector.USE_CAMERA, useCamera);
bundle.putInt(ImageSelector.MAX_SELECT_COUNT, maxSelectCount);
bundle.putStringArrayList(ImageSelector.SELECTED, selected);
return bundle;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_select);
Intent intent = getIntent();
mMaxCount = intent.getIntExtra(ImageSelector.MAX_SELECT_COUNT, 0);
isSingle = intent.getBooleanExtra(ImageSelector.IS_SINGLE, false);
isViewImage = intent.getBooleanExtra(ImageSelector.IS_VIEW_IMAGE, true);
useCamera = intent.getBooleanExtra(ImageSelector.USE_CAMERA, true);
mSelectedImages = intent.getStringArrayListExtra(ImageSelector.SELECTED);
setStatusBarColor();
initView();
initListener();
initImageList();
checkPermissionAndLoadImages();
hideFolderList();
setSelectImageCount(0);
}
/**
* 修改状态栏颜色
*/
private void setStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.parseColor("#373c3d"));
}
}
private void initView() {
rvImage = (RecyclerView) findViewById(R.id.rv_image);
rvFolder = (RecyclerView) findViewById(R.id.rv_folder);
tvConfirm = (TextView) findViewById(R.id.tv_confirm);
tvPreview = (TextView) findViewById(R.id.tv_preview);
btnConfirm = (FrameLayout) findViewById(R.id.btn_confirm);
btnPreview = (FrameLayout) findViewById(R.id.btn_preview);
tvFolderName = (TextView) findViewById(R.id.tv_folder_name);
tvTime = (TextView) findViewById(R.id.tv_time);
masking = findViewById(R.id.masking);
}
private void initListener() {
findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
btnPreview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ArrayList<Image> images = new ArrayList<>();
images.addAll(mAdapter.getSelectImages());
toPreviewActivity(images, 0);
}
});
btnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirm();
}
});
findViewById(R.id.btn_folder).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isInitFolder) {
if (isOpenFolder) {
closeFolder();
} else {
openFolder();
}
}
}
});
masking.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
closeFolder();
}
});
rvImage.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
changeTime();
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
changeTime();
}
});
}
/**
* 初始化图片列表
*/
private void initImageList() {
// 判断屏幕方向
Configuration configuration = getResources().getConfiguration();
if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
mLayoutManager = new GridLayoutManager(this, 3);
} else {
mLayoutManager = new GridLayoutManager(this, 5);
}
rvImage.setLayoutManager(mLayoutManager);
mAdapter = new ImageAdapter(this, mMaxCount, isSingle, isViewImage);
rvImage.setAdapter(mAdapter);
((SimpleItemAnimator) rvImage.getItemAnimator()).setSupportsChangeAnimations(false);
if (mFolders != null && !mFolders.isEmpty()) {
setFolder(mFolders.get(0));
}
mAdapter.setOnImageSelectListener(new ImageAdapter.OnImageSelectListener() {
@Override
public void OnImageSelect(Image image, boolean isSelect, int selectCount) {
setSelectImageCount(selectCount);
}
});
mAdapter.setOnItemClickListener(new ImageAdapter.OnItemClickListener() {
@Override
public void OnItemClick(Image image, int position) {
toPreviewActivity(mAdapter.getData(), position);
}
@Override
public void OnCameraClick() {
checkPermissionAndCamera();
}
});
}
/**
* 初始化图片文件夹列表
*/
private void initFolderList() {
if (mFolders != null && !mFolders.isEmpty()) {
isInitFolder = true;
rvFolder.setLayoutManager(new LinearLayoutManager(ImageSelectorActivity.this));
FolderAdapter adapter = new FolderAdapter(ImageSelectorActivity.this, mFolders);
adapter.setOnFolderSelectListener(new FolderAdapter.OnFolderSelectListener() {
@Override
public void OnFolderSelect(Folder folder) {
setFolder(folder);
closeFolder();
}
});
rvFolder.setAdapter(adapter);
}
}
/**
* 刚开始的时候文件夹列表默认是隐藏的
*/
private void hideFolderList() {
rvFolder.post(new Runnable() {
@Override
public void run() {
rvFolder.setTranslationY(rvFolder.getHeight());
rvFolder.setVisibility(View.GONE);
}
});
}
/**
* 设置选中的文件夹,同时刷新图片列表
*
* @param folder
*/
private void setFolder(Folder folder) {
if (folder != null && mAdapter != null && !folder.equals(mFolder)) {
mFolder = folder;
tvFolderName.setText(folder.getName());
rvImage.scrollToPosition(0);
mAdapter.refresh(folder.getImages(), folder.isUseCamera());
}
}
private void setSelectImageCount(int count) {
if (count == 0) {
btnConfirm.setEnabled(false);
btnPreview.setEnabled(false);
tvConfirm.setText("确定");
tvPreview.setText("预览");
} else {
btnConfirm.setEnabled(true);
btnPreview.setEnabled(true);
tvPreview.setText("预览(" + count + ")");
if (isSingle) {
tvConfirm.setText("确定");
} else if (mMaxCount > 0) {
tvConfirm.setText("确定(" + count + "/" + mMaxCount + ")");
} else {
tvConfirm.setText("确定(" + count + ")");
}
}
}
/**
* 弹出文件夹列表
*/
private void openFolder() {
if (!isOpenFolder) {
masking.setVisibility(View.VISIBLE);
ObjectAnimator animator = ObjectAnimator.ofFloat(rvFolder, "translationY",
rvFolder.getHeight(), 0).setDuration(300);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
rvFolder.setVisibility(View.VISIBLE);
}
});
animator.start();
isOpenFolder = true;
}
}
/**
* 收起文件夹列表
*/
private void closeFolder() {
if (isOpenFolder) {
masking.setVisibility(View.GONE);
ObjectAnimator animator = ObjectAnimator.ofFloat(rvFolder, "translationY",
0, rvFolder.getHeight()).setDuration(300);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
rvFolder.setVisibility(View.GONE);
}
});
animator.start();
isOpenFolder = false;
}
}
/**
* 隐藏时间条
*/
private void hideTime() {
if (isShowTime) {
ObjectAnimator.ofFloat(tvTime, "alpha", 1, 0).setDuration(300).start();
isShowTime = false;
}
}
/**
* 显示时间条
*/
private void showTime() {
if (!isShowTime) {
ObjectAnimator.ofFloat(tvTime, "alpha", 0, 1).setDuration(300).start();
isShowTime = true;
}
}
/**
* 改变时间条显示的时间(显示图片列表中的第一个可见图片的时间)
*/
private void changeTime() {
int firstVisibleItem = getFirstVisibleItem();
Image image = mAdapter.getFirstVisibleImage(firstVisibleItem);
if (image != null) {
String time = DateUtils.getImageTime(image.getTime() * 1000);
tvTime.setText(time);
showTime();
mHideHandler.removeCallbacks(mHide);
mHideHandler.postDelayed(mHide, 1500);
}
}
private int getFirstVisibleItem() {
return mLayoutManager.findFirstVisibleItemPosition();
}
private void confirm() {
if (mAdapter == null) {
return;
}
//因为图片的实体类是Image而我们返回的是String数组所以要进行转换。
ArrayList<Image> selectImages = mAdapter.getSelectImages();
ArrayList<String> images = new ArrayList<>();
for (Image image : selectImages) {
images.add(image.getPath());
}
//点击确定把选中的图片通过Intent传给上一个Activity。
setResult(images,false);
finish();
}
private void setResult(ArrayList<String> images,boolean isCameraImage) {
Intent intent = new Intent();
intent.putStringArrayListExtra(ImageSelector.SELECT_RESULT, images);
intent.putExtra(ImageSelector.IS_CAMERA_IMAGE,isCameraImage);
setResult(RESULT_OK, intent);
}
private void toPreviewActivity(ArrayList<Image> images, int position) {
if (images != null && !images.isEmpty()) {
PreviewActivity.openActivity(this, images,
mAdapter.getSelectImages(), isSingle, mMaxCount, position);
}
}
@Override
protected void onStart() {
super.onStart();
if (applyLoadImage) {
applyLoadImage = false;
checkPermissionAndLoadImages();
}
}
/**
* 处理图片预览页返回的结果
*
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ImageSelector.RESULT_CODE) {
if (data != null && data.getBooleanExtra(ImageSelector.IS_CONFIRM, false)) {
//如果用户在预览页点击了确定,就直接把用户选中的图片返回给用户。
confirm();
} else {
//否则,就刷新当前页面。
mAdapter.notifyDataSetChanged();
setSelectImageCount(mAdapter.getSelectImages().size());
}
} else if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(mPhotoPath))));
ArrayList<String> images = new ArrayList<>();
images.add(mPhotoPath);
setResult(images,true);
finish();
}
}
}
/**
* 横竖屏切换处理
*
* @param newConfig
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
//非默认值
if (newConfig.fontScale != 1){
getResources();
}
super.onConfigurationChanged(newConfig);
if (mLayoutManager != null && mAdapter != null) {
//切换为竖屏
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
mLayoutManager.setSpanCount(3);
}
//切换为横屏
else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
mLayoutManager.setSpanCount(5);
}
mAdapter.notifyDataSetChanged();
}
}
/**
* 检查权限并加载SD卡里的图片。
*/
private void checkPermissionAndLoadImages() {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
// Toast.makeText(this, "没有图片", Toast.LENGTH_LONG).show();
return;
}
int hasWriteExternalPermission = ContextCompat.checkSelfPermission(getApplication(),
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWriteExternalPermission == PackageManager.PERMISSION_GRANTED) {
//有权限,加载图片。
loadImageForSDCard();
} else {
//没有权限,申请权限。
ActivityCompat.requestPermissions(ImageSelectorActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_WRITE_EXTERNAL_REQUEST_CODE);
}
}
/**
* 检查权限并拍照。
*/
private void checkPermissionAndCamera() {
int hasCameraPermission = ContextCompat.checkSelfPermission(getApplication(),
Manifest.permission.CAMERA);
if (hasCameraPermission == PackageManager.PERMISSION_GRANTED) {
//有调起相机拍照。
openCamera();
} else {
//没有权限,申请权限。
ActivityCompat.requestPermissions(ImageSelectorActivity.this,
new String[]{Manifest.permission.CAMERA}, PERMISSION_CAMERA_REQUEST_CODE);
}
}
/**
* 处理权限申请的回调。
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_WRITE_EXTERNAL_REQUEST_CODE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//允许权限,加载图片。
loadImageForSDCard();
} else {
//拒绝权限,弹出提示框。
showExceptionDialog(true);
}
} else if (requestCode == PERMISSION_CAMERA_REQUEST_CODE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//允许权限,有调起相机拍照。
openCamera();
} else {
//拒绝权限,弹出提示框。
showExceptionDialog(false);
}
}
}
/**
* 发生没有权限等异常时显示一个提示dialog.
*/
private void showExceptionDialog(final boolean applyLoad) {
new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("提示")
.setMessage("该相册需要赋予访问存储和拍照的权限,请到“设置”>“应用”>“权限”中配置权限。")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
finish();
}
}).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
startAppSettings();
if (applyLoad) {
applyLoadImage = true;
}
}
}).show();
}
/**
* 从SDCard加载图片。
*/
private void loadImageForSDCard() {
ImageModel.loadImageForSDCard(this, new ImageModel.DataCallback() {
@Override
public void onSuccess(ArrayList<Folder> folders) {
mFolders = folders;
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mFolders != null && !mFolders.isEmpty()) {
initFolderList();
mFolders.get(0).setUseCamera(useCamera);
setFolder(mFolders.get(0));
if (mSelectedImages != null && mAdapter != null) {
mAdapter.setSelectedImages(mSelectedImages);
mSelectedImages = null;
setSelectImageCount(mAdapter.getSelectImages().size());
}
}
}
});
}
});
}
/**
* 调起相机拍照
*/
private void openCamera() {
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (captureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
if (photoFile != null) {
mPhotoPath = photoFile.getAbsolutePath();
//通过FileProvider创建一个content类型的Uri
Uri photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(captureIntent, CAMERA_REQUEST_CODE);
}
}
}
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String imageFileName = String.format("JPEG_%s.jpg", timeStamp);
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
if (!storageDir.exists()) {
storageDir.mkdir();
}
File tempFile = new File(storageDir, imageFileName);
if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) {
return null;
}
return tempFile;
}
/**
* 启动应用的设置
*/
private void startAppSettings() {
Intent intent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN && isOpenFolder) {
closeFolder();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public Resources getResources() {//还原字体大小
Resources res = super.getResources();
//非默认值
if (res.getConfiguration().fontScale != 1) {
Configuration newConfig = new Configuration();
newConfig.setToDefaults();//设置默认
res.updateConfiguration(newConfig, res.getDisplayMetrics());
}
return res;
}
}

View File

@@ -0,0 +1,346 @@
package imageselector;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.sl.house_property.R;
import java.util.ArrayList;
import imageselector.adapter.ImagePagerAdapter;
import imageselector.entry.Image;
import imageselector.utils.ImageSelector;
import imageselector.view.MyViewPager;
import static android.animation.ObjectAnimator.ofFloat;
public class PreviewActivity extends AppCompatActivity {
private MyViewPager vpImage;
private TextView tvIndicator;
private TextView tvConfirm;
private FrameLayout btnConfirm;
private TextView tvSelect;
private RelativeLayout rlTopBar;
private RelativeLayout rlBottomBar;
//tempImages和tempSelectImages用于图片列表数据的页面传输。
//之所以不要Intent传输这两个图片列表因为要保证两位页面操作的是同一个列表数据同时可以避免数据量大时
// 用Intent传输发生的错误问题。
private static ArrayList<Image> tempImages;
private static ArrayList<Image> tempSelectImages;
private ArrayList<Image> mImages;
private ArrayList<Image> mSelectImages;
private boolean isShowBar = true;
private boolean isConfirm = false;
private boolean isSingle;
private int mMaxCount;
private BitmapDrawable mSelectDrawable;
private BitmapDrawable mUnSelectDrawable;
public static void openActivity(Activity activity, ArrayList<Image> images,
ArrayList<Image> selectImages, boolean isSingle,
int maxSelectCount, int position) {
tempImages = images;
tempSelectImages = selectImages;
Intent intent = new Intent(activity, PreviewActivity.class);
intent.putExtra(ImageSelector.MAX_SELECT_COUNT, maxSelectCount);
intent.putExtra(ImageSelector.IS_SINGLE, isSingle);
intent.putExtra(ImageSelector.POSITION, position);
activity.startActivityForResult(intent, ImageSelector.RESULT_CODE);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preview);
setStatusBarVisible(true);
mImages = tempImages;
tempImages = null;
mSelectImages = tempSelectImages;
tempSelectImages = null;
Intent intent = getIntent();
mMaxCount = intent.getIntExtra(ImageSelector.MAX_SELECT_COUNT, 0);
isSingle = intent.getBooleanExtra(ImageSelector.IS_SINGLE, false);
Resources resources = getResources();
Bitmap selectBitmap = BitmapFactory.decodeResource(resources, R.drawable.icon_image_select);
mSelectDrawable = new BitmapDrawable(resources, selectBitmap);
mSelectDrawable.setBounds(0, 0, selectBitmap.getWidth(), selectBitmap.getHeight());
Bitmap unSelectBitmap = BitmapFactory.decodeResource(resources, R.drawable.icon_image_un_select);
mUnSelectDrawable = new BitmapDrawable(resources, unSelectBitmap);
mUnSelectDrawable.setBounds(0, 0, unSelectBitmap.getWidth(), unSelectBitmap.getHeight());
setStatusBarColor();
initView();
initListener();
initViewPager();
tvIndicator.setText(1 + "/" + mImages.size());
changeSelect(mImages.get(0));
vpImage.setCurrentItem(intent.getIntExtra(ImageSelector.POSITION, 0));
}
private void initView() {
vpImage = (MyViewPager) findViewById(R.id.vp_image);
tvIndicator = (TextView) findViewById(R.id.tv_indicator);
tvConfirm = (TextView) findViewById(R.id.tv_confirm);
btnConfirm = (FrameLayout) findViewById(R.id.btn_confirm);
tvSelect = (TextView) findViewById(R.id.tv_select);
rlTopBar = (RelativeLayout) findViewById(R.id.rl_top_bar);
rlBottomBar = (RelativeLayout) findViewById(R.id.rl_bottom_bar);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) rlTopBar.getLayoutParams();
lp.topMargin = getStatusBarHeight(this);
rlTopBar.setLayoutParams(lp);
}
private void initListener() {
findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
btnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isConfirm = true;
finish();
}
});
tvSelect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickSelect();
}
});
}
/**
* 初始化ViewPager
*/
private void initViewPager() {
ImagePagerAdapter adapter = new ImagePagerAdapter(this, mImages);
vpImage.setAdapter(adapter);
adapter.setOnItemClickListener(new ImagePagerAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position, Image image) {
if (isShowBar) {
hideBar();
} else {
showBar();
}
}
});
vpImage.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
tvIndicator.setText(position + 1 + "/" + mImages.size());
changeSelect(mImages.get(position));
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 修改状态栏颜色
*/
private void setStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.parseColor("#373c3d"));
}
}
/**
* 获取状态栏高度
*
* @param context
* @return
*/
public static int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
/**
* 显示和隐藏状态栏
*
* @param show
*/
private void setStatusBarVisible(boolean show) {
if (show) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
/**
* 显示头部和尾部栏
*/
private void showBar() {
isShowBar = true;
setStatusBarVisible(true);
//添加延时保证StatusBar完全显示后再进行动画。
rlTopBar.postDelayed(new Runnable() {
@Override
public void run() {
if (rlTopBar != null) {
ObjectAnimator animator = ofFloat(rlTopBar, "translationY",
rlTopBar.getTranslationY(), 0).setDuration(300);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
if (rlTopBar != null) {
rlTopBar.setVisibility(View.VISIBLE);
}
}
});
animator.start();
ofFloat(rlBottomBar, "translationY", rlBottomBar.getTranslationY(), 0)
.setDuration(300).start();
}
}
}, 100);
}
/**
* 隐藏头部和尾部栏
*/
private void hideBar() {
isShowBar = false;
ObjectAnimator animator = ObjectAnimator.ofFloat(rlTopBar, "translationY",
0, -rlTopBar.getHeight()).setDuration(300);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (rlTopBar != null) {
rlTopBar.setVisibility(View.GONE);
//添加延时保证rlTopBar完全隐藏后再隐藏StatusBar。
rlTopBar.postDelayed(new Runnable() {
@Override
public void run() {
setStatusBarVisible(false);
}
}, 5);
}
}
});
animator.start();
ofFloat(rlBottomBar, "translationY", 0, rlBottomBar.getHeight())
.setDuration(300).start();
}
private void clickSelect() {
int position = vpImage.getCurrentItem();
if (mImages != null && mImages.size() > position) {
Image image = mImages.get(position);
if (mSelectImages.contains(image)) {
mSelectImages.remove(image);
} else if (isSingle) {
mSelectImages.clear();
mSelectImages.add(image);
} else if (mMaxCount <= 0 || mSelectImages.size() < mMaxCount) {
mSelectImages.add(image);
}
changeSelect(image);
}
}
private void changeSelect(Image image) {
tvSelect.setCompoundDrawables(mSelectImages.contains(image) ?
mSelectDrawable : mUnSelectDrawable, null, null, null);
setSelectImageCount(mSelectImages.size());
}
private void setSelectImageCount(int count) {
if (count == 0) {
btnConfirm.setEnabled(false);
tvConfirm.setText("确定");
} else {
btnConfirm.setEnabled(true);
if (isSingle) {
tvConfirm.setText("确定");
} else if (mMaxCount > 0) {
tvConfirm.setText("确定(" + count + "/" + mMaxCount + ")");
} else {
tvConfirm.setText("确定(" + count + ")");
}
}
}
@Override
public void finish() {
//Activity关闭时通过Intent把用户的操作(确定/返回)传给ImageSelectActivity。
Intent intent = new Intent();
intent.putExtra(ImageSelector.IS_CONFIRM, isConfirm);
setResult(ImageSelector.RESULT_CODE, intent);
super.finish();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
//非默认值
if (newConfig.fontScale != 1){
getResources();
}
super.onConfigurationChanged(newConfig);
}
@Override
public Resources getResources() {//还原字体大小
Resources res = super.getResources();
//非默认值
if (res.getConfiguration().fontScale != 1) {
Configuration newConfig = new Configuration();
newConfig.setToDefaults();//设置默认
res.updateConfiguration(newConfig, res.getDisplayMetrics());
}
return res;
}
}

View File

@@ -0,0 +1,100 @@
package imageselector.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.sl.house_property.R;
import java.io.File;
import java.util.ArrayList;
import imageselector.entry.Folder;
import imageselector.entry.Image;
public class FolderAdapter extends RecyclerView.Adapter<FolderAdapter.ViewHolder> {
private Context mContext;
private ArrayList<Folder> mFolders;
private LayoutInflater mInflater;
private int mSelectItem;
private OnFolderSelectListener mListener;
public FolderAdapter(Context context, ArrayList<Folder> folders) {
mContext = context;
mFolders = folders;
this.mInflater = LayoutInflater.from(context);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.adapter_folder, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final Folder folder = mFolders.get(position);
ArrayList<Image> images = folder.getImages();
holder.tvFolderName.setText(folder.getName());
holder.ivSelect.setVisibility(mSelectItem == position ? View.VISIBLE : View.GONE);
if (images != null && !images.isEmpty()) {
holder.tvFolderSize.setText(images.size() + "");
Glide.with(mContext).load(new File(images.get(0).getPath()))
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.into(holder.ivImage);
} else {
holder.tvFolderSize.setText("0张");
holder.ivImage.setImageBitmap(null);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSelectItem = holder.getAdapterPosition();
notifyDataSetChanged();
if (mListener != null) {
mListener.OnFolderSelect(folder);
}
}
});
}
@Override
public int getItemCount() {
return mFolders == null ? 0 : mFolders.size();
}
public void setOnFolderSelectListener(OnFolderSelectListener listener) {
this.mListener = listener;
}
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView ivImage;
ImageView ivSelect;
TextView tvFolderName;
TextView tvFolderSize;
public ViewHolder(View itemView) {
super(itemView);
ivImage = itemView.findViewById(R.id.iv_image);
ivSelect = itemView.findViewById(R.id.iv_select);
tvFolderName = itemView.findViewById(R.id.tv_folder_name);
tvFolderSize = itemView.findViewById(R.id.tv_folder_size);
}
}
public interface OnFolderSelectListener {
void OnFolderSelect(Folder folder);
}
}

View File

@@ -0,0 +1,146 @@
package imageselector.adapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.github.chrisbanes.photoview.PhotoView;
import com.github.chrisbanes.photoview.PhotoViewAttacher;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import imageselector.entry.Image;
import imageselector.utils.ImageUtil;
public class FullScreenImagePagerAdapter extends PagerAdapter {
private Context mContext;
private List<PhotoView> viewList = new ArrayList<>(4);
List<File> mImgList;
private OnItemClickListener mListener;
public FullScreenImagePagerAdapter(Context context, List<File> imgList) {
this.mContext = context;
createImageViews();
mImgList = imgList;
}
private void createImageViews() {
for (int i = 0; i < 4; i++) {
PhotoView imageView = new PhotoView(mContext);
imageView.setAdjustViewBounds(true);
viewList.add(imageView);
}
}
@Override
public int getCount() {
return mImgList == null ? 0 : mImgList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (object instanceof PhotoView) {
PhotoView view = (PhotoView) object;
view.setImageDrawable(null);
viewList.add(view);
container.removeView(view);
}
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
final PhotoView currentView = viewList.remove(0);
final File image = mImgList.get(position);
container.addView(currentView);
Glide.with(mContext).asBitmap()
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.load(image).into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
int bw = resource.getWidth();
int bh = resource.getHeight();
if (bw > 8192 || bh > 8192) {
Bitmap bitmap = ImageUtil.zoomBitmap(resource, 8192, 8192);
setBitmap(currentView, bitmap);
} else {
setBitmap(currentView, resource);
}
}
});
currentView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
// mListener.onItemClick(position, image);
}
}
});
return currentView;
}
private void setBitmap(PhotoView imageView, Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
if (bitmap != null) {
int bw = bitmap.getWidth();
int bh = bitmap.getHeight();
int vw = imageView.getWidth();
int vh = imageView.getHeight();
if (bw != 0 && bh != 0 && vw != 0 && vh != 0) {
if (1.0f * bh / bw > 1.0f * vh / vw) {
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
float offset = (1.0f * bh * vw / bw - vh) / 2;
adjustOffset(imageView, offset);
} else {
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
}
}
}
}
public void setOnItemClickListener(OnItemClickListener l) {
mListener = l;
}
public interface OnItemClickListener {
void onItemClick(int position, Image image);
}
private void adjustOffset(PhotoView view, float offset) {
PhotoViewAttacher attacher = view.getAttacher();
try {
Field field = PhotoViewAttacher.class.getDeclaredField("mBaseMatrix");
field.setAccessible(true);
Matrix matrix = (Matrix) field.get(attacher);
matrix.postTranslate(0, offset);
Method method = PhotoViewAttacher.class.getDeclaredMethod("resetMatrix");
method.setAccessible(true);
method.invoke(attacher);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,146 @@
package imageselector.adapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.github.chrisbanes.photoview.PhotoView;
import com.github.chrisbanes.photoview.PhotoViewAttacher;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import imageselector.entry.Image;
import imageselector.utils.ImageUtil;
public class FullScreenOnlineImagePagerAdapter extends PagerAdapter {
private Context mContext;
private List<PhotoView> viewList = new ArrayList<>(4);
List<String> mImgList;
private OnItemClickListener mListener;
public FullScreenOnlineImagePagerAdapter(Context context, List<String> imgList) {
this.mContext = context;
createImageViews();
mImgList = imgList;
}
private void createImageViews() {
for (int i = 0; i < 4; i++) {
PhotoView imageView = new PhotoView(mContext);
imageView.setAdjustViewBounds(true);
viewList.add(imageView);
}
}
@Override
public int getCount() {
return mImgList == null ? 0 : mImgList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (object instanceof PhotoView) {
PhotoView view = (PhotoView) object;
view.setImageDrawable(null);
viewList.add(view);
container.removeView(view);
}
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
final PhotoView currentView = viewList.remove(0);
final String image = mImgList.get(position);
container.addView(currentView);
Glide.with(mContext).asBitmap()
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.load(image).into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
int bw = resource.getWidth();
int bh = resource.getHeight();
if (bw > 8192 || bh > 8192) {
Bitmap bitmap = ImageUtil.zoomBitmap(resource, 8192, 8192);
setBitmap(currentView, bitmap);
} else {
setBitmap(currentView, resource);
}
}
});
currentView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
// mListener.onItemClick(position, image);
}
}
});
return currentView;
}
private void setBitmap(PhotoView imageView, Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
if (bitmap != null) {
int bw = bitmap.getWidth();
int bh = bitmap.getHeight();
int vw = imageView.getWidth();
int vh = imageView.getHeight();
if (bw != 0 && bh != 0 && vw != 0 && vh != 0) {
if (1.0f * bh / bw > 1.0f * vh / vw) {
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
float offset = (1.0f * bh * vw / bw - vh) / 2;
adjustOffset(imageView, offset);
} else {
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
}
}
}
}
public void setOnItemClickListener(OnItemClickListener l) {
mListener = l;
}
public interface OnItemClickListener {
void onItemClick(int position, Image image);
}
private void adjustOffset(PhotoView view, float offset) {
PhotoViewAttacher attacher = view.getAttacher();
try {
Field field = PhotoViewAttacher.class.getDeclaredField("mBaseMatrix");
field.setAccessible(true);
Matrix matrix = (Matrix) field.get(attacher);
matrix.postTranslate(0, offset);
Method method = PhotoViewAttacher.class.getDeclaredMethod("resetMatrix");
method.setAccessible(true);
method.invoke(attacher);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,288 @@
package imageselector.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.sl.house_property.R;
import java.io.File;
import java.util.ArrayList;
import imageselector.entry.Image;
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder> {
private Context mContext;
private ArrayList<Image> mImages;
private LayoutInflater mInflater;
//保存选中的图片
private ArrayList<Image> mSelectImages = new ArrayList<>();
private OnImageSelectListener mSelectListener;
private OnItemClickListener mItemClickListener;
private int mMaxCount;
private boolean isSingle;
private boolean isViewImage;
private static final int TYPE_CAMERA = 1;
private static final int TYPE_IMAGE = 2;
private boolean useCamera;
/**
* @param maxCount 图片的最大选择数量小于等于0时不限数量isSingle为false时才有用。
* @param isSingle 是否单选
* @param isViewImage 是否点击放大图片查看
*/
public ImageAdapter(Context context, int maxCount, boolean isSingle, boolean isViewImage) {
mContext = context;
this.mInflater = LayoutInflater.from(mContext);
mMaxCount = maxCount;
this.isSingle = isSingle;
this.isViewImage = isViewImage;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_IMAGE) {
View view = mInflater.inflate(R.layout.adapter_images_item, parent, false);
return new ViewHolder(view);
} else {
View view = mInflater.inflate(R.layout.adapter_camera, parent, false);
return new ViewHolder(view);
}
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
if (getItemViewType(position) == TYPE_IMAGE) {
final Image image = getImage(position);
Glide.with(mContext).load(new File(image.getPath()))
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.into(holder.ivImage);
setItemSelect(holder, mSelectImages.contains(image));
holder.ivGif.setVisibility(image.isGif() ? View.VISIBLE : View.GONE);
//点击选中/取消选中图片
holder.ivSelectIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkedImage(holder, image);
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isViewImage) {
if (mItemClickListener != null) {
int p = holder.getAdapterPosition();
mItemClickListener.OnItemClick(image, useCamera ? p - 1 : p);
}
} else {
checkedImage(holder, image);
}
}
});
} else if (getItemViewType(position) == TYPE_CAMERA) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mItemClickListener != null) {
mItemClickListener.OnCameraClick();
}
}
});
}
}
@Override
public int getItemViewType(int position) {
if (useCamera && position == 0) {
return TYPE_CAMERA;
} else {
return TYPE_IMAGE;
}
}
private void checkedImage(ViewHolder holder, Image image) {
if (mSelectImages.contains(image)) {
//如果图片已经选中,就取消选中
unSelectImage(image);
setItemSelect(holder, false);
} else if (isSingle) {
//如果是单选,就先清空已经选中的图片,再选中当前图片
clearImageSelect();
selectImage(image);
setItemSelect(holder, true);
} else if (mMaxCount <= 0 || mSelectImages.size() < mMaxCount) {
//如果不限制图片的选中数量,或者图片的选中数量
// 还没有达到最大限制,就直接选中当前图片。
selectImage(image);
setItemSelect(holder, true);
}
}
/**
* 选中图片
*
* @param image
*/
private void selectImage(Image image) {
mSelectImages.add(image);
if (mSelectListener != null) {
mSelectListener.OnImageSelect(image, true, mSelectImages.size());
}
}
/**
* 取消选中图片
*
* @param image
*/
private void unSelectImage(Image image) {
mSelectImages.remove(image);
if (mSelectListener != null) {
mSelectListener.OnImageSelect(image, false, mSelectImages.size());
}
}
@Override
public int getItemCount() {
return useCamera ? getImageCount() + 1 : getImageCount();
}
private int getImageCount() {
return mImages == null ? 0 : mImages.size();
}
public ArrayList<Image> getData() {
return mImages;
}
public void refresh(ArrayList<Image> data, boolean useCamera) {
mImages = data;
this.useCamera = useCamera;
notifyDataSetChanged();
}
private Image getImage(int position) {
return mImages.get(useCamera ? position - 1 : position);
}
public Image getFirstVisibleImage(int firstVisibleItem) {
if (mImages != null && !mImages.isEmpty()) {
if (useCamera) {
return mImages.get(firstVisibleItem == 0 ? 0 : firstVisibleItem - 1);
} else {
return mImages.get(firstVisibleItem);
}
}
return null;
}
/**
* 设置图片选中和未选中的效果
*/
private void setItemSelect(ViewHolder holder, boolean isSelect) {
if (isSelect) {
holder.ivSelectIcon.setImageResource(R.drawable.icon_image_select);
holder.ivMasking.setAlpha(0.5f);
} else {
holder.ivSelectIcon.setImageResource(R.drawable.icon_image_un_select);
holder.ivMasking.setAlpha(0.2f);
}
}
private void clearImageSelect() {
if (mImages != null && mSelectImages.size() == 1) {
int index = mImages.indexOf(mSelectImages.get(0));
mSelectImages.clear();
if (index != -1) {
notifyItemChanged(useCamera ? index + 1 : index);
}
}
}
public void setSelectedImages(ArrayList<String> selected) {
if (mImages != null && selected != null) {
for (String path : selected) {
if (isFull()) {
return;
}
for (Image image : mImages) {
if (path.equals(image.getPath())) {
if (!mSelectImages.contains(image)) {
mSelectImages.add(image);
}
break;
}
}
}
notifyDataSetChanged();
}
}
private boolean isFull() {
if (isSingle && mSelectImages.size() == 1) {
return true;
} else if (mMaxCount > 0 && mSelectImages.size() == mMaxCount) {
return true;
} else {
return false;
}
}
public ArrayList<Image> getSelectImages() {
return mSelectImages;
}
public void setOnImageSelectListener(OnImageSelectListener listener) {
this.mSelectListener = listener;
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mItemClickListener = listener;
}
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView ivImage;
ImageView ivSelectIcon;
ImageView ivMasking;
ImageView ivGif;
ImageView ivCamera;
public ViewHolder(View itemView) {
super(itemView);
ivImage = itemView.findViewById(R.id.iv_image);
ivSelectIcon = itemView.findViewById(R.id.iv_select);
ivMasking = itemView.findViewById(R.id.iv_masking);
ivGif = itemView.findViewById(R.id.iv_gif);
ivCamera = itemView.findViewById(R.id.iv_camera);
}
}
public interface OnImageSelectListener {
void OnImageSelect(Image image, boolean isSelect, int selectCount);
}
public interface OnItemClickListener {
void OnItemClick(Image image, int position);
void OnCameraClick();
}
}

View File

@@ -0,0 +1,151 @@
package imageselector.adapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.github.chrisbanes.photoview.PhotoView;
import com.github.chrisbanes.photoview.PhotoViewAttacher;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import imageselector.entry.Image;
import imageselector.utils.ImageUtil;
public class ImagePagerAdapter extends PagerAdapter {
private Context mContext;
private List<PhotoView> viewList = new ArrayList<>(4);
List<Image> mImgList;
private OnItemClickListener mListener;
public ImagePagerAdapter(Context context, List<Image> imgList) {
this.mContext = context;
createImageViews();
mImgList = imgList;
}
private void createImageViews() {
for (int i = 0; i < 4; i++) {
PhotoView imageView = new PhotoView(mContext);
imageView.setAdjustViewBounds(true);
viewList.add(imageView);
}
}
@Override
public int getCount() {
return mImgList == null ? 0 : mImgList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (object instanceof PhotoView) {
PhotoView view = (PhotoView) object;
view.setImageDrawable(null);
viewList.add(view);
container.removeView(view);
}
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
final PhotoView currentView = viewList.remove(0);
final Image image = mImgList.get(position);
container.addView(currentView);
if (image.isGif()) {
currentView.setScaleType(ImageView.ScaleType.FIT_CENTER);
Glide.with(mContext).load(new File(image.getPath()))
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.into(currentView);
} else {
Glide.with(mContext).asBitmap()
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.load(new File(image.getPath())).into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
int bw = resource.getWidth();
int bh = resource.getHeight();
if (bw > 8192 || bh > 8192) {
Bitmap bitmap = ImageUtil.zoomBitmap(resource, 8192, 8192);
setBitmap(currentView, bitmap);
} else {
setBitmap(currentView, resource);
}
}
});
}
currentView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onItemClick(position, image);
}
}
});
return currentView;
}
private void setBitmap(PhotoView imageView, Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
if (bitmap != null) {
int bw = bitmap.getWidth();
int bh = bitmap.getHeight();
int vw = imageView.getWidth();
int vh = imageView.getHeight();
if (bw != 0 && bh != 0 && vw != 0 && vh != 0) {
if (1.0f * bh / bw > 1.0f * vh / vw) {
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
float offset = (1.0f * bh * vw / bw - vh) / 2;
adjustOffset(imageView, offset);
} else {
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
}
}
}
}
public void setOnItemClickListener(OnItemClickListener l) {
mListener = l;
}
public interface OnItemClickListener {
void onItemClick(int position, Image image);
}
private void adjustOffset(PhotoView view, float offset) {
PhotoViewAttacher attacher = view.getAttacher();
try {
Field field = PhotoViewAttacher.class.getDeclaredField("mBaseMatrix");
field.setAccessible(true);
Matrix matrix = (Matrix) field.get(attacher);
matrix.postTranslate(0, offset);
Method method = PhotoViewAttacher.class.getDeclaredMethod("resetMatrix");
method.setAccessible(true);
method.invoke(attacher);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,67 @@
package imageselector.entry;
import java.util.ArrayList;
import imageselector.utils.StringUtils;
/**
* 图片文件夹实体类
*/
public class Folder {
private boolean useCamera; // 是否可以调用相机拍照。只有“全部”文件夹才可以拍照
private String name;
private ArrayList<Image> images;
public Folder(String name) {
this.name = name;
}
public Folder(String name, ArrayList<Image> images) {
this.name = name;
this.images = images;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<Image> getImages() {
return images;
}
public void setImages(ArrayList<Image> images) {
this.images = images;
}
public boolean isUseCamera() {
return useCamera;
}
public void setUseCamera(boolean useCamera) {
this.useCamera = useCamera;
}
public void addImage(Image image) {
if (image != null && StringUtils.isNotEmptyString(image.getPath())) {
if (images == null) {
images = new ArrayList<>();
}
images.add(image);
}
}
@Override
public String toString() {
return "Folder{" +
"name='" + name + '\'' +
", images=" + images +
'}';
}
}

View File

@@ -0,0 +1,90 @@
package imageselector.entry;
import android.os.Parcel;
import android.os.Parcelable;
/**
*图片实体类
*/
public class Image implements Parcelable {
private String path;
private long time;
private String name;
private String mimeType;
public Image(String path, long time, String name,String mimeType) {
this.path = path;
this.time = time;
this.name = name;
this.mimeType = mimeType;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
public boolean isGif(){
return "image/gif".equals(mimeType);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.path);
dest.writeLong(this.time);
dest.writeString(this.name);
dest.writeString(this.mimeType);
}
protected Image(Parcel in) {
this.path = in.readString();
this.time = in.readLong();
this.name = in.readString();
this.mimeType = in.readString();
}
public static final Creator<Image> CREATOR = new Creator<Image>() {
@Override
public Image createFromParcel(Parcel source) {
return new Image(source);
}
@Override
public Image[] newArray(int size) {
return new Image[size];
}
};
}

View File

@@ -0,0 +1,159 @@
package imageselector.model;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import imageselector.entry.Folder;
import imageselector.entry.Image;
import imageselector.utils.StringUtils;
public class ImageModel {
/**
* 从SDCard加载图片
*
* @param context
* @param callback
*/
public static void loadImageForSDCard(final Context context, final DataCallback callback) {
//由于扫描图片是耗时的操作,所以要在子线程处理。
new Thread(new Runnable() {
@Override
public void run() {
//扫描图片
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver mContentResolver = context.getContentResolver();
Cursor mCursor = mContentResolver.query(mImageUri, new String[]{
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.MIME_TYPE},
null,
null,
MediaStore.Images.Media.DATE_ADDED);
ArrayList<Image> images = new ArrayList<>();
//读取扫描到的图片
if (mCursor != null) {
while (mCursor.moveToNext()) {
// 获取图片的路径
String path = mCursor.getString(
mCursor.getColumnIndex(MediaStore.Images.Media.DATA));
//获取图片名称
String name = mCursor.getString(
mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
//获取图片时间
long time = mCursor.getLong(
mCursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));
//获取图片类型
String mimeType = mCursor.getString(
mCursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE));
//过滤未下载完成或者不存在的文件
if (!"downloading".equals(getExtensionName(path)) && checkImgExists(path)) {
images.add(new Image(path, time, name, mimeType));
}
}
mCursor.close();
}
Collections.reverse(images);
callback.onSuccess(splitFolder(images));
}
}).start();
}
/**
* 检查图片是否存在。ContentResolver查询处理的数据有可能文件路径并不存在。
*
* @param filePath
* @return
*/
private static boolean checkImgExists(String filePath) {
return new File(filePath).exists();
}
/**
* 把图片按文件夹拆分,第一个文件夹保存所有的图片
*
* @param images
* @return
*/
private static ArrayList<Folder> splitFolder(ArrayList<Image> images) {
ArrayList<Folder> folders = new ArrayList<>();
folders.add(new Folder("全部图片", images));
if (images != null && !images.isEmpty()) {
int size = images.size();
for (int i = 0; i < size; i++) {
String path = images.get(i).getPath();
String name = getFolderName(path);
if (StringUtils.isNotEmptyString(name)) {
Folder folder = getFolder(name, folders);
folder.addImage(images.get(i));
}
}
}
return folders;
}
/**
* Java文件操作 获取文件扩展名
*/
public static String getExtensionName(String filename) {
if (filename != null && filename.length() > 0) {
int dot = filename.lastIndexOf('.');
if (dot > -1 && dot < filename.length() - 1) {
return filename.substring(dot + 1);
}
}
return "";
}
/**
* 根据图片路径,获取图片文件夹名称
*
* @param path
* @return
*/
private static String getFolderName(String path) {
if (StringUtils.isNotEmptyString(path)) {
String[] strings = path.split(File.separator);
if (strings.length >= 2) {
return strings[strings.length - 2];
}
}
return "";
}
private static Folder getFolder(String name, List<Folder> folders) {
if (!folders.isEmpty()) {
int size = folders.size();
for (int i = 0; i < size; i++) {
Folder folder = folders.get(i);
if (name.equals(folder.getName())) {
return folder;
}
}
}
Folder newFolder = new Folder(name);
folders.add(newFolder);
return newFolder;
}
public interface DataCallback {
void onSuccess(ArrayList<Folder> folders);
}
}

View File

@@ -0,0 +1,42 @@
package imageselector.utils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class DateUtils {
public static String getImageTime(long time) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
Calendar imageTime = Calendar.getInstance();
imageTime.setTimeInMillis(time);
if (sameDay(calendar, imageTime)) {
return "今天";
} else if (sameWeek(calendar, imageTime)) {
return "本周";
} else if (sameMonth(calendar, imageTime)) {
return "本月";
} else {
Date date = new Date(time);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM");
return sdf.format(date);
}
}
public static boolean sameDay(Calendar calendar1, Calendar calendar2) {
return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR)
&& calendar1.get(Calendar.DAY_OF_YEAR) == calendar2.get(Calendar.DAY_OF_YEAR);
}
public static boolean sameWeek(Calendar calendar1, Calendar calendar2) {
return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR)
&& calendar1.get(Calendar.WEEK_OF_YEAR) == calendar2.get(Calendar.WEEK_OF_YEAR);
}
public static boolean sameMonth(Calendar calendar1, Calendar calendar2) {
return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR)
&& calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
}
}

View File

@@ -0,0 +1,174 @@
package imageselector.utils;
import android.app.Activity;
import android.support.v4.app.Fragment;
import java.util.ArrayList;
import imageselector.ClipImageActivity;
import imageselector.ImageSelectorActivity;
/**
* Depiction:
* Author:lry
* Date:2018/6/25
*/
public class ImageSelector {
/**
* 图片选择的结果
*/
public static final String SELECT_RESULT = "select_result";
/**
* 是否是来自于相机拍照的图片,
* 只有本次调用相机拍出来的照片返回时才为true。
* 当为true时图片返回当结果有且只有一张图片。
*/
public static final String IS_CAMERA_IMAGE = "is_camera_image";
//最大的图片选择数
public static final String MAX_SELECT_COUNT = "max_select_count";
//是否单选
public static final String IS_SINGLE = "is_single";
//是否点击放大图片查看
public static final String IS_VIEW_IMAGE = "is_view_image";
//是否使用拍照功能
public static final String USE_CAMERA = "is_camera";
//原来已选择的图片
public static final String SELECTED = "selected";
//初始位置
public static final String POSITION = "position";
public static final String IS_CONFIRM = "is_confirm";
public static final int RESULT_CODE = 0x00000012;
public static ImageSelectorBuilder builder() {
return new ImageSelectorBuilder();
}
public static class ImageSelectorBuilder {
private boolean isCrop = false;
private boolean useCamera = true;
private boolean isSingle = false;
private boolean isViewImage = true;
private int maxSelectCount;
private ArrayList<String> selected;
/**
* 是否使用图片剪切功能。默认false。如果使用了图片剪切功能相册只能单选。
*
* @param isCrop
* @return
*/
public ImageSelectorBuilder setCrop(boolean isCrop) {
this.isCrop = isCrop;
return this;
}
/**
* 是否单选
*
* @param isSingle
* @return
*/
public ImageSelectorBuilder setSingle(boolean isSingle) {
this.isSingle = isSingle;
return this;
}
/**
* 是否点击放大图片查看,默认为true
*
* @param isViewImage
* @return
*/
public ImageSelectorBuilder setViewImage(boolean isViewImage) {
this.isViewImage = isViewImage;
return this;
}
/**
* 是否使用拍照功能。
*
* @param useCamera 默认为true
* @return
*/
public ImageSelectorBuilder useCamera(boolean useCamera) {
this.useCamera = useCamera;
return this;
}
/**
* 图片的最大选择数量小于等于0时不限数量isSingle为false时才有用。
*
* @param maxSelectCount
* @return
*/
public ImageSelectorBuilder setMaxSelectCount(int maxSelectCount) {
this.maxSelectCount = maxSelectCount;
return this;
}
/**
* 接收从外面传进来的已选择的图片列表。当用户原来已经有选择过图片,现在重新打开
* 选择器,允许用户把先前选过的图片传进来,并把这些图片默认为选中状态。
*
* @param selected
* @return
*/
public ImageSelectorBuilder setSelected(ArrayList<String> selected) {
this.selected = selected;
return this;
}
/**
* 打开相册
*
* @param activity
* @param requestCode
*/
public void start(Activity activity, int requestCode) {
if (isCrop) {
ClipImageActivity.openActivity(activity, requestCode, isViewImage, useCamera, selected);
} else {
ImageSelectorActivity.openActivity(activity, requestCode, isSingle, isViewImage,
useCamera, maxSelectCount, selected);
}
}
/**
* 打开相册
*
* @param fragment
* @param requestCode
*/
public void start(Fragment fragment, int requestCode) {
if (isCrop) {
ClipImageActivity.openActivity(fragment, requestCode, isViewImage, useCamera, selected);
} else {
ImageSelectorActivity.openActivity(fragment, requestCode, isSingle, isViewImage,
useCamera, maxSelectCount, selected);
}
}
/**
* 打开相册
*
* @param fragment
* @param requestCode
*/
public void start(android.app.Fragment fragment, int requestCode) {
if (isCrop) {
ClipImageActivity.openActivity(fragment, requestCode, isViewImage, useCamera, selected);
} else {
ImageSelectorActivity.openActivity(fragment, requestCode, isSingle, isViewImage,
useCamera, maxSelectCount, selected);
}
}
}
}

View File

@@ -0,0 +1,80 @@
package imageselector.utils;
import android.app.Activity;
import java.util.ArrayList;
import imageselector.ClipImageActivity;
import imageselector.ImageSelectorActivity;
/**
* 提供给外界相册的调用的工具类
*/
@Deprecated
public class ImageSelectorUtils {
//图片选择的结果
public static final String SELECT_RESULT = ImageSelector.SELECT_RESULT;
/**
* 打开相册,选择图片,可多选,不限数量。
*
* @param activity
* @param requestCode
*/
public static void openPhoto(Activity activity, int requestCode) {
openPhoto(activity, requestCode, false, 0);
}
/**
* 打开相册,选择图片,可多选,不限数量。
*
* @param activity
* @param requestCode
* @param selected 接收从外面传进来的已选择的图片列表。当用户原来已经有选择过图片,现在重新打开
* 选择器,允许用户把先前选过的图片传进来,并把这些图片默认为选中状态。
*/
public static void openPhoto(Activity activity, int requestCode, ArrayList<String> selected) {
openPhoto(activity, requestCode, false, 0, selected);
}
/**
* 打开相册,选择图片,可多选,限制最大的选择数量。
*
* @param activity
* @param requestCode
* @param isSingle 是否单选
* @param maxSelectCount 图片的最大选择数量小于等于0时不限数量isSingle为false时才有用。
*/
public static void openPhoto(Activity activity, int requestCode,
boolean isSingle, int maxSelectCount) {
openPhoto(activity, requestCode, isSingle, maxSelectCount, null);
}
/**
* 打开相册,选择图片,可多选,限制最大的选择数量。
*
* @param activity
* @param requestCode
* @param isSingle 是否单选
* @param maxSelectCount 图片的最大选择数量小于等于0时不限数量isSingle为false时才有用。
* @param selected 接收从外面传进来的已选择的图片列表。当用户原来已经有选择过图片,现在重新打开
* 选择器,允许用户把先前选过的图片传进来,并把这些图片默认为选中状态。
*/
public static void openPhoto(Activity activity, int requestCode,
boolean isSingle, int maxSelectCount, ArrayList<String> selected) {
ImageSelectorActivity.openActivity(activity, requestCode, isSingle, true,
true, maxSelectCount, selected);
}
/**
* 打开相册,单选图片并剪裁。
*
* @param activity
* @param requestCode
*/
public static void openPhotoAndClip(Activity activity, int requestCode) {
ClipImageActivity.openActivity(activity, requestCode, true, true, null);
}
}

View File

@@ -0,0 +1,166 @@
package imageselector.utils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.text.format.DateFormat;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;
public class ImageUtil {
public static String saveImage(Bitmap bitmap, String path) {
String name = new DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".png";
FileOutputStream b = null;
File file = new File(path);
if (!file.exists()) {
file.mkdirs();// 创建文件夹
}
String fileName = path + File.separator + name;
try {
b = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, 75, b);// 把数据写入文件
return fileName;
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (b != null) {
b.flush();
b.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return "";
}
public static Bitmap zoomBitmap(Bitmap bm, int reqWidth, int reqHeight) {
// 获得图片的宽高
int width = bm.getWidth();
int height = bm.getHeight();
// 计算缩放比例
float scaleWidth = ((float) reqWidth) / width;
float scaleHeight = ((float) reqHeight) / height;
float scale = Math.min(scaleWidth, scaleHeight);
// 取得想要缩放的matrix参数
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
// 得到新的图片
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,
true);
return newbm;
}
/**
* 根据计算的inSampleSize得到压缩后图片
*
* @param pathName
* @param reqWidth
* @param reqHeight
* @return
*/
public static Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) {
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(pathName);
int result = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
switch (result) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
return null;
}
try {
// 第一次解析将inJustDecodeBounds设置为true来获取图片大小
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
// 调用上面定义的方法计算inSampleSize值
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// 使用获取到的inSampleSize值再次解析图片
options.inJustDecodeBounds = false;
// options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeFile(pathName, options);
if (degree != 0) {
Bitmap newBitmap = rotateImageView(bitmap, degree);
bitmap.recycle();
bitmap = null;
return newBitmap;
}
return bitmap;
} catch (OutOfMemoryError error) {
Log.e("eee", "内存泄露!");
return null;
}
}
/**
* 旋转图片
*
* @param bitmap
* @param angle
* @return Bitmap
*/
public static Bitmap rotateImageView(Bitmap bitmap, int angle) {
//旋转图片 动作
Matrix matrix = new Matrix();
matrix.postRotate(angle);
// 创建新的图片
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
/**
* 计算inSampleSize用于压缩图片
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
private static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// 源图片的宽度
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
if (width > reqWidth && height > reqHeight) {
// 计算出实际宽度和目标宽度的比率
int widthRatio = Math.round((float) width / (float) reqWidth);
int heightRatio = Math.round((float) height / (float) reqHeight);
inSampleSize = Math.max(widthRatio, heightRatio);
}
return inSampleSize;
}
}

View File

@@ -0,0 +1,12 @@
package imageselector.utils;
public class StringUtils {
public static boolean isNotEmptyString(final String str) {
return str != null && str.length() > 0;
}
public static boolean isEmptyString(final String str) {
return str == null || str.length() <= 0;
}
}

View File

@@ -0,0 +1,357 @@
package imageselector.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.WindowManager;
public class ClipImageView extends AppCompatImageView {
private PointF mDownPoint;
private PointF mMiddlePoint;
private Matrix mMatrix;
private Matrix mTempMatrix;
private int mBitmapWidth;
private int mBitmapHeight;
private final int MODE_NONE = 0;
private final int MODE_DRAG = 1;
private final int MODE_ZOOM = 2;
private final int MODE_POINTER_UP = 3;
private int CURR_MODE = MODE_NONE;
private float mLastDistance;
private Paint mFrontGroundPaint = new Paint();
private int mTargetWidth;
private int mTargetHeight;
private Xfermode mXfermode;
private Rect r;
private RectF rf;
private float mCircleCenterX, mCircleCenterY;
private float mCircleX, mCircleY;
private boolean isCutImage;
public ClipImageView(Context context) {
super(context);
setRadius();
}
public ClipImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setRadius();
}
/**
* 设置要剪裁的图片
*
* @param bitmap
*/
public void setBitmapData(Bitmap bitmap) {
if (bitmap == null) {
return;
}
mBitmapHeight = bitmap.getHeight();
mBitmapWidth = bitmap.getWidth();
setImageBitmap(bitmap);
init();
}
private void init() {
mDownPoint = new PointF();
mMiddlePoint = new PointF();
mMatrix = new Matrix();
mTempMatrix = new Matrix();
mFrontGroundPaint.setColor(Color.parseColor("#ac000000"));
mFrontGroundPaint.setAntiAlias(true);
mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
setScaleType(ScaleType.MATRIX);
post(new Runnable() {
@Override
public void run() {
center();
}
});
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mCircleCenterX = getWidth() / 2;
mCircleCenterY = getHeight() / 2;
mCircleX = mCircleCenterX - mTargetWidth / 2;
mCircleY = mCircleCenterY - mTargetHeight / 2;
}
private void setRadius() {
int width = getScreenWidth(getContext());
int height = getScreenHeight(getContext());
if (width > height) {
mTargetWidth = height;
mTargetHeight = height;
} else {
mTargetWidth = width;
mTargetHeight = width;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isCutImage) {
return;
}
if (rf == null || rf.isEmpty()) {
r = new Rect(0, 0, getWidth(), getHeight());
rf = new RectF(r);
}
// 画入前景圆形蒙板层
int sc = canvas.saveLayer(rf, null, Canvas.MATRIX_SAVE_FLAG
| Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
| Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG | Canvas.ALL_SAVE_FLAG);
//画入矩形黑色半透明蒙板层
canvas.drawRect(r, mFrontGroundPaint);
//设置Xfermode目的是为了去除矩形黑色半透明蒙板层和圆形的相交部分
mFrontGroundPaint.setXfermode(mXfermode);
//画入正方形
canvas.drawRect(mCircleCenterX - mTargetWidth / 2, mCircleCenterY - mTargetHeight / 2,
mCircleCenterX + mTargetWidth / 2, mCircleCenterY + mTargetHeight / 2, mFrontGroundPaint);
canvas.restoreToCount(sc);
//清除Xfermode防止影响下次画图
mFrontGroundPaint.setXfermode(null);
}
/**
* 截取Bitmap
*
* @return
*/
public Bitmap clipImage() {
isCutImage = true;
Paint paint = new Paint();
setDrawingCacheEnabled(true);
Bitmap bitmap = getDrawingCache();
Bitmap targetBitmap = Bitmap.createBitmap(mTargetWidth, mTargetHeight,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
RectF dst = new RectF(-bitmap.getWidth() / 2 + mTargetWidth / 2, -getHeight()
/ 2 + mTargetHeight / 2, bitmap.getWidth() / 2
+ mTargetWidth / 2, getHeight() / 2 + mTargetHeight / 2);
canvas.drawBitmap(bitmap, null, dst, paint);
setDrawingCacheEnabled(false);
bitmap.recycle();
bitmap = null;
isCutImage = false;
//返回正方形图片
return targetBitmap;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mMatrix == null) {
return super.onTouchEvent(event);
}
float[] values = new float[9];
mMatrix.getValues(values);
float left = values[Matrix.MTRANS_X];
float top = values[Matrix.MTRANS_Y];
float right = (left + mBitmapWidth * values[Matrix.MSCALE_X]);
float bottom = (top + mBitmapHeight * values[Matrix.MSCALE_Y]);
float x = 0f;
float y = 0f;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
CURR_MODE = MODE_DRAG;
mDownPoint.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_POINTER_DOWN:
if (getDistance(event) > 10f) {
CURR_MODE = MODE_ZOOM;
midPoint(mMiddlePoint, event);
mLastDistance = getDistance(event);
}
break;
case MotionEvent.ACTION_MOVE:
//如果当前模式为拖曳(单指触屏)
if (CURR_MODE == MODE_DRAG || CURR_MODE == MODE_POINTER_UP) {
if (CURR_MODE == MODE_DRAG) {
x = event.getX() - mDownPoint.x;
y = event.getY() - mDownPoint.y;
//left靠边
if (x + left > mCircleX) {
x = 0;
}
//right靠边
if (x + right < mCircleX + mTargetWidth) {
x = 0;
}
//top靠边
if (y + top > mCircleY) {
y = 0;
}
//bottom靠边
if (y + bottom < mCircleY + mTargetHeight) {
y = 0;
}
mMatrix.postTranslate(x, y);
mDownPoint.set(event.getX(), event.getY());
} else {
CURR_MODE = MODE_DRAG;
mDownPoint.set(event.getX(), event.getY());
}
} else {
//否则当前模式为缩放(双指触屏)
float distance = getDistance(event);
if (distance > 10f) {
float scale = distance / mLastDistance;
//left靠边
if (left >= mCircleX) {
mMiddlePoint.x = 0;
}
//right靠边
if (right <= mCircleX + mTargetWidth) {
mMiddlePoint.x = right;
}
//top靠边
if (top >= mCircleY) {
mMiddlePoint.y = 0;
}
//bottom靠边
if (bottom <= mCircleY + mTargetHeight) {
mMiddlePoint.y = bottom;
}
mTempMatrix.set(mMatrix);
mTempMatrix.postScale(scale, scale, mMiddlePoint.x, mMiddlePoint.y);
float[] temp_values = new float[9];
mTempMatrix.getValues(temp_values);
float temp_left = temp_values[Matrix.MTRANS_X];
float temp_top = temp_values[Matrix.MTRANS_Y];
float temp_right = (temp_left + mBitmapWidth * temp_values[Matrix.MSCALE_X]);
float temp_bottom = (temp_top + mBitmapHeight * temp_values[Matrix.MSCALE_Y]);
//靠边预判断
if (temp_left > mCircleX || temp_right < mCircleX + mTargetWidth ||
temp_top > mCircleY || temp_bottom < mCircleY + mTargetHeight) {
return true;
}
mMatrix.postScale(scale, scale, mMiddlePoint.x, mMiddlePoint.y);
mLastDistance = getDistance(event);
}
}
break;
case MotionEvent.ACTION_UP:
CURR_MODE = MODE_NONE;
break;
case MotionEvent.ACTION_POINTER_UP:
CURR_MODE = MODE_POINTER_UP;
break;
}
setImageMatrix(mMatrix);
return true;
}
/**
* 两点的距离
*/
private float getDistance(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
/**
* 两点的中点
*/
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
/**
* 横向、纵向居中
*/
protected void center() {
float height = mBitmapHeight;
float width = mBitmapWidth;
float screenWidth = getWidth();
float screenHeight = getHeight();
float scale = 1f;
if (width >= height) {
scale = screenWidth / width;
if (scale * height < mTargetHeight) {
scale = mTargetHeight / height;
}
} else {
if (height <= screenHeight) {
scale = screenWidth / width;
} else {
scale = screenHeight / height;
}
if (scale * width < mTargetWidth) {
scale = mTargetWidth / width;
}
}
float deltaX = (screenWidth - width * scale) / 2f;
float deltaY = (screenHeight - height * scale) / 2f;
mMatrix.postScale(scale, scale);
mMatrix.postTranslate(deltaX, deltaY);
setImageMatrix(mMatrix);
}
/**
* 获得屏幕宽度
*/
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* 获得屏幕高度
*/
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
}

View File

@@ -0,0 +1,30 @@
package imageselector.view;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* 继承ViewPager并在onInterceptTouchEvent捕捉异常。
* 因为ViewPager嵌套PhotoView使用有时候会发生IllegalArgumentException异常。
*/
public class MyViewPager extends ViewPager {
public MyViewPager(Context context) {
super(context);
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
return false;
}
}
}

View File

@@ -0,0 +1,28 @@
package imageselector.view;
import android.content.Context;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
/**
* 正方形的ImageView
*/
public class SquareImageView extends AppCompatImageView {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}