fragmentStack = new Stack<>();
+ private final String CLASS_NAME = getClass().getSimpleName();
protected Bundle mSaveDataBundle;
protected String BUNDLE_KEY = "KEY_" + CLASS_NAME;
-
protected Configuration mConfiguration;
@Override
@@ -47,29 +50,29 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
Bundle argsBundle = getArguments();
- if(savedInstanceState != null){
+ if (savedInstanceState != null) {
mConfiguration = savedInstanceState.getParcelable(EXTRA_CONFIGURATION);
}
- if(mConfiguration == null && argsBundle != null) {
+ if (mConfiguration == null && argsBundle != null) {
mConfiguration = argsBundle.getParcelable(EXTRA_CONFIGURATION);
}
- if(mConfiguration != null){
- if(argsBundle == null){
+ if (mConfiguration != null) {
+ if (argsBundle == null) {
argsBundle = savedInstanceState;
}
onViewCreatedOk(view, argsBundle);
setTheme();
} else {
- if(getActivity() != null && !getActivity().isFinishing()) {
- getActivity().finish();
+ FragmentActivity activity = getActivity();
+ if (activity != null && !activity.isFinishing()) {
+ activity.finish();
}
}
}
public abstract void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState);
-
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@@ -77,6 +80,30 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
return inflater.inflate(getContentView(), container, false);
}
+ @Override
+ public void startActivityForResult(Intent intent, int requestCode) {
+ Logger.i("startActivityForResult");
+ Fragment parentFragment = getParentFragment();
+ if (null != parentFragment) {
+ fragmentStack.push(this);
+ parentFragment.startActivityForResult(intent, requestCode);
+ } else {
+ super.startActivityForResult(intent, requestCode);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ Logger.i("onActivityResult");
+ BaseFragment fragment = fragmentStack.isEmpty() ? null : fragmentStack.pop();
+ if (null != fragment) {
+ fragment.onActivityResult(requestCode, resultCode, data);
+ return;
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+
@Override
public void onStart() {
super.onStart();
@@ -116,9 +143,10 @@ public void onDetach() {
public abstract int getContentView();
- public void setTheme(){}
+ public void setTheme() {
+ }
- private void printFragmentLife(String method){
+ private void printFragmentLife(String method) {
Logger.i(String.format("Fragment:%s Method:%s", CLASS_NAME, method));
}
@@ -147,7 +175,7 @@ private void saveStateToArguments() {
if (mSaveDataBundle != null) {
Bundle b = getArguments();
- if(b != null) {
+ if (b != null) {
b.putBundle(BUNDLE_KEY, mSaveDataBundle);
}
}
@@ -155,7 +183,7 @@ private void saveStateToArguments() {
private boolean restoreStateFromArguments() {
Bundle b = getArguments();
- if(b != null) {
+ if (b != null) {
mSaveDataBundle = b.getBundle(BUNDLE_KEY);
if (mSaveDataBundle != null) {
restoreState();
@@ -177,7 +205,6 @@ private void restoreState() {
/**
* 恢复数据
- * @param savedInstanceState
*/
protected abstract void onRestoreState(Bundle savedInstanceState);
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java
index 8971cf3e..90719709 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaGridFragment.java
@@ -4,13 +4,10 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.View;
@@ -19,7 +16,18 @@
import android.widget.TextView;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.FragmentActivity;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.hjq.permissions.OnPermissionCallback;
+import com.yalantis.ucrop.UCrop;
import com.yalantis.ucrop.UCropActivity;
+import com.yalantis.ucrop.model.AspectRatio;
+import com.zhy.base.fileprovider.FileProvider7;
import java.io.File;
import java.text.SimpleDateFormat;
@@ -27,6 +35,7 @@
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Random;
import cn.finalteam.rxgalleryfinal.Configuration;
import cn.finalteam.rxgalleryfinal.R;
@@ -38,16 +47,17 @@
import cn.finalteam.rxgalleryfinal.bean.MediaBean;
import cn.finalteam.rxgalleryfinal.presenter.impl.MediaGridPresenterImpl;
import cn.finalteam.rxgalleryfinal.rxbus.RxBus;
-import cn.finalteam.rxgalleryfinal.rxbus.RxBusSubscriber;
+import cn.finalteam.rxgalleryfinal.rxbus.RxBusDisposable;
import cn.finalteam.rxgalleryfinal.rxbus.event.CloseMediaViewPageFragmentEvent;
import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent;
import cn.finalteam.rxgalleryfinal.rxbus.event.MediaCheckChangeEvent;
+import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPageFragmentEvent;
import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPreviewFragmentEvent;
import cn.finalteam.rxgalleryfinal.rxbus.event.RequestStorageReadAccessPermissionEvent;
-import cn.finalteam.rxgalleryfinal.rxbus.event.OpenMediaPageFragmentEvent;
import cn.finalteam.rxgalleryfinal.ui.activity.MediaActivity;
import cn.finalteam.rxgalleryfinal.ui.adapter.BucketAdapter;
import cn.finalteam.rxgalleryfinal.ui.adapter.MediaGridAdapter;
+import cn.finalteam.rxgalleryfinal.ui.base.IRadioImageCheckedListener;
import cn.finalteam.rxgalleryfinal.ui.widget.FooterAdapter;
import cn.finalteam.rxgalleryfinal.ui.widget.HorizontalDividerItemDecoration;
import cn.finalteam.rxgalleryfinal.ui.widget.MarginDecoration;
@@ -55,36 +65,50 @@
import cn.finalteam.rxgalleryfinal.utils.CameraUtils;
import cn.finalteam.rxgalleryfinal.utils.DeviceUtils;
import cn.finalteam.rxgalleryfinal.utils.EmptyViewUtils;
+import cn.finalteam.rxgalleryfinal.utils.FileUtils;
import cn.finalteam.rxgalleryfinal.utils.Logger;
import cn.finalteam.rxgalleryfinal.utils.MediaScanner;
import cn.finalteam.rxgalleryfinal.utils.MediaUtils;
import cn.finalteam.rxgalleryfinal.utils.PermissionCheckUtils;
+import cn.finalteam.rxgalleryfinal.utils.SimpleDateUtils;
import cn.finalteam.rxgalleryfinal.utils.ThemeUtils;
import cn.finalteam.rxgalleryfinal.view.MediaGridView;
-import rx.Observable;
-import rx.Observer;
-import rx.Subscription;
-import rx.android.schedulers.AndroidSchedulers;
-import rx.schedulers.Schedulers;
+import io.reactivex.Observable;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.observers.DisposableObserver;
+import io.reactivex.schedulers.Schedulers;
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/7 上午10:02
+ *
+ * Desction: 直接暴漏
+ * Author:KARL-Dujinyang
+ * Date:2017.
*/
public class MediaGridFragment extends BaseFragment implements MediaGridView, RecyclerViewFinal.OnLoadMoreListener,
- FooterAdapter.OnItemClickListener,View.OnClickListener, MediaScanner.ScanCallback, BucketAdapter.OnRecyclerViewItemClickListener {
-
+ FooterAdapter.OnItemClickListener, View.OnClickListener, MediaScanner.ScanCallback, BucketAdapter.OnRecyclerViewItemClickListener {
+
+ private static final String IMAGE_TYPE = "image/jpeg";
+ //接口-单选-是否裁剪
+ public static IRadioImageCheckedListener iListenerRadio;
+ //预留公开命名接口
+ private static File mImageStoreDir;
+ private static File mImageStoreCropDir; //裁剪目录
+ //裁剪后+name
+ private static File mCropPath = null;
private final String IMAGE_STORE_FILE_NAME = "IMG_%s.jpg";
+ private final String VIDEO_STORE_FILE_NAME = "IMG_%s.mp4";
private final int TAKE_IMAGE_REQUEST_CODE = 1001;
+ private final int CROP_IMAGE_REQUEST_CODE = 1011;
private final String TAKE_URL_STORAGE_KEY = "take_url_storage_key";
private final String BUCKET_ID_KEY = "bucket_id_key";
-
private final int LIMIT = 23;
-
MediaGridPresenterImpl mMediaGridPresenter;
DisplayMetrics mScreenSize;
-
private List mMediaBeanList;
private MediaGridAdapter mMediaGridAdapter;
private RecyclerViewFinal mRvMedia;
@@ -96,20 +120,31 @@ public class MediaGridFragment extends BaseFragment implements MediaGridView, Re
private TextView mTvFolderName;
private TextView mTvPreview;
private RelativeLayout mRlRootView;
-
+ //扫描
private MediaScanner mMediaScanner;
-
private int mPage = 1;
- private File mImageStoreDir;
- private File mImageStoreCropDir;
private String mImagePath;
private String mBucketId = String.valueOf(Integer.MIN_VALUE);
private MediaActivity mMediaActivity;
- private Subscription mSubscrMediaCheckChangeEvent;
- private Subscription mSubscrCloseMediaViewPageFragmentEvent;
- private Subscription mSubscrRequestStorageReadAccessPermissionEvent;
+ private Disposable mMediaCheckChangeDisposable;
+ private Disposable mCloseMediaViewPageFragmentDisposable;
+ private Disposable mRequestStorageReadAccessPermissionDisposable;
+
+ private SlideInUnderneathAnimation slideInUnderneathAnimation;
+ private SlideOutUnderneathAnimation slideOutUnderneathAnimation;
+
+ private int uCropStatusColor;
+ private int uCropToolbarColor;
+ private int uCropActivityWidgetColor;
+ private int uCropToolbarWidgetColor;
+ private String uCropTitle;
+ private String requestStorageAccessPermissionTips;
+
+ private boolean currShowType ;
+
+ private static String rootPath = "myrxgalleryfinal";
public static MediaGridFragment newInstance(Configuration configuration) {
MediaGridFragment fragment = new MediaGridFragment();
@@ -119,17 +154,28 @@ public static MediaGridFragment newInstance(Configuration configuration) {
return fragment;
}
+ public static void setRadioListener(IRadioImageCheckedListener radioListener) {
+ MediaGridFragment.iListenerRadio = radioListener;
+ }
+
+ public static String getImageStoreDirByStr() {
+ if (mImageStoreDir != null)
+ return mImageStoreDir.getPath();
+ else{
+ mImageStoreDir = new File(Environment.getExternalStorageDirectory(), rootPath);
+ if (!mImageStoreDir.exists()) {
+ mImageStoreDir.mkdirs();
+ }
+ }
+ return mImageStoreDir.getPath();
+ }
+
@Override
public void onAttach(Context context) {
super.onAttach(context);
- if(context instanceof MediaActivity) {
+ if (context instanceof MediaActivity) {
mMediaActivity = (MediaActivity) context;
}
- mImageStoreDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/RxGalleryFinal/");
- mImageStoreCropDir = new File(mImageStoreDir, "crop");
- if (!mImageStoreCropDir.exists()) {
- mImageStoreCropDir.mkdirs();
- }
mMediaScanner = new MediaScanner(context);
}
@@ -140,6 +186,7 @@ public int getContentView() {
@Override
public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) {
+
mRvMedia = (RecyclerViewFinal) view.findViewById(R.id.rv_media);
mLlEmptyView = (LinearLayout) view.findViewById(R.id.ll_empty_view);
mRvBucket = (RecyclerView) view.findViewById(R.id.rv_bucket);
@@ -147,7 +194,7 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) {
mRlRootView = (RelativeLayout) view.findViewById(R.id.rl_root_view);
mRvMedia.setEmptyView(mLlEmptyView);
- GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 3);
+ GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), mConfiguration.getSpanCount());
gridLayoutManager.setOrientation(GridLayoutManager.VERTICAL);
mRvMedia.addItemDecoration(new MarginDecoration(getContext()));
mRvMedia.setLayoutManager(gridLayoutManager);
@@ -159,15 +206,24 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) {
mTvPreview = (TextView) view.findViewById(R.id.tv_preview);
mTvPreview.setOnClickListener(this);
mTvPreview.setEnabled(false);
- if(mConfiguration.isRadio()){
+ currShowType = mConfiguration.isImage();
+ if (mConfiguration.isRadio()) {
view.findViewById(R.id.tv_preview_vr).setVisibility(View.GONE);
mTvPreview.setVisibility(View.GONE);
+
+ } else {
+ if (mConfiguration.isHidePreview()) {
+ view.findViewById(R.id.tv_preview_vr).setVisibility(View.GONE);
+ mTvPreview.setVisibility(View.GONE);
+ } else {
+ view.findViewById(R.id.tv_preview_vr).setVisibility(View.VISIBLE);
+ mTvPreview.setVisibility(View.VISIBLE);
+ }
}
mMediaBeanList = new ArrayList<>();
mScreenSize = DeviceUtils.getScreenSize(getContext());
- mMediaGridAdapter = new MediaGridAdapter(mMediaActivity, mMediaBeanList,
- mScreenSize.widthPixels, mConfiguration);
+ mMediaGridAdapter = new MediaGridAdapter(mMediaActivity, mMediaBeanList, mScreenSize.widthPixels, mConfiguration);
mRvMedia.setAdapter(mMediaGridAdapter);
mMediaGridPresenter = new MediaGridPresenterImpl(getContext(), mConfiguration.isImage());
mMediaGridPresenter.setMediaGridView(this);
@@ -182,40 +238,63 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) {
.build());
mRvBucket.setLayoutManager(linearLayoutManager);
mBucketBeanList = new ArrayList<>();
- mBucketAdapter = new BucketAdapter(getContext(), mBucketBeanList, mConfiguration);
+ mBucketAdapter = new BucketAdapter(getContext(),mBucketBeanList, mConfiguration, ContextCompat.getColor(getContext(), R.color.gallery_bucket_list_item_normal_color));
mRvBucket.setAdapter(mBucketAdapter);
mRvMedia.setOnItemClickListener(this);
mMediaGridPresenter.getBucketList();
mBucketAdapter.setOnRecyclerViewItemClickListener(this);
mRlBucektOverview.setVisibility(View.INVISIBLE);
- new SlideInUnderneathAnimation(mRvBucket)
+
+ if (slideInUnderneathAnimation == null) {
+ slideInUnderneathAnimation = new SlideInUnderneathAnimation(mRvBucket);
+ }
+
+ slideInUnderneathAnimation
.setDirection(Animation.DIRECTION_DOWN)
.animate();
subscribeEvent();
Activity activity = mMediaActivity;
- if(activity == null){
+ if (activity == null) {
activity = getActivity();
}
+ if (mConfiguration.isImage()) {
+ mTvFolderName.setText(R.string.gallery_all_image);
+ } else {
+ mTvFolderName.setText(R.string.gallery_all_video);
+ }
+
String requestStorageAccessPermissionTips = ThemeUtils.resolveString(getContext(),
R.attr.gallery_request_storage_access_permission_tips,
R.string.gallery_default_request_storage_access_permission_tips);
- boolean success = PermissionCheckUtils.checkReadExternalPermission(activity, requestStorageAccessPermissionTips,
- MediaActivity.REQUEST_STORAGE_READ_ACCESS_PERMISSION);
- if(success) {
- mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT);
- }
+ PermissionCheckUtils.checkWriteExternalPermission(activity, requestStorageAccessPermissionTips,
+ MediaActivity.REQUEST_STORAGE_WRITE_ACCESS_PERMISSION,new OnPermissionCallback() {
+
+ @Override
+ public void onGranted(List permissions, boolean all) {
+ mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType);
+ }
+
+ @Override
+ public void onDenied(List permissions, boolean never) {
+
+ }
+ });
+
}
+ /**
+ * RxBus
+ */
private void subscribeEvent() {
- mSubscrMediaCheckChangeEvent = RxBus.getDefault().toObservable(MediaCheckChangeEvent.class)
- .subscribe(new RxBusSubscriber() {
+ mMediaCheckChangeDisposable = RxBus.getDefault().toObservable(MediaCheckChangeEvent.class)
+ .subscribeWith(new RxBusDisposable() {
@Override
protected void onEvent(MediaCheckChangeEvent mediaCheckChangeEvent) {
- if(mMediaActivity.getCheckedList().size() == 0){
+ if (mMediaActivity.getCheckedList().size() == 0) {
mTvPreview.setEnabled(false);
} else {
mTvPreview.setEnabled(true);
@@ -223,53 +302,90 @@ protected void onEvent(MediaCheckChangeEvent mediaCheckChangeEvent) {
}
});
- RxBus.getDefault().add(mSubscrMediaCheckChangeEvent);
+ RxBus.getDefault().add(mMediaCheckChangeDisposable);
- mSubscrCloseMediaViewPageFragmentEvent = RxBus.getDefault().toObservable(CloseMediaViewPageFragmentEvent.class)
- .subscribe(new RxBusSubscriber() {
+ mCloseMediaViewPageFragmentDisposable = RxBus.getDefault().toObservable(CloseMediaViewPageFragmentEvent.class)
+ .subscribeWith(new RxBusDisposable() {
@Override
protected void onEvent(CloseMediaViewPageFragmentEvent closeMediaViewPageFragmentEvent) throws Exception {
mMediaGridAdapter.notifyDataSetChanged();
}
});
- RxBus.getDefault().add(mSubscrCloseMediaViewPageFragmentEvent);
+ RxBus.getDefault().add(mCloseMediaViewPageFragmentDisposable);
- mSubscrRequestStorageReadAccessPermissionEvent = RxBus.getDefault().toObservable(RequestStorageReadAccessPermissionEvent.class)
- .subscribe(new RxBusSubscriber() {
+ mRequestStorageReadAccessPermissionDisposable = RxBus.getDefault().toObservable(RequestStorageReadAccessPermissionEvent.class)
+ .subscribeWith(new RxBusDisposable() {
@Override
protected void onEvent(RequestStorageReadAccessPermissionEvent requestStorageReadAccessPermissionEvent) throws Exception {
- if(requestStorageReadAccessPermissionEvent.isSuccess()){
- mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT);
+ if (requestStorageReadAccessPermissionEvent.getType() == RequestStorageReadAccessPermissionEvent.TYPE_WRITE) {
+ if (requestStorageReadAccessPermissionEvent.isSuccess()) {
+ mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType);
+ } else {
+ getActivity().finish();
+ }
} else {
- getActivity().finish();
+ if (requestStorageReadAccessPermissionEvent.isSuccess()) {
+ openCamera(mMediaActivity);
+ }
}
}
});
- RxBus.getDefault().add(mSubscrRequestStorageReadAccessPermissionEvent);
+ RxBus.getDefault().add(mRequestStorageReadAccessPermissionDisposable);
}
+ /**
+ * 设置主题
+ */
@Override
public void setTheme() {
super.setTheme();
+ uCropStatusColor = ThemeUtils.resolveColor(getActivity(), R.attr.gallery_ucrop_status_bar_color, R.color.gallery_default_ucrop_color_widget_active);
+ uCropToolbarColor = ThemeUtils.resolveColor(getActivity(), R.attr.gallery_ucrop_toolbar_color, R.color.gallery_default_ucrop_color_widget_active);
+ uCropActivityWidgetColor = ThemeUtils.resolveColor(getActivity(), R.attr.gallery_ucrop_activity_widget_color, R.color.gallery_default_ucrop_color_widget);
+ uCropToolbarWidgetColor = ThemeUtils.resolveColor(getActivity(), R.attr.gallery_ucrop_toolbar_widget_color, R.color.gallery_default_toolbar_widget_color);
+ uCropTitle = ThemeUtils.resolveString(getActivity(), R.attr.gallery_ucrop_toolbar_title, R.string.gallery_title_cut);
int pageColor = ThemeUtils.resolveColor(getContext(), R.attr.gallery_page_bg, R.color.gallery_default_page_bg);
mRlRootView.setBackgroundColor(pageColor);
+ requestStorageAccessPermissionTips = ThemeUtils.resolveString(getContext(), R.attr.gallery_request_camera_permission_tips, R.string.gallery_default_camera_access_permission_tips);
}
@Override
protected void onFirstTimeLaunched() {
+ if(mConfiguration.isOpenCameraOnStart()){
+ onLoadFile();
+ this.openCameraOnStart();
+ }
+ }
+
+ public void openCameraOnStart(){
+ if (!CameraUtils.hasCamera(getContext())) {
+ Toast.makeText(getContext(), R.string.gallery_device_no_camera_tips, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ openCamera(mMediaActivity);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ onLoadFile();
+ //直接刷新一次
+ // refreshUI();
}
+
@Override
public void loadMore() {
- mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT);
+ mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType);
}
@Override
public void onRequestMediaCallback(List list) {
- if(!mConfiguration.isHideCamera()) {
- if (mPage == 1 && TextUtils.equals(mBucketId, String.valueOf(Integer.MIN_VALUE))) {
+ if (!mConfiguration.isHideCamera()) {
+ if (mPage == 1 && TextUtils.equals(mBucketId, String.valueOf(Integer.MIN_VALUE))
+ && mMediaBeanList.size()==0) {
MediaBean takePhotoBean = new MediaBean();
takePhotoBean.setId(Integer.MIN_VALUE);
takePhotoBean.setBucketId(String.valueOf(Integer.MIN_VALUE));
@@ -277,7 +393,18 @@ public void onRequestMediaCallback(List list) {
}
}
if (list != null && list.size() > 0) {
- mMediaBeanList.addAll(list);
+ //说明原来有图片,说明是从相机返回,增量添加
+ if(mMediaBeanList.size()>1 && mPage==1 && currShowType== mConfiguration.isImage()){
+ list.removeAll(mMediaBeanList);
+ if(list!=null && list.size()>0){
+ mMediaBeanList.addAll(1,list);
+ checkMediaBean(list);
+ mMediaGridAdapter.notifyDataSetChanged();
+ }
+ return;
+ }else {
+ mMediaBeanList.addAll(list);
+ }
Logger.i(String.format("得到:%s张图片", list.size()));
} else {
Logger.i("没有更多图片");
@@ -286,9 +413,19 @@ public void onRequestMediaCallback(List list) {
mPage++;
- if (list == null || list.size() < LIMIT) {
- mRvMedia.setFooterViewHide(true);
- mRvMedia.setHasLoadMore(false);
+ if (list == null || list.size()==0 || list.size() <= (LIMIT-3)) {
+ if(currShowType== mConfiguration.isImage() && mConfiguration.isSelectBoth()
+ && TextUtils.equals(mBucketId, String.valueOf(Integer.MIN_VALUE))
+ ){
+ mPage = 1;
+ currShowType = !currShowType;
+ mRvMedia.setFooterViewHide(false);
+ mRvMedia.setHasLoadMore(true);
+ this.loadMore();
+ }else {
+ mRvMedia.setFooterViewHide(true);
+ mRvMedia.setHasLoadMore(false);
+ }
} else {
mRvMedia.setFooterViewHide(false);
mRvMedia.setHasLoadMore(true);
@@ -304,13 +441,12 @@ public void onRequestMediaCallback(List list) {
@Override
public void onRequestBucketCallback(List list) {
- if(list == null || list.size() == 0){
+ if (list == null || list.size() == 0) {
return;
}
mBucketBeanList.addAll(list);
mBucketAdapter.setSelectedBucket(list.get(0));
- mBucketAdapter.notifyDataSetChanged();
}
@Override
@@ -318,7 +454,7 @@ public void onItemClick(View view, int position) {
BucketBean bucketBean = mBucketBeanList.get(position);
String bucketId = bucketBean.getBucketId();
mRlBucektOverview.setVisibility(View.GONE);
- if(TextUtils.equals(mBucketId, bucketId)){
+ if (TextUtils.equals(mBucketId, bucketId)) {
return;
}
mBucketId = bucketId;
@@ -326,15 +462,20 @@ public void onItemClick(View view, int position) {
mRvMedia.setHasLoadMore(false);
mMediaBeanList.clear();
mMediaGridAdapter.notifyDataSetChanged();
+ mTvFolderName.setText(bucketBean.getBucketName());
mBucketAdapter.setSelectedBucket(bucketBean);
-
mRvMedia.setFooterViewHide(true);
mPage = 1;
- mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT);
+ currShowType = mConfiguration.isImage();
+ mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType);
}
@Override
public void onItemClick(RecyclerView.ViewHolder holder, int position) {
+ onObItemClick(position);
+ }
+
+ public void onObItemClick(int position) {
MediaBean mediaBean = mMediaBeanList.get(position);
if (mediaBean.getId() == Integer.MIN_VALUE) {
@@ -343,17 +484,20 @@ public void onItemClick(RecyclerView.ViewHolder holder, int position) {
return;
}
- openCamera();
-
+ openCamera(mMediaActivity);
} else {
if (mConfiguration.isRadio()) {
- radioNext(mediaBean);
+ if (mConfiguration.isImage()) {
+ radioNext(mediaBean);
+ } else {
+ videoRadioNext(mediaBean);
+ }
} else {
MediaBean firstBean = mMediaBeanList.get(0);
ArrayList gridMediaList = new ArrayList<>();
gridMediaList.addAll(mMediaBeanList);
int pos = position;
- if(firstBean.getId() == Integer.MIN_VALUE) {
+ if (firstBean.getId() == Integer.MIN_VALUE) {
pos = position - 1;
gridMediaList.clear();
List list = mMediaBeanList.subList(1, mMediaBeanList.size());
@@ -364,37 +508,163 @@ public void onItemClick(RecyclerView.ViewHolder holder, int position) {
}
}
+ /**
+ * 处理 Video 选择 是否预览
+ *
+ * @param mediaBean
+ */
+ private void videoRadioNext(MediaBean mediaBean) {
+ if (!mConfiguration.isVideoPreview()) {
+ setPostMediaBean(mediaBean);
+ getActivity().finish();
+ return;
+ }
+ try {
+ Intent openVideo = new Intent(Intent.ACTION_VIEW);
+ openVideo.setDataAndType(Uri.parse(mediaBean.getOriginalPath()), "video/*");
+ startActivity(openVideo);
+ } catch (Exception e) {
+ Toast.makeText(getContext(), "启动播放器失败", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ /**
+ * 处理回调
+ */
+ private void setPostMediaBean(MediaBean mediaBean) {
+ ImageCropBean bean = new ImageCropBean();
+ bean.copyMediaBean(mediaBean);
+ RxBus.getDefault().post(new ImageRadioResultEvent(bean));
+ }
+
+ /**
+ * 区分功能
+ */
private void radioNext(MediaBean mediaBean) {
- if(!mConfiguration.isCrop()){
- ImageCropBean bean = new ImageCropBean();
- bean.copyMediaBean(mediaBean);
- RxBus.getDefault().post(new ImageRadioResultEvent(bean));
+ Logger.i("isCrop :" + mConfiguration.isCrop());
+ if (!mConfiguration.isCrop()) {
+ setPostMediaBean(mediaBean);
getActivity().finish();
} else {
+ //裁剪根据大家需求加上选择完图片后的回调
+ setPostMediaBean(mediaBean);
String originalPath = mediaBean.getOriginalPath();
File file = new File(originalPath);
- Uri outUri = Uri.fromFile(new File(mImageStoreCropDir, file.getName()));
+ Random random = new Random();
+ String outName = String.format(IMAGE_STORE_FILE_NAME, SimpleDateUtils.getNowTime() + "_" + random.nextInt(1024));
+ Logger.i("--->isCrop:" + mImageStoreCropDir);
+ Logger.i("--->mediaBean.getOriginalPath():" + mediaBean.getOriginalPath());
+ mCropPath = new File(mImageStoreCropDir, outName);
+ Uri outUri = Uri.fromFile(mCropPath);
+ if (!mImageStoreCropDir.exists()) {
+ mImageStoreCropDir.mkdirs();
+ }
+ if (!file.exists()) {
+ file.mkdirs();
+ }
+ Uri inputUri = Uri.fromFile(new File(mediaBean.getOriginalPath()));
Intent intent = new Intent(getContext(), UCropActivity.class);
+
+ FileProvider7.grantPermissions(getActivity(),intent,outUri,true);
+
+ // UCrop 参数 start
Bundle bundle = new Bundle();
- bundle.putParcelable(UCropActivity.EXTRA_OUTPUT_URI, outUri);
- bundle.putParcelable(UCropActivity.EXTRA_INPUT_BEAN, mediaBean);
- bundle.putParcelable(UCropActivity.EXTRA_CONFIGURATION, mConfiguration);
+
+ bundle.putParcelable(UCrop.EXTRA_OUTPUT_URI, outUri);
+ bundle.putParcelable(UCrop.Options.EXTRA_ASPECT_RATIO_OPTIONS, mediaBean);
+ bundle.putInt(UCrop.Options.EXTRA_STATUS_BAR_COLOR, uCropStatusColor);
+ bundle.putInt(UCrop.Options.EXTRA_TOOL_BAR_COLOR, uCropToolbarColor);
+ bundle.putString(UCrop.Options.EXTRA_UCROP_TITLE_TEXT_TOOLBAR, uCropTitle);
+ bundle.putInt(UCrop.Options.EXTRA_UCROP_COLOR_CONTROLS_WIDGET_ACTIVE, uCropActivityWidgetColor);
+ bundle.putInt(UCrop.Options.EXTRA_UCROP_WIDGET_COLOR_TOOLBAR, uCropToolbarWidgetColor);
+ bundle.putBoolean(UCrop.Options.EXTRA_HIDE_BOTTOM_CONTROLS, mConfiguration.isHideBottomControls());
+ bundle.putIntArray(UCrop.Options.EXTRA_ALLOWED_GESTURES, mConfiguration.getAllowedGestures());
+ bundle.putInt(UCrop.Options.EXTRA_COMPRESSION_QUALITY, mConfiguration.getCompressionQuality());
+ bundle.putInt(UCrop.Options.EXTRA_MAX_BITMAP_SIZE, mConfiguration.getMaxBitmapSize());
+ bundle.putFloat(UCrop.Options.EXTRA_MAX_SCALE_MULTIPLIER, mConfiguration.getMaxScaleMultiplier());
+ bundle.putFloat(UCrop.EXTRA_ASPECT_RATIO_X, mConfiguration.getAspectRatioX());
+ bundle.putFloat(UCrop.EXTRA_ASPECT_RATIO_Y, mConfiguration.getAspectRatioY());
+ bundle.putInt(UCrop.EXTRA_MAX_SIZE_X, mConfiguration.getMaxResultWidth());
+ bundle.putInt(UCrop.EXTRA_MAX_SIZE_Y, mConfiguration.getMaxResultHeight());
+ bundle.putInt(UCrop.Options.EXTRA_ASPECT_RATIO_SELECTED_BY_DEFAULT, mConfiguration.getSelectedByDefault());
+ bundle.putBoolean(UCrop.Options.EXTRA_FREE_STYLE_CROP, mConfiguration.isFreestyleCropEnabled());
+ bundle.putParcelable(UCrop.EXTRA_INPUT_URI, inputUri);
+ // UCrop 参数 end
+
+ int bk = FileUtils.existImageDir(inputUri.getPath());
+ Logger.i("--->" + inputUri.getPath());
+ //Logger.i("--->" + outUri.getPath());
+ ArrayList aspectRatioList = new ArrayList<>();
+ AspectRatio[] aspectRatios = mConfiguration.getAspectRatio();
+ if (aspectRatios != null) {
+ for (int i = 0; i < aspectRatios.length; i++) {
+ aspectRatioList.add(i, aspectRatios[i]);
+ Logger.i("自定义比例=>" + aspectRatioList.get(i).getAspectRatioX() + " " + aspectRatioList.get(i).getAspectRatioY());
+ }
+ }
+ // AspectRatio[]aspectRatios = mConfiguration.getAspectRatio();
+ bundle.putParcelableArrayList(UCrop.Options.EXTRA_ASPECT_RATIO_OPTIONS, aspectRatioList);//EXTRA_CONFIGURATION
intent.putExtras(bundle);
- startActivity(intent);
+ if (bk != -1) {
+ //裁剪
+ startActivityForResult(intent, CROP_IMAGE_REQUEST_CODE);
+ } else {
+ Logger.w("点击图片无效");
+ }
}
}
- private void openCamera() {
- Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- if (captureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
- String filename = String.format(IMAGE_STORE_FILE_NAME, dateFormat.format(new Date()));
- mImagePath = new File(mImageStoreDir, filename).getAbsolutePath();
- captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mImagePath)));
- startActivityForResult(captureIntent, TAKE_IMAGE_REQUEST_CODE);
- } else {
- Toast.makeText(getContext(), R.string.gallery_device_camera_unable, Toast.LENGTH_SHORT).show();
- }
+ public void openCamera(Context context) {
+ FragmentActivity activity = this.getActivity();
+ PermissionCheckUtils.checkCameraPermission(mMediaActivity, requestStorageAccessPermissionTips, MediaActivity.REQUEST_CAMERA_ACCESS_PERMISSION,new OnPermissionCallback() {
+
+ @Override
+ public void onGranted(List permissions, boolean all) {
+
+ boolean image = mConfiguration.isImage();
+
+ Intent captureIntent = image ? new Intent(MediaStore.ACTION_IMAGE_CAPTURE) : new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+ if (captureIntent.resolveActivity(context.getPackageManager()) == null) {
+ Toast.makeText(getContext(), R.string.gallery_device_camera_unable, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if(mConfiguration.isMultipleShot() && image){
+ captureIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+ }
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
+ String filename = String.format(image ? IMAGE_STORE_FILE_NAME : VIDEO_STORE_FILE_NAME, dateFormat.format(new Date()));
+ Logger.i("openCamera:" + mImageStoreDir.getAbsolutePath());
+ File fileImagePath = new File(mImageStoreDir, filename);
+ mImagePath = fileImagePath.getAbsolutePath();
+
+ Uri pictureUri = null;
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ //""中的内容是随意的,但最好用package名.provider名的形式,清晰明了
+ pictureUri = FileProvider7.getUriForFile(activity, fileImagePath);
+ } else {
+ pictureUri = Uri.fromFile(fileImagePath);
+ }
+
+ captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
+ // video : 1: 高质量 0 低质量
+ if(!image){
+ captureIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, mConfiguration.getVideoQuality());
+ }
+ //这一句非常重要
+ captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ startActivityForResult(captureIntent, TAKE_IMAGE_REQUEST_CODE);
+ }
+
+ @Override
+ public void onDenied(List permissions, boolean never) {
+
+ }
+ });
+
}
@Override
@@ -403,9 +673,47 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
Logger.i("onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode);
if (requestCode == TAKE_IMAGE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
Logger.i(String.format("拍照成功,图片存储路径:%s", mImagePath));
+ mMediaScanner.scanFile(mImagePath, mConfiguration.isImage() ? IMAGE_TYPE : "", this);
+ }else if (requestCode == TAKE_IMAGE_REQUEST_CODE && resultCode == Activity.RESULT_CANCELED) {
+ if(mConfiguration.isReturnAfterShot()){
+ getActivity().finish();
+ }
+ } else if (requestCode == 222) {
+ Toast.makeText(getActivity(), "摄像成功", Toast.LENGTH_SHORT).show();
+ } else if (requestCode == CROP_IMAGE_REQUEST_CODE && data != null) {
+ Logger.i("裁剪成功");
+ onCropFinished();
+ }
+ //重新加载图片
+ mPage = 1;
+ currShowType = mConfiguration.isImage();
+ mMediaGridPresenter.getMediaList(mBucketId, mPage, LIMIT,currShowType);
+ }
- //刷新相册数据库
- mMediaScanner.scanFile(mImagePath, "image/jpeg", this);
+ /**
+ * 裁剪之后
+ * setResult(RESULT_OK, new Intent()
+ * .putExtra(UCrop.EXTRA_OUTPUT_URI, uri)
+ * .putExtra(UCrop.EXTRA_OUTPUT_CROP_ASPECT_RATIO, resultAspectRatio)
+ * .putExtra(UCrop.EXTRA_OUTPUT_IMAGE_WIDTH, imageWidth)
+ * .putExtra(UCrop.EXTRA_OUTPUT_IMAGE_HEIGHT, imageHeight)
+ */
+ private void onCropFinished() {
+ if (iListenerRadio != null && mCropPath != null) {
+ if (mConfiguration.isCrop()) {
+ iListenerRadio.cropAfter(mCropPath);
+ }
+ } else {
+ Logger.i("# CropPath is null!# ");
+ }
+ //裁剪默认会关掉这个界面. 实现接口返回true则不关闭.
+ if (iListenerRadio == null) {
+ getActivity().finish();
+ } else {
+ boolean flag = iListenerRadio.isActivityFinish();
+ Logger.i("# crop image is flag # :" + flag);
+ if (flag)
+ getActivity().finish();
}
}
@@ -415,7 +723,7 @@ public void onSaveInstanceState(Bundle outState) {
if (!TextUtils.isEmpty(mImagePath)) {
outState.putString(TAKE_URL_STORAGE_KEY, mImagePath);
}
- if(!TextUtils.isEmpty(mBucketId)) {
+ if (!TextUtils.isEmpty(mBucketId)) {
outState.putString(BUCKET_ID_KEY, mBucketId);
}
}
@@ -425,6 +733,9 @@ protected void onRestoreState(Bundle savedInstanceState) {
}
+
+ //****************************************************************************
+
@Override
protected void onSaveState(Bundle outState) {
@@ -449,73 +760,139 @@ public void onDestroy() {
@Override
public void onClick(View v) {
int id = v.getId();
- if(id == R.id.tv_preview) {
+ if (id == R.id.tv_preview) {
RxBus.getDefault().post(new OpenMediaPreviewFragmentEvent());
- } else if(id == R.id.tv_folder_name) {
+ } else if (id == R.id.tv_folder_name) {
v.setEnabled(false);
- int visibility = mRlBucektOverview.getVisibility();
- if(visibility == View.VISIBLE) {
- new SlideOutUnderneathAnimation(mRvBucket)
- .setDirection(Animation.DIRECTION_DOWN)
- .setDuration(Animation.DURATION_DEFAULT)
- .setListener(animation -> {
- v.setEnabled(true);
- mRlBucektOverview.setVisibility(View.GONE);
- })
- .animate();
- } else {
- mRlBucektOverview.setVisibility(View.VISIBLE);
- new SlideInUnderneathAnimation(mRvBucket)
- .setDirection(Animation.DIRECTION_DOWN)
- .setDuration(Animation.DURATION_DEFAULT)
- .setListener(animation -> {
- v.setEnabled(true);
- })
- .animate();
+ if (isShowRvBucketView()) {
+ hideRvBucketView();
+ } else {
+ showRvBucketView();
}
}
}
+ public boolean isShowRvBucketView() {
+ return mRlBucektOverview != null && mRlBucektOverview.getVisibility() == View.VISIBLE;
+ }
+
+
+ public void showRvBucketView() {
+ if (mRlBucektOverview == null) {
+ slideInUnderneathAnimation = new SlideInUnderneathAnimation(mRlBucektOverview);
+ }
+ mRlBucektOverview.setVisibility(View.VISIBLE);
+ slideInUnderneathAnimation
+ .setDirection(Animation.DIRECTION_DOWN)
+ .setDuration(Animation.DURATION_DEFAULT)
+ .setListener(animation -> mTvFolderName.setEnabled(true))
+ .animate();
+ }
+
+ public void hideRvBucketView() {
+ if (slideOutUnderneathAnimation == null) {
+ slideOutUnderneathAnimation = new SlideOutUnderneathAnimation(mRvBucket);
+ }
+ slideOutUnderneathAnimation
+ .setDirection(Animation.DIRECTION_DOWN)
+ .setDuration(Animation.DURATION_DEFAULT)
+ .setListener(animation -> {
+ mTvFolderName.setEnabled(true);
+ mRlBucektOverview.setVisibility(View.GONE);
+ })
+ .animate();
+ }
+
@Override
public void onScanCompleted(String[] images) {
- if(images == null || images.length == 0){
+ if (images == null || images.length == 0) {
Logger.i("images empty");
return;
}
- Observable.create((Observable.OnSubscribe) subscriber -> {
- MediaBean mediaBean = MediaUtils.getMediaBeanWithImage(getContext(), images[0]);
+ // mediaBean 有可能为Null,onNext 做了处理,在 getMediaBeanWithImage 时候就不处理Null了
+ Observable.create((ObservableOnSubscribe) subscriber -> {
+ MediaBean mediaBean =
+ mConfiguration.isImage() ? MediaUtils.getMediaBeanWithImage(getContext(), images[0])
+ :
+ MediaUtils.getMediaBeanWithVideo(getContext(), images[0]);
subscriber.onNext(mediaBean);
- subscriber.onCompleted();
+ subscriber.onComplete();
})
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
- @Override
- public void onCompleted() {
- }
-
- @Override
- public void onError(Throwable e) {
- Logger.i("获取MediaBean异常");
- }
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new DisposableObserver() {
+ @Override
+ public void onComplete() {
+ }
- @Override
- public void onNext(MediaBean mediaBean) {
+ @Override
+ public void onError(Throwable e) {
+ Logger.i("获取MediaBean异常" + e.toString());
+ }
- if(!isDetached() && mediaBean != null) {
- mMediaBeanList.add(1, mediaBean);
- mMediaGridAdapter.notifyDataSetChanged();
- }
+ @Override
+ public void onNext(MediaBean mediaBean) {
+ if (!isDetached() && mediaBean != null) {
+ int bk = FileUtils.existImageDir(mediaBean.getOriginalPath());
+ if (bk != -1) {
+ if(mConfiguration.isReturnAfterShot()){
+ if (mConfiguration.isImage()) {
+ radioNext(mediaBean);
+ } else {
+ videoRadioNext(mediaBean);
+ }
+ }else{
+ mMediaBeanList.add(1, mediaBean);
+ checkMediaBean(mediaBean);
+ mMediaGridAdapter.notifyDataSetChanged();
+ }
+
+ } else {
+ Logger.i("获取:无");
+ }
+ }
- }
- });
+ }
+ });
}
@Override
public void onDestroyView() {
super.onDestroyView();
- RxBus.getDefault().remove(mSubscrMediaCheckChangeEvent);
- RxBus.getDefault().remove(mSubscrCloseMediaViewPageFragmentEvent);
+ RxBus.getDefault().remove(mMediaCheckChangeDisposable);
+ RxBus.getDefault().remove(mCloseMediaViewPageFragmentDisposable);
+
+ }
+
+ /**
+ * onAttach 转 onStart
+ */
+ public void onLoadFile() {
+ //没有的话就默认路径
+ if (mImageStoreDir == null) {
+ mImageStoreDir = new File(Environment.getExternalStorageDirectory(), rootPath);
+ }
+ if (!mImageStoreDir.exists()) {
+ mImageStoreDir.mkdirs();
+ }
+ if (mImageStoreCropDir== null) {
+ mImageStoreCropDir = new File(mImageStoreDir, "crop");
+ if (!mImageStoreCropDir.exists()) {
+ mImageStoreCropDir.mkdirs();
+ }
+ }
+ }
+
+ public void checkMediaBean(MediaBean mediaBean){
+ if(!mConfiguration.isRadio() && mMediaActivity.getCheckedList().size() list){
+ for (MediaBean mediaBean:list){
+ checkMediaBean(mediaBean);
+ }
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPageFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPageFragment.java
index bf2e5388..7cb6418d 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPageFragment.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPageFragment.java
@@ -3,10 +3,11 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.view.ViewPager;
-import android.support.v4.widget.CompoundButtonCompat;
-import android.support.v7.widget.AppCompatCheckBox;
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+import androidx.viewpager.widget.ViewPager;
+import androidx.core.widget.CompoundButtonCompat;
+import androidx.appcompat.widget.AppCompatCheckBox;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.RelativeLayout;
@@ -31,14 +32,14 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/14 下午10:02
*/
public class MediaPageFragment extends BaseFragment implements ViewPager.OnPageChangeListener,
- View.OnClickListener{
+ View.OnClickListener {
private static final String EXTRA_MEDIA_LIST = EXTRA_PREFIX + ".MediaList";
- private static final String EXTRA_ITEM_CLICK_POSITION = EXTRA_PREFIX +".ItemClickPosition";
+ private static final String EXTRA_ITEM_CLICK_POSITION = EXTRA_PREFIX + ".ItemClickPosition";
DisplayMetrics mScreenSize;
@@ -51,15 +52,7 @@ public class MediaPageFragment extends BaseFragment implements ViewPager.OnPageC
private MediaActivity mMediaActivity;
private int mItemClickPosition;
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- if(context instanceof MediaActivity) {
- mMediaActivity = (MediaActivity) context;
- }
- }
-
- public static MediaPageFragment newInstance(Configuration configuration, ArrayList list, int position){
+ public static MediaPageFragment newInstance(Configuration configuration, ArrayList list, int position) {
MediaPageFragment fragment = new MediaPageFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_CONFIGURATION, configuration);
@@ -69,6 +62,14 @@ public static MediaPageFragment newInstance(Configuration configuration, ArrayLi
return fragment;
}
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (context instanceof MediaActivity) {
+ mMediaActivity = (MediaActivity) context;
+ }
+ }
+
@Override
public int getContentView() {
return R.layout.gallery_fragment_media_page;
@@ -82,16 +83,18 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) {
mScreenSize = DeviceUtils.getScreenSize(getContext());
mMediaBeanList = new ArrayList<>();
- if(savedInstanceState != null){
+ if (savedInstanceState != null) {
List mediaList = savedInstanceState.getParcelableArrayList(EXTRA_MEDIA_LIST);
mItemClickPosition = savedInstanceState.getInt(EXTRA_ITEM_CLICK_POSITION);
- if(mediaList != null) {
+ if (mediaList != null) {
mMediaBeanList.addAll(mediaList);
}
}
- mMediaPreviewAdapter = new MediaPreviewAdapter(getContext(), mMediaBeanList,
- mScreenSize.widthPixels, mScreenSize.heightPixels, mConfiguration);
+ mMediaPreviewAdapter = new MediaPreviewAdapter(mMediaBeanList,
+ mScreenSize.widthPixels, mScreenSize.heightPixels, mConfiguration
+ , ThemeUtils.resolveColor(getActivity(), R.attr.gallery_page_bg, R.color.gallery_default_page_bg),
+ ContextCompat.getDrawable(getActivity(), ThemeUtils.resolveDrawableRes(getActivity(), R.attr.gallery_default_image, R.drawable.gallery_default_image)));
mViewPager.setAdapter(mMediaPreviewAdapter);
mCbCheck.setOnClickListener(this);
mViewPager.setCurrentItem(mItemClickPosition);
@@ -102,13 +105,13 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) {
@Override
public void onStart() {
super.onStart();
- if(mConfiguration == null || mMediaBeanList.size() == 0
+ if (mConfiguration == null || mMediaBeanList.size() == 0
|| mCbCheck == null || mViewPager == null) {
return;
}
MediaBean mediaBean = mMediaBeanList.get(mItemClickPosition);
- if(mMediaActivity != null && mMediaActivity.getCheckedList() != null){
- if(mMediaActivity.getCheckedList().contains(mediaBean)) {
+ if (mMediaActivity != null && mMediaActivity.getCheckedList() != null) {
+ if (mMediaActivity.getCheckedList().contains(mediaBean)) {
mCbCheck.setChecked(true);
}
}
@@ -133,19 +136,15 @@ protected void onFirstTimeLaunched() {
@Override
protected void onRestoreState(Bundle savedInstanceState) {
- if(savedInstanceState==null){
+ if (savedInstanceState == null) {
return;
}
-
List mediaList = savedInstanceState.getParcelableArrayList(EXTRA_MEDIA_LIST);
mItemClickPosition = savedInstanceState.getInt(EXTRA_ITEM_CLICK_POSITION);
-
- if(mediaList != null) {
+ if (mediaList != null) {
mMediaBeanList.clear();
- Logger.i("恢复数据:" + mediaList.size() +" d=" + mediaList.get(0).getOriginalPath());
+ Logger.i("恢复数据:" + mediaList.size() + " d=" + mediaList.get(0).getOriginalPath());
mMediaBeanList.addAll(mediaList);
- } else{
- Logger.i("恢复数据: null");
}
mViewPager.setCurrentItem(mItemClickPosition);
mMediaPreviewAdapter.notifyDataSetChanged();
@@ -153,7 +152,7 @@ protected void onRestoreState(Bundle savedInstanceState) {
@Override
protected void onSaveState(Bundle outState) {
- if(outState==null){
+ if (outState == null) {
return;
}
outState.putParcelableArrayList(EXTRA_MEDIA_LIST, mMediaBeanList);
@@ -170,7 +169,7 @@ public void onPageSelected(int position) {
MediaBean mediaBean = mMediaBeanList.get(position);
//判断是否选择
- if(mMediaActivity != null && mMediaActivity.getCheckedList() != null){
+ if (mMediaActivity != null && mMediaActivity.getCheckedList() != null) {
mCbCheck.setChecked(mMediaActivity.getCheckedList().contains(mediaBean));
} else {
mCbCheck.setChecked(false);
@@ -185,17 +184,16 @@ public void onPageScrollStateChanged(int state) {
/**
* 改变选择
- * @param view
*/
@Override
public void onClick(View view) {
- if(mMediaBeanList.size() == 0){
+ if (mMediaBeanList.size() == 0) {
return;
}
int position = mViewPager.getCurrentItem();
MediaBean mediaBean = mMediaBeanList.get(position);
- if(mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size()
+ if (mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size()
&& !mMediaActivity.getCheckedList().contains(mediaBean)) {
Toast.makeText(getContext(), getResources()
.getString(R.string.gallery_image_max_size_tip, mConfiguration.getMaxSize()), Toast.LENGTH_SHORT).show();
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPreviewFragment.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPreviewFragment.java
index 3af5a4a8..53db2916 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPreviewFragment.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/fragment/MediaPreviewFragment.java
@@ -3,10 +3,11 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.view.ViewPager;
-import android.support.v4.widget.CompoundButtonCompat;
-import android.support.v7.widget.AppCompatCheckBox;
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+import androidx.viewpager.widget.ViewPager;
+import androidx.core.widget.CompoundButtonCompat;
+import androidx.appcompat.widget.AppCompatCheckBox;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.RelativeLayout;
@@ -29,11 +30,11 @@
/**
* Desction:图片预览
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/6/9 上午1:35
*/
public class MediaPreviewFragment extends BaseFragment implements ViewPager.OnPageChangeListener,
- View.OnClickListener{
+ View.OnClickListener {
private static final String EXTRA_PAGE_INDEX = EXTRA_PREFIX + ".PageIndex";
@@ -41,22 +42,13 @@ public class MediaPreviewFragment extends BaseFragment implements ViewPager.OnPa
private AppCompatCheckBox mCbCheck;
private ViewPager mViewPager;
- private MediaPreviewAdapter mMediaPreviewAdapter;
private List mMediaBeanList;
private RelativeLayout mRlRootView;
private MediaActivity mMediaActivity;
private int mPagerPosition;
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- if(context instanceof MediaActivity) {
- mMediaActivity = (MediaActivity) context;
- }
- }
-
- public static MediaPreviewFragment newInstance(Configuration configuration, int position){
+ public static MediaPreviewFragment newInstance(Configuration configuration, int position) {
MediaPreviewFragment fragment = new MediaPreviewFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_CONFIGURATION, configuration);
@@ -65,6 +57,14 @@ public static MediaPreviewFragment newInstance(Configuration configuration, int
return fragment;
}
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (context instanceof MediaActivity) {
+ mMediaActivity = (MediaActivity) context;
+ }
+ }
+
@Override
public int getContentView() {
return R.layout.gallery_fragment_media_preview;
@@ -78,15 +78,17 @@ public void onViewCreatedOk(View view, @Nullable Bundle savedInstanceState) {
mRlRootView = (RelativeLayout) view.findViewById(R.id.rl_root_view);
mScreenSize = DeviceUtils.getScreenSize(getContext());
mMediaBeanList = new ArrayList<>();
- if(mMediaActivity.getCheckedList() != null){
+ if (mMediaActivity.getCheckedList() != null) {
mMediaBeanList.addAll(mMediaActivity.getCheckedList());
}
- mMediaPreviewAdapter = new MediaPreviewAdapter(getContext(), mMediaBeanList,
- mScreenSize.widthPixels, mScreenSize.heightPixels, mConfiguration);
+ MediaPreviewAdapter mMediaPreviewAdapter = new MediaPreviewAdapter(mMediaBeanList,
+ mScreenSize.widthPixels, mScreenSize.heightPixels, mConfiguration,
+ ThemeUtils.resolveColor(getActivity(), R.attr.gallery_page_bg, R.color.gallery_default_page_bg),
+ ContextCompat.getDrawable(getActivity(), ThemeUtils.resolveDrawableRes(getActivity(), R.attr.gallery_default_image, R.drawable.gallery_default_image)));
mViewPager.setAdapter(mMediaPreviewAdapter);
mCbCheck.setOnClickListener(this);
- if(savedInstanceState != null) {
+ if (savedInstanceState != null) {
mPagerPosition = savedInstanceState.getInt(EXTRA_PAGE_INDEX);
}
}
@@ -96,6 +98,8 @@ public void onStart() {
super.onStart();
mViewPager.setCurrentItem(mPagerPosition, false);
mViewPager.addOnPageChangeListener(this);
+ //#ADD UI预览数量的BUG
+ RxBus.getDefault().post(new MediaViewPagerChangedEvent(mPagerPosition, mMediaBeanList.size(), true));
}
@Override
@@ -117,14 +121,14 @@ protected void onFirstTimeLaunched() {
@Override
protected void onRestoreState(Bundle savedInstanceState) {
- if(savedInstanceState != null){
+ if (savedInstanceState != null) {
mPagerPosition = savedInstanceState.getInt(EXTRA_PAGE_INDEX);
}
}
@Override
protected void onSaveState(Bundle outState) {
- if(outState != null){
+ if (outState != null) {
outState.putInt(EXTRA_PAGE_INDEX, mPagerPosition);
}
}
@@ -139,7 +143,7 @@ public void onPageSelected(int position) {
MediaBean mediaBean = mMediaBeanList.get(position);
mCbCheck.setChecked(false);
//判断是否选择
- if(mMediaActivity != null && mMediaActivity.getCheckedList() != null){
+ if (mMediaActivity != null && mMediaActivity.getCheckedList() != null) {
mCbCheck.setChecked(mMediaActivity.getCheckedList().contains(mediaBean));
}
@@ -152,13 +156,12 @@ public void onPageScrollStateChanged(int state) {
/**
* 改变选择
- * @param view
*/
@Override
public void onClick(View view) {
int position = mViewPager.getCurrentItem();
MediaBean mediaBean = mMediaBeanList.get(position);
- if(mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size()
+ if (mConfiguration.getMaxSize() == mMediaActivity.getCheckedList().size()
&& !mMediaActivity.getCheckedList().contains(mediaBean)) {
Toast.makeText(getContext(), getResources()
.getString(R.string.gallery_image_max_size_tip, mConfiguration.getMaxSize()), Toast.LENGTH_SHORT).show();
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixImageView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixImageView.java
index 3baf38ac..9dfd5a8e 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixImageView.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixImageView.java
@@ -3,13 +3,14 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
-import android.support.v7.widget.AppCompatImageView;
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Desction:为了兼容fresco框架而自定义的ImageView
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:2015/12/24 0024 20:14
*/
public class FixImageView extends AppCompatImageView {
@@ -32,18 +33,10 @@ public void setOnImageViewListener(OnImageViewListener listener) {
mOnImageViewListener = listener;
}
- public static interface OnImageViewListener {
- void onDetach();
- void onAttach();
- boolean verifyDrawable(Drawable dr) ;
- void onDraw(Canvas canvas);
- boolean onTouchEvent(MotionEvent event);
- }
-
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if(mOnImageViewListener != null) {
+ if (mOnImageViewListener != null) {
mOnImageViewListener.onDetach();
}
}
@@ -51,14 +44,14 @@ protected void onDetachedFromWindow() {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- if(mOnImageViewListener != null) {
+ if (mOnImageViewListener != null) {
mOnImageViewListener.onAttach();
}
}
@Override
- protected boolean verifyDrawable(Drawable dr) {
- if(mOnImageViewListener != null) {
+ protected boolean verifyDrawable(@NonNull Drawable dr) {
+ if (mOnImageViewListener != null) {
if (mOnImageViewListener.verifyDrawable(dr)) {
return true;
}
@@ -69,7 +62,7 @@ protected boolean verifyDrawable(Drawable dr) {
@Override
public void onStartTemporaryDetach() {
super.onStartTemporaryDetach();
- if(mOnImageViewListener != null) {
+ if (mOnImageViewListener != null) {
mOnImageViewListener.onDetach();
}
}
@@ -77,7 +70,7 @@ public void onStartTemporaryDetach() {
@Override
public void onFinishTemporaryDetach() {
super.onFinishTemporaryDetach();
- if(mOnImageViewListener != null) {
+ if (mOnImageViewListener != null) {
mOnImageViewListener.onAttach();
}
}
@@ -85,7 +78,7 @@ public void onFinishTemporaryDetach() {
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
- if(mOnImageViewListener != null) {
+ if (mOnImageViewListener != null) {
mOnImageViewListener.onDraw(canvas);
}
@@ -93,10 +86,22 @@ protected void onDraw(Canvas canvas) {
@Override
public boolean onTouchEvent(MotionEvent event) {
- if(mOnImageViewListener == null){
+ if (mOnImageViewListener == null) {
return super.onTouchEvent(event);
}
return mOnImageViewListener.onTouchEvent(event) || super.onTouchEvent(event);
}
+ public interface OnImageViewListener {
+ void onDetach();
+
+ void onAttach();
+
+ boolean verifyDrawable(Drawable dr);
+
+ void onDraw(Canvas canvas);
+
+ boolean onTouchEvent(MotionEvent event);
+ }
+
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixViewPager.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixViewPager.java
index f8e59897..087f9286 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixViewPager.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FixViewPager.java
@@ -1,16 +1,16 @@
package cn.finalteam.rxgalleryfinal.ui.widget;
import android.content.Context;
-import android.support.v4.view.ViewPager;
+import androidx.viewpager.widget.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:2015/12/29 0029 19:29
*/
-public class FixViewPager extends ViewPager{
+public class FixViewPager extends ViewPager {
public FixViewPager(Context context) {
super(context);
}
@@ -22,11 +22,9 @@ public FixViewPager(Context context, AttributeSet attrs) {
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
try {
- return super .dispatchTouchEvent(ev);
+ return super.dispatchTouchEvent(ev);
} catch (IllegalArgumentException ignored) {
- } catch (ArrayIndexOutOfBoundsException e) {
}
-
- return false ;
+ return false;
}
}
\ No newline at end of file
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FlexibleDividerDecoration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FlexibleDividerDecoration.java
index ef92909e..77d125dd 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FlexibleDividerDecoration.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FlexibleDividerDecoration.java
@@ -7,17 +7,17 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.support.annotation.ColorRes;
-import android.support.annotation.DimenRes;
-import android.support.annotation.DrawableRes;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.ColorRes;
+import androidx.annotation.DimenRes;
+import androidx.annotation.DrawableRes;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
/**
- * Created by yqritc on 2015/01/08.
+ * by yqritc on 2015/01/08.
*/
public abstract class FlexibleDividerDecoration extends RecyclerView.ItemDecoration {
@@ -25,22 +25,17 @@ public abstract class FlexibleDividerDecoration extends RecyclerView.ItemDecorat
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
-
- protected enum DividerType {
- DRAWABLE, PAINT, COLOR
- }
-
- protected DividerType mDividerType = DividerType.DRAWABLE;
- protected VisibilityProvider mVisibilityProvider;
- protected PaintProvider mPaintProvider;
- protected ColorProvider mColorProvider;
- protected DrawableProvider mDrawableProvider;
- protected SizeProvider mSizeProvider;
- protected boolean mShowLastDivider;
- protected boolean mPositionInsideItem;
+ final boolean mPositionInsideItem;
+ private final VisibilityProvider mVisibilityProvider;
+ private final boolean mShowLastDivider;
+ DividerType mDividerType = DividerType.DRAWABLE;
+ PaintProvider mPaintProvider;
+ DrawableProvider mDrawableProvider;
+ SizeProvider mSizeProvider;
+ private ColorProvider mColorProvider;
private Paint mPaint;
- protected FlexibleDividerDecoration(Builder builder) {
+ FlexibleDividerDecoration(Builder builder) {
if (builder.mPaintProvider != null) {
mDividerType = DividerType.PAINT;
mPaintProvider = builder.mPaintProvider;
@@ -55,12 +50,7 @@ protected FlexibleDividerDecoration(Builder builder) {
TypedArray a = builder.mContext.obtainStyledAttributes(ATTRS);
final Drawable divider = a.getDrawable(0);
a.recycle();
- mDrawableProvider = new DrawableProvider() {
- @Override
- public Drawable drawableProvider(int position, RecyclerView parent) {
- return divider;
- }
- };
+ mDrawableProvider = (position, parent) -> divider;
} else {
mDrawableProvider = builder.mDrawableProvider;
}
@@ -75,12 +65,7 @@ public Drawable drawableProvider(int position, RecyclerView parent) {
private void setSizeProvider(Builder builder) {
mSizeProvider = builder.mSizeProvider;
if (mSizeProvider == null) {
- mSizeProvider = new SizeProvider() {
- @Override
- public int dividerSize(int position, RecyclerView parent) {
- return DEFAULT_SIZE;
- }
- };
+ mSizeProvider = (position, parent) -> DEFAULT_SIZE;
}
}
@@ -164,13 +149,9 @@ public void getItemOffsets(Rect rect, View v, RecyclerView parent, RecyclerView.
* @param parent RecyclerView
* @return true if recyclerview is reverse layout
*/
- protected boolean isReverseLayout(RecyclerView parent) {
+ boolean isReverseLayout(RecyclerView parent) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
- if (layoutManager instanceof LinearLayoutManager) {
- return ((LinearLayoutManager) layoutManager).getReverseLayout();
- } else {
- return false;
- }
+ return layoutManager instanceof LinearLayoutManager && ((LinearLayoutManager) layoutManager).getReverseLayout();
}
/**
@@ -242,6 +223,10 @@ private int getGroupIndex(int position, RecyclerView parent) {
protected abstract void setItemOffsets(Rect outRect, int position, RecyclerView parent);
+ protected enum DividerType {
+ DRAWABLE, PAINT, COLOR
+ }
+
/**
* Interface for controlling divider visibility
*/
@@ -263,7 +248,7 @@ public interface VisibilityProvider {
public interface PaintProvider {
/**
- * Returns {@link android.graphics.Paint} for divider
+ * Returns {@link Paint} for divider
*
* @param position Divider position (or group index for GridLayoutManager)
* @param parent RecyclerView
@@ -320,18 +305,13 @@ public interface SizeProvider {
public static class Builder {
- private Context mContext;
- protected Resources mResources;
+ final Resources mResources;
+ private final Context mContext;
private PaintProvider mPaintProvider;
private ColorProvider mColorProvider;
private DrawableProvider mDrawableProvider;
private SizeProvider mSizeProvider;
- private VisibilityProvider mVisibilityProvider = new VisibilityProvider() {
- @Override
- public boolean shouldHideDivider(int position, RecyclerView parent) {
- return false;
- }
- };
+ private VisibilityProvider mVisibilityProvider = (position, parent) -> false;
private boolean mShowLastDivider = false;
private boolean mPositionInsideItem = false;
@@ -341,12 +321,7 @@ public Builder(Context context) {
}
public T paint(final Paint paint) {
- return paintProvider(new PaintProvider() {
- @Override
- public Paint dividerPaint(int position, RecyclerView parent) {
- return paint;
- }
- });
+ return paintProvider((position, parent) -> paint);
}
public T paintProvider(PaintProvider provider) {
@@ -355,12 +330,7 @@ public T paintProvider(PaintProvider provider) {
}
public T color(final int color) {
- return colorProvider(new ColorProvider() {
- @Override
- public int dividerColor(int position, RecyclerView parent) {
- return color;
- }
- });
+ return colorProvider((position, parent) -> color);
}
public T colorResId(@ColorRes int colorId) {
@@ -377,12 +347,7 @@ public T drawable(@DrawableRes int id) {
}
public T drawable(final Drawable drawable) {
- return drawableProvider(new DrawableProvider() {
- @Override
- public Drawable drawableProvider(int position, RecyclerView parent) {
- return drawable;
- }
- });
+ return drawableProvider((position, parent) -> drawable);
}
public T drawableProvider(DrawableProvider provider) {
@@ -391,12 +356,7 @@ public T drawableProvider(DrawableProvider provider) {
}
public T size(final int size) {
- return sizeProvider(new SizeProvider() {
- @Override
- public int dividerSize(int position, RecyclerView parent) {
- return size;
- }
- });
+ return sizeProvider((position, parent) -> size);
}
public T sizeResId(@DimenRes int sizeId) {
@@ -423,7 +383,7 @@ public T positionInsideItem(boolean positionInsideItem) {
return (T) this;
}
- protected void checkBuilderParams() {
+ void checkBuilderParams() {
if (mPaintProvider != null) {
if (mColorProvider != null) {
throw new IllegalArgumentException(
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FooterAdapter.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FooterAdapter.java
index 1b532a0b..6cd1646a 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FooterAdapter.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/FooterAdapter.java
@@ -1,32 +1,38 @@
package cn.finalteam.rxgalleryfinal.ui.widget;
-import android.support.v7.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
/**
* Desction:footer适配器
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/21 下午3:59
*/
public class FooterAdapter extends RecyclerView.Adapter {
private static final int ITEM_VIEW_TYPE_FOOTER = 0;
private static final int ITEM_VIEW_TYPE_ITEM = 1;
- private RecyclerView.Adapter mAdapter;
- private View mFooterView;
+ private final RecyclerView.Adapter mAdapter;
+ private final View mFooterView;
private OnItemClickListener mOnItemClickListener;
public FooterAdapter(RecyclerView.Adapter adapter, View footerView) {
this.mAdapter = adapter;
- this.mAdapter.registerAdapterDataObserver(mDataObserver);
+ this.mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ notifyDataSetChanged();
+ }
+ });
this.mFooterView = footerView;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- if(viewType == ITEM_VIEW_TYPE_FOOTER) {
+ if (viewType == ITEM_VIEW_TYPE_FOOTER) {
return new FooterViewHolder(mFooterView);
}
return mAdapter.onCreateViewHolder(parent, viewType);
@@ -34,9 +40,8 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
- if(isFooter(position)) {
- } else {
- if(mOnItemClickListener != null) {
+ if (!isFooter(position)) {
+ if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(v -> mOnItemClickListener.onItemClick(holder, position));
}
mAdapter.onBindViewHolder(holder, position);
@@ -45,16 +50,11 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
/**
* 设置Item点击事件
- * @param listener
*/
public void setOnItemClickListener(OnItemClickListener listener) {
this.mOnItemClickListener = listener;
}
- public interface OnItemClickListener{
- void onItemClick(RecyclerView.ViewHolder holder, int position);
- }
-
@Override
public int getItemCount() {
return mAdapter.getItemCount() + 1;
@@ -62,26 +62,22 @@ public int getItemCount() {
@Override
public int getItemViewType(int position) {
- return isFooter(position)?ITEM_VIEW_TYPE_FOOTER:ITEM_VIEW_TYPE_ITEM;
+ return isFooter(position) ? ITEM_VIEW_TYPE_FOOTER : ITEM_VIEW_TYPE_ITEM;
}
public boolean isFooter(int position) {
return position == getItemCount() - 1;
}
- class FooterViewHolder extends RecyclerView.ViewHolder{
+ public interface OnItemClickListener {
+ void onItemClick(RecyclerView.ViewHolder holder, int position);
+ }
+
+ class FooterViewHolder extends RecyclerView.ViewHolder {
public FooterViewHolder(View itemView) {
super(itemView);
}
}
- private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {
- @Override
- public void onChanged() {
- super.onChanged();
- notifyDataSetChanged();
- }
- };
-
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/HorizontalDividerItemDecoration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/HorizontalDividerItemDecoration.java
index 3bcab36b..b7afd57e 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/HorizontalDividerItemDecoration.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/HorizontalDividerItemDecoration.java
@@ -3,19 +3,19 @@
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.support.annotation.DimenRes;
-import android.support.v4.view.ViewCompat;
-import android.support.v7.widget.RecyclerView;
+import androidx.annotation.DimenRes;
+import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
/**
- * Created by yqritc on 2015/01/15.
+ * by yqritc on 2015/01/15.
*/
public class HorizontalDividerItemDecoration extends FlexibleDividerDecoration {
- private MarginProvider mMarginProvider;
+ private final MarginProvider mMarginProvider;
- protected HorizontalDividerItemDecoration(Builder builder) {
+ private HorizontalDividerItemDecoration(Builder builder) {
super(builder);
mMarginProvider = builder.mMarginProvider;
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/MarginDecoration.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/MarginDecoration.java
index e3ab94ea..18469963 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/MarginDecoration.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/MarginDecoration.java
@@ -2,13 +2,13 @@
import android.content.Context;
import android.graphics.Rect;
-import android.support.v7.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import cn.finalteam.rxgalleryfinal.R;
public class MarginDecoration extends RecyclerView.ItemDecoration {
- private int margin;
+ private final int margin;
public MarginDecoration(Context context) {
margin = context.getResources().getDimensionPixelSize(R.dimen.gallery_grid_item_margin);
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerImageView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerImageView.java
deleted file mode 100644
index 8dd7771b..00000000
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerImageView.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package cn.finalteam.rxgalleryfinal.ui.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-/**
- * Desction:
- * Author:pengjianbo
- * Date:16/6/3 下午8:10
- */
-public class RecyclerImageView extends SquareImageView {
-
- public RecyclerImageView(Context context) {
- super(context);
- }
-
- public RecyclerImageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public RecyclerImageView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
-// @Override
-// protected void onDetachedFromWindow() {
-// super.onDetachedFromWindow();
-// setImageDrawable(null);
-// }
-
-}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerViewFinal.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerViewFinal.java
index 1fb848fc..3c738568 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerViewFinal.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/RecyclerViewFinal.java
@@ -1,16 +1,16 @@
package cn.finalteam.rxgalleryfinal.ui.widget;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.os.SystemClock;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.StaggeredGridLayoutManager;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.widget.Adapter;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -19,52 +19,69 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/3/7 下午6:40
*/
public class RecyclerViewFinal extends RecyclerView {
/**
- * 加载更多lock
+ * 是否可以加载跟多
*/
- private boolean mLoadMoreLock;
+ private boolean mHasLoadMore;
/**
- * 是否可以加载跟多
+ * 加载更多lock
*/
- boolean mHasLoadMore;
-
+ private boolean mLoadMoreLock;
/**
* 加载更多事件回调
*/
private OnLoadMoreListener mOnLoadMoreListener;
-
/**
* emptyview
*/
private View mEmptyView;
+ /**
+ * 刷新数据时停止滑动,避免出现数组下标越界问题
+ */
+ private final AdapterDataObserver mDataObserver = new AdapterDataObserver() {
+ @Override
+ public void onChanged() {
+ Adapter> adapter = getAdapter();
+ if (adapter != null && mEmptyView != null) {
+ if (adapter.getItemCount() == 0) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ setVisibility(View.GONE);
+ } else {
+ mEmptyView.setVisibility(View.GONE);
+ setVisibility(View.VISIBLE);
+ }
+ }
+ dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0));
+ }
+ };
private FooterAdapter mFooterViewAdapter;
-
private TextView mTvMessage;
private ProgressBar mPbLoading;
private View mFooterView;
public RecyclerViewFinal(Context context) {
super(context);
- init(context, null);
+ init(context);
}
public RecyclerViewFinal(Context context, AttributeSet attrs) {
super(context, attrs);
- init(context, attrs);
+ init(context);
}
public RecyclerViewFinal(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- init(context, attrs);
+ init(context);
}
- private void init(Context context, AttributeSet attrs) {
+ @SuppressLint("InflateParams")
+ private void init(Context context) {
mFooterView = LayoutInflater.from(context).inflate(R.layout.gallery_loading_view_final_footer_default, null);
mPbLoading = (ProgressBar) mFooterView.findViewById(R.id.pb_loading);
mTvMessage = (TextView) mFooterView.findViewById(R.id.tv_loading_msg);
@@ -73,18 +90,17 @@ private void init(Context context, AttributeSet attrs) {
addOnScrollListener(new RecyclerViewOnScrollListener());
}
- Adapter adapter;
@Override
public void setAdapter(Adapter adapter) {
- this.adapter = adapter;
try {
adapter.unregisterAdapterDataObserver(mDataObserver);
- } catch (Exception e){}
+ } catch (Exception ignored) {
+ }
adapter.registerAdapterDataObserver(mDataObserver);
mFooterViewAdapter = new FooterAdapter(adapter, mFooterView);
- if(getLayoutManager() != null) {
+ if (getLayoutManager() != null) {
GridLayoutManager manager = (GridLayoutManager) getLayoutManager();
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
@@ -99,7 +115,6 @@ public int getSpanSize(int position) {
/**
* 设置recyclerview emptyview
- * @param emptyView
*/
public void setEmptyView(View emptyView) {
this.mEmptyView = emptyView;
@@ -108,7 +123,7 @@ public void setEmptyView(View emptyView) {
/**
* 没有很多了
*/
- void showNoMoreUI() {
+ private void showNoMoreUI() {
mLoadMoreLock = false;
mPbLoading.setVisibility(View.GONE);
mTvMessage.setText(R.string.gallery_loading_view_no_more);
@@ -117,7 +132,7 @@ void showNoMoreUI() {
/**
* 显示默认UI
*/
- void showNormalUI() {
+ private void showNormalUI() {
mLoadMoreLock = false;
mPbLoading.setVisibility(View.GONE);
mTvMessage.setText(R.string.gallery_loading_view_click_loading_more);
@@ -126,14 +141,13 @@ void showNormalUI() {
/**
* 显示加载中UI
*/
- void showLoadingUI(){
+ private void showLoadingUI() {
mPbLoading.setVisibility(View.VISIBLE);
mTvMessage.setText(R.string.gallery_loading_view_loading);
}
/**
* 是否有更多
- * @param hasLoadMore
*/
public void setHasLoadMore(boolean hasLoadMore) {
mHasLoadMore = hasLoadMore;
@@ -146,7 +160,6 @@ public void setHasLoadMore(boolean hasLoadMore) {
/**
* 设置加载更多事件回调
- * @param loadMoreListener
*/
public void setOnLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.mOnLoadMoreListener = loadMoreListener;
@@ -164,8 +177,8 @@ public void onLoadMoreComplete() {
/**
* 加载更多
*/
- void executeLoadMore() {
- if(!mLoadMoreLock && mHasLoadMore) {
+ private void executeLoadMore() {
+ if (!mLoadMoreLock && mHasLoadMore) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.loadMore();
}
@@ -175,7 +188,7 @@ void executeLoadMore() {
}
public void setFooterViewHide(boolean footerViewHide) {
- if(footerViewHide) {
+ if (footerViewHide) {
mFooterView.setVisibility(View.GONE);
} else {
mFooterView.setVisibility(View.VISIBLE);
@@ -184,12 +197,15 @@ public void setFooterViewHide(boolean footerViewHide) {
/**
* 设置OnItemClickListener
- * @param listener
*/
public void setOnItemClickListener(FooterAdapter.OnItemClickListener listener) {
mFooterViewAdapter.setOnItemClickListener(listener);
}
+ public interface OnLoadMoreListener {
+ void loadMore();
+ }
+
/**
* 滚动到底部自动加载更多数据
*/
@@ -216,10 +232,10 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
LayoutManager layoutManager = recyclerView.getLayoutManager();
- if (layoutManager instanceof LinearLayoutManager) {
- lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
- } else if (layoutManager instanceof GridLayoutManager) {
+ if (layoutManager instanceof GridLayoutManager) {
lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
+ } else if (layoutManager instanceof LinearLayoutManager) {
+ lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
if (lastPositions == null) {
@@ -241,7 +257,7 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
if ((visibleItemCount > 0 && currentScrollState == RecyclerView.SCROLL_STATE_IDLE && (lastVisibleItemPosition) >= totalItemCount - 1)) {
- if(mHasLoadMore) {
+ if (mHasLoadMore) {
executeLoadMore();
}
}
@@ -249,9 +265,6 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
/**
* 取数组中最大值
- *
- * @param lastPositions
- * @return
*/
private int findMax(int[] lastPositions) {
int max = lastPositions[0];
@@ -264,30 +277,4 @@ private int findMax(int[] lastPositions) {
return max;
}
}
-
- public interface OnLoadMoreListener {
- void loadMore();
- }
-
-
- /**
- * 刷新数据时停止滑动,避免出现数组下标越界问题
- */
- private AdapterDataObserver mDataObserver = new AdapterDataObserver() {
- @Override
- public void onChanged() {
- Adapter> adapter = getAdapter();
- if(adapter != null && mEmptyView != null) {
- if(adapter.getItemCount() == 0) {
- mEmptyView.setVisibility(View.VISIBLE);
- setVisibility(View.GONE);
- } else {
- mEmptyView.setVisibility(View.GONE);
- setVisibility(View.VISIBLE);
- }
- }
-
- dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0));
- }
- };
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareImageView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareImageView.java
index 17b57192..6822079a 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareImageView.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareImageView.java
@@ -5,7 +5,7 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/7/9 上午12:53
*/
public class SquareImageView extends FixImageView {
@@ -22,8 +22,8 @@ public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr) {
}
@Override
- protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) {
- super .onMeasure(widthMeasureSpec, heightMeasureSpec);
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareLinearLayout.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareLinearLayout.java
index 9949a7c9..0f1bb0c2 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareLinearLayout.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareLinearLayout.java
@@ -6,7 +6,7 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/6/17 下午1:48
*/
public class SquareLinearLayout extends LinearLayout {
@@ -20,8 +20,8 @@ public SquareLinearLayout(Context context, AttributeSet attrs) {
}
@Override
- protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) {
- super .onMeasure(widthMeasureSpec, heightMeasureSpec);
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareRelativeLayout.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareRelativeLayout.java
index abe75128..bfa53568 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareRelativeLayout.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/ui/widget/SquareRelativeLayout.java
@@ -6,7 +6,7 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/6/8 下午4:07
*/
public class SquareRelativeLayout extends RelativeLayout {
@@ -24,8 +24,8 @@ public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAtt
}
@Override
- protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) {
- super .onMeasure(widthMeasureSpec, heightMeasureSpec);
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/BitmapUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/BitmapUtils.java
index bf127632..4f881d93 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/BitmapUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/BitmapUtils.java
@@ -6,14 +6,14 @@
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
-import android.media.ExifInterface;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.graphics.drawable.DrawableCompat;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.exifinterface.media.ExifInterface;
+import androidx.core.graphics.drawable.DrawableCompat;
import android.text.TextUtils;
import com.yalantis.ucrop.callback.BitmapLoadCallback;
@@ -27,7 +27,7 @@
/**
* Desction:Bitmap处理工具类,图片压缩、裁剪、选择、存储
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/4 下午5:03
*/
public class BitmapUtils {
@@ -45,14 +45,10 @@ public static void createVideoThumbnailSmallPath(String thumbnailSaveDir, String
/**
* 创建视频缩略图
- * @param thumbnailSaveDir
- * @param originalPath
- * @param scale
- * @return
*/
public static void createVideoThumbnail(String thumbnailSaveDir, String originalPath, int scale) {
Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(originalPath, MediaStore.Video.Thumbnails.MINI_KIND);
- if(bitmap == null){
+ if (bitmap == null) {
return;
}
int originalImageWidth = bitmap.getWidth();
@@ -60,7 +56,7 @@ public static void createVideoThumbnail(String thumbnailSaveDir, String original
int maxValue = Math.max(originalImageWidth, originalImageHeight);
BufferedInputStream bufferedInputStream = null;
FileOutputStream fileOutputStream = null;
- File targetFile = null;
+ File targetFile;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
if (maxValue > 3000) {
@@ -68,9 +64,9 @@ public static void createVideoThumbnail(String thumbnailSaveDir, String original
} else if (maxValue > 2000 && maxValue <= 3000) {
options.inSampleSize = scale * 4;
} else if (maxValue > 1500 && maxValue <= 2000) {
- options.inSampleSize = (int)(scale * 2.5);
+ options.inSampleSize = (int) (scale * 2.5);
} else if (maxValue > 1000 && maxValue <= 1500) {
- options.inSampleSize = (int)(scale * 1.3);
+ options.inSampleSize = (int) (scale * 1.3);
// } else if (maxValue > 400 && maxValue <= 1000) {
// options.inSampleSize = scale * 2;
} else {
@@ -96,10 +92,10 @@ public static void createVideoThumbnail(String thumbnailSaveDir, String original
fileOutputStream = new FileOutputStream(targetFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
- } catch (Exception e){
+ } catch (Exception e) {
Logger.e(e);
} finally {
- if(bitmap != null && !bitmap.isRecycled()){
+ if (!bitmap.isRecycled()) {
bitmap.recycle();
}
@@ -111,28 +107,30 @@ public static void createVideoThumbnail(String thumbnailSaveDir, String original
/**
* 创建大缩略图
- * @param targetFile 保存目标文件
+ *
+ * @param targetFile 保存目标文件
* @param originalPath 图片地址
- * */
+ */
public static void createThumbnailBig(File targetFile, String originalPath) {
compressAndSaveImage(targetFile, originalPath, THUMBNAIL_BIG);
}
/**
* 创建小缩略图
- * @param targetFile 保存目标文件
+ *
+ * @param targetFile 保存目标文件
* @param originalPath 图片地址
- * */
+ */
public static void createThumbnailSmall(File targetFile, String originalPath) {
compressAndSaveImage(targetFile, originalPath, THUMBNAIL_SMALL);
}
/**
* 图片压缩并且存储
- * @param targetFile 保存目标文件
+ *
+ * @param targetFile 保存目标文件
* @param originalPath 图片地址
- * @param scale 图片缩放值
- * @return
+ * @param scale 图片缩放值
*/
public static void compressAndSaveImage(File targetFile, String originalPath, int scale) {
@@ -176,9 +174,9 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in
} else if (maxValue > 2000 && maxValue <= 3000) {
options.inSampleSize = scale * 4;
} else if (maxValue > 1500 && maxValue <= 2000) {
- options.inSampleSize = (int)(scale * 2.5);
+ options.inSampleSize = (int) (scale * 2.5);
} else if (maxValue > 1000 && maxValue <= 1500) {
- options.inSampleSize = (int)(scale * 1.3);
+ options.inSampleSize = (int) (scale * 1.3);
// } else if (maxValue > 400 && maxValue <= 1000) {
// options.inSampleSize = scale * 2;
} else {
@@ -191,7 +189,7 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in
bitmap = BitmapFactory.decodeStream(bufferedInputStream, null, options);
bufferedInputStream.close();
- if(bitmap == null){
+ if (bitmap == null) {
return;
}
String extension = FilenameUtils.getExtension(originalPath);
@@ -209,10 +207,10 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in
}
//5、保存图片
- if(TextUtils.equals(extension.toLowerCase(), "jpg")
+ if (TextUtils.equals(extension.toLowerCase(), "jpg")
|| TextUtils.equals(extension.toLowerCase(), "jpeg")) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
- } else if(TextUtils.equals(extension.toLowerCase(), "webp")
+ } else if (TextUtils.equals(extension.toLowerCase(), "webp")
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
bitmap.compress(Bitmap.CompressFormat.WEBP, 100, fileOutputStream);
} else {
@@ -224,7 +222,7 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in
IOUtils.close(bufferedInputStream);
IOUtils.flush(fileOutputStream);
IOUtils.close(fileOutputStream);
- if(bitmap != null && bitmap.isRecycled()){
+ if (bitmap != null && bitmap.isRecycled()) {
bitmap.recycle();
}
}
@@ -232,29 +230,16 @@ public static void compressAndSaveImage(File targetFile, String originalPath, in
/**
* 获取一张图片在手机上的方向值
- * @param uri
- * @return
- * @throws IOException
*/
- public static int getImageOrientation(String uri) {
- if(!new File(uri).exists()){
+ public static int getImageOrientation(String uri) throws IOException {
+ if (!new File(uri).exists()) {
return 0;
}
- try {
- ExifInterface exif = new ExifInterface(uri);
- int orientation = exif.getAttributeInt(
- ExifInterface.TAG_ORIENTATION,
- ExifInterface.ORIENTATION_NORMAL);
- return orientation;
- }catch (Exception e){}
- return 0;
+ return new ExifInterface(uri).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
}
/**
* Drawable着色工具
- * @param drawable
- * @param colors
- * @return
*/
public static Drawable tintDrawable(Drawable drawable, ColorStateList colors) {
final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
@@ -269,12 +254,6 @@ public void decodeBitmapInBackground(@NonNull Context context, @NonNull Uri uri,
/**
* 获取图片Bitmap
- * @param context
- * @param uri
- * @param outputUri
- * @param requiredWidth
- * @param requiredHeight
- * @param loadCallback
*/
public void decodeBitmapInBackground(@NonNull Context context, @NonNull Uri uri, @Nullable Uri outputUri,
int requiredWidth, int requiredHeight, BitmapLoadCallback loadCallback) {
@@ -283,12 +262,6 @@ public void decodeBitmapInBackground(@NonNull Context context, @NonNull Uri uri,
/**
* 图片压缩旋转
- * @param context
- * @param uri
- * @param outputUri
- * @param requiredWidth
- * @param requiredHeight
- * @param loadCallback
*/
public void rotateImage(@NonNull Context context, @NonNull Uri uri, @Nullable Uri outputUri,
int requiredWidth, int requiredHeight, BitmapLoadCallback loadCallback) {
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/CameraUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/CameraUtils.java
index c895d390..b6a06239 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/CameraUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/CameraUtils.java
@@ -5,22 +5,17 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/6/3 下午8:28
*/
public class CameraUtils {
/**
* 判断设备是否有摄像头
- * @param context
- * @return
*/
public static boolean hasCamera(Context context) {
PackageManager packageManager = context.getPackageManager();
- if(!packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)){
- return false;
- }
+ return packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
- return true;
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/DeviceUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/DeviceUtils.java
index 80abbe90..b40989f9 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/DeviceUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/DeviceUtils.java
@@ -6,7 +6,7 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/8/8 下午11:05
*/
public class DeviceUtils {
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/EmptyViewUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/EmptyViewUtils.java
index d6f7bd41..6824e33a 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/EmptyViewUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/EmptyViewUtils.java
@@ -7,13 +7,13 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/14 下午7:26
*/
public class EmptyViewUtils {
public static void showLoading(ViewGroup emptyView) {
- if(emptyView == null) {
+ if (emptyView == null) {
return;
}
ProgressBar pbLoading = (ProgressBar) emptyView.getChildAt(0);
@@ -23,7 +23,7 @@ public static void showLoading(ViewGroup emptyView) {
}
public static void showMessage(ViewGroup emptyView, String msg) {
- if(emptyView == null) {
+ if (emptyView == null) {
return;
}
ProgressBar pbLoading = (ProgressBar) emptyView.getChildAt(0);
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java
index d7bd79b8..ade8ccb8 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FileUtils.java
@@ -1,10 +1,44 @@
package cn.finalteam.rxgalleryfinal.utils;
+import android.app.Activity;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.MediaStore;
+
+import com.zhy.base.fileprovider.FileProvider7;
+
+import java.io.File;
+
/**
* Desction:文件工具类
- * Author:pengjianbo
- * Date:16/5/6 下午5:45
+ * Author:dujinyang
*/
public class FileUtils {
+ /**
+ * 验证是否是图片路径
+ */
+ public static int existImageDir(String dir) {
+ return dir.trim().lastIndexOf(".");
+ }
+
+ public static Uri fromFile(Activity activity, File file) {
+
+ Uri imageUri = null;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ imageUri = Uri.fromFile(file);
+ } else {
+ //兼容android7.0 使用共享文件的形式
+ ContentValues contentValues = new ContentValues(1);
+ contentValues.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
+
+ imageUri = activity.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
+ }
+ return imageUri;
+ }
+
+ public static Uri fromFile7(Activity activity, File file) {
+ return FileProvider7.getUriForFile(activity, file);
+ }
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java
index bee0a139..7b8f963d 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java
@@ -66,12 +66,14 @@ public class FilenameUtils {
/**
* The extension separator character.
+ *
* @since 1.4
*/
public static final char EXTENSION_SEPARATOR = '.';
/**
* The extension separator String.
+ *
* @since 1.4
*/
public static final String EXTENSION_SEPARATOR_STR = Character.toString(EXTENSION_SEPARATOR);
@@ -95,6 +97,7 @@ public class FilenameUtils {
* The separator character that is the opposite of the system separator.
*/
private static final char OTHER_SEPARATOR;
+
static {
if (isSystemWindows()) {
OTHER_SEPARATOR = UNIX_SEPARATOR;
@@ -111,6 +114,7 @@ public FilenameUtils() {
}
//-----------------------------------------------------------------------
+
/**
* Determines if Windows file system is in use.
*
@@ -121,10 +125,11 @@ static boolean isSystemWindows() {
}
//-----------------------------------------------------------------------
+
/**
* Checks if the character is a separator.
*
- * @param ch the character to check
+ * @param ch the character to check
* @return true if it is a separator character
*/
private static boolean isSeparator(char ch) {
@@ -132,6 +137,7 @@ private static boolean isSeparator(char ch) {
}
//-----------------------------------------------------------------------
+
/**
* Normalizes a path, removing double and single dot path steps.
*
@@ -169,12 +175,13 @@ private static boolean isSeparator(char ch) {
*
* (Note the file separator returned will be correct for Windows/Unix)
*
- * @param filename the filename to normalize, null returns null
+ * @param filename the filename to normalize, null returns null
* @return the normalized filename, or null if invalid
*/
public static String normalize(String filename) {
return doNormalize(filename, SYSTEM_SEPARATOR, true);
}
+
/**
* Normalizes a path, removing double and single dot path steps.
*
@@ -213,9 +220,9 @@ public static String normalize(String filename) {
* The output will be the same on both Unix and Windows including
* the separator character.
*
- * @param filename the filename to normalize, null returns null
+ * @param filename the filename to normalize, null returns null
* @param unixSeparator {@code true} if a unix separator should
- * be used or {@code false} if a windows separator should be used.
+ * be used or {@code false} if a windows separator should be used.
* @return the normalized filename, or null if invalid
* @since 2.0
*/
@@ -225,6 +232,7 @@ public static String normalize(String filename, boolean unixSeparator) {
}
//-----------------------------------------------------------------------
+
/**
* Normalizes a path, removing double and single dot path steps,
* and removing any final directory separator.
@@ -263,7 +271,7 @@ public static String normalize(String filename, boolean unixSeparator) {
*
* (Note the file separator returned will be correct for Windows/Unix)
*
- * @param filename the filename to normalize, null returns null
+ * @param filename the filename to normalize, null returns null
* @return the normalized filename, or null if invalid
*/
public static String normalizeNoEndSeparator(String filename) {
@@ -307,9 +315,9 @@ public static String normalizeNoEndSeparator(String filename) {
* ~/../bar --> null
*
*
- * @param filename the filename to normalize, null returns null
+ * @param filename the filename to normalize, null returns null
* @param unixSeparator {@code true} if a unix separator should
- * be used or {@code false} if a windows separtor should be used.
+ * be used or {@code false} if a windows separtor should be used.
* @return the normalized filename, or null if invalid
* @since 2.0
*/
@@ -321,9 +329,9 @@ public static String normalizeNoEndSeparator(String filename, boolean unixSepara
/**
* Internal method to perform the normalization.
*
- * @param filename the filename
- * @param separator The separator character to use
- * @param keepSeparator true to keep the final separator
+ * @param filename the filename
+ * @param separator The separator character to use
+ * @param keepSeparator true to keep the final separator
* @return the normalized filename
*/
private static String doNormalize(String filename, char separator, boolean keepSeparator) {
@@ -374,7 +382,7 @@ private static String doNormalize(String filename, char separator, boolean keepS
lastIsDirectory = true;
}
System.arraycopy(array, i + 1, array, i - 1, size - i);
- size -=2;
+ size -= 2;
i--;
}
}
@@ -391,7 +399,7 @@ private static String doNormalize(String filename, char separator, boolean keepS
lastIsDirectory = true;
}
int j;
- for (j = i - 4 ; j >= prefix; j--) {
+ for (j = i - 4; j >= prefix; j--) {
if (array[j] == separator) {
// remove b/../ from a/b/../c
System.arraycopy(array, i + 1, array, j + 1, size - i);
@@ -420,6 +428,7 @@ private static String doNormalize(String filename, char separator, boolean keepS
}
//-----------------------------------------------------------------------
+
/**
* Concatenates a filename to a base path using normal command line style rules.
*
@@ -456,8 +465,8 @@ private static String doNormalize(String filename, char separator, boolean keepS
* the name will be built into the concatenated path. If this might be a problem,
* use {@link #getFullPath(String)} on the base path argument.
*
- * @param basePath the base path to attach to, always treated as a path
- * @param fullFilenameToAdd the filename (or path) to attach to the base
+ * @param basePath the base path to attach to, always treated as a path
+ * @param fullFilenameToAdd the filename (or path) to attach to the base
* @return the concatenated path, or null if invalid
*/
public static String concat(String basePath, String fullFilenameToAdd) {
@@ -484,10 +493,11 @@ public static String concat(String basePath, String fullFilenameToAdd) {
}
//-----------------------------------------------------------------------
+
/**
* Converts all separators to the Unix separator of forward slash.
*
- * @param path the path to be changed, null ignored
+ * @param path the path to be changed, null ignored
* @return the updated path
*/
public static String separatorsToUnix(String path) {
@@ -500,7 +510,7 @@ public static String separatorsToUnix(String path) {
/**
* Converts all separators to the Windows separator of backslash.
*
- * @param path the path to be changed, null ignored
+ * @param path the path to be changed, null ignored
* @return the updated path
*/
public static String separatorsToWindows(String path) {
@@ -513,7 +523,7 @@ public static String separatorsToWindows(String path) {
/**
* Converts all separators to the system separator.
*
- * @param path the path to be changed, null ignored
+ * @param path the path to be changed, null ignored
* @return the updated path
*/
public static String separatorsToSystem(String path) {
@@ -528,6 +538,7 @@ public static String separatorsToSystem(String path) {
}
//-----------------------------------------------------------------------
+
/**
* Returns the length of the filename prefix, such as C:/
or ~/
.
*
@@ -556,7 +567,7 @@ public static String separatorsToSystem(String path) {
* The output will be the same irrespective of the machine that the code is running on.
* ie. both Unix and Windows prefixes are matched regardless.
*
- * @param filename the filename to find the prefix in, null returns -1
+ * @param filename the filename to find the prefix in, null returns -1
* @return the length of the prefix, -1 if invalid or null
*/
public static int getPrefixLength(String filename) {
@@ -591,7 +602,7 @@ public static int getPrefixLength(String filename) {
if (ch1 == ':') {
ch0 = Character.toUpperCase(ch0);
if (ch0 >= 'A' && ch0 <= 'Z') {
- if (len == 2 || isSeparator(filename.charAt(2)) == false) {
+ if (len == 2 || !isSeparator(filename.charAt(2))) {
return 2;
}
return 3;
@@ -621,7 +632,7 @@ public static int getPrefixLength(String filename) {
*
* The output will be the same irrespective of the machine that the code is running on.
*
- * @param filename the filename to find the last path separator in, null returns -1
+ * @param filename the filename to find the last path separator in, null returns -1
* @return the index of the last separator character, or -1 if there
* is no such character
*/
@@ -643,7 +654,7 @@ public static int indexOfLastSeparator(String filename) {
*
* The output will be the same irrespective of the machine that the code is running on.
*
- * @param filename the filename to find the last path separator in, null returns -1
+ * @param filename the filename to find the last path separator in, null returns -1
* @return the index of the last separator character, or -1 if there
* is no such character
*/
@@ -657,6 +668,7 @@ public static int indexOfExtension(String filename) {
}
//-----------------------------------------------------------------------
+
/**
* Gets the prefix from a full filename, such as C:/
* or ~/
.
@@ -683,7 +695,7 @@ public static int indexOfExtension(String filename) {
* The output will be the same irrespective of the machine that the code is running on.
* ie. both Unix and Windows prefixes are matched regardless.
*
- * @param filename the filename to query, null returns null
+ * @param filename the filename to query, null returns null
* @return the prefix of the file, null if invalid
*/
public static String getPrefix(String filename) {
@@ -719,7 +731,7 @@ public static String getPrefix(String filename) {
* This method drops the prefix from the result.
* See {@link #getFullPath(String)} for the method that retains the prefix.
*
- * @param filename the filename to query, null returns null
+ * @param filename the filename to query, null returns null
* @return the path of the file, an empty string if none exists, null if invalid
*/
public static String getPath(String filename) {
@@ -746,7 +758,7 @@ public static String getPath(String filename) {
* This method drops the prefix from the result.
* See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix.
*
- * @param filename the filename to query, null returns null
+ * @param filename the filename to query, null returns null
* @return the path of the file, an empty string if none exists, null if invalid
*/
public static String getPathNoEndSeparator(String filename) {
@@ -756,8 +768,8 @@ public static String getPathNoEndSeparator(String filename) {
/**
* Does the work of getting the path.
*
- * @param filename the filename
- * @param separatorAdd 0 to omit the end separator, 1 to return it
+ * @param filename the filename
+ * @param separatorAdd 0 to omit the end separator, 1 to return it
* @return the path
*/
private static String doGetPath(String filename, int separatorAdd) {
@@ -769,7 +781,7 @@ private static String doGetPath(String filename, int separatorAdd) {
return null;
}
int index = indexOfLastSeparator(filename);
- int endIndex = index+separatorAdd;
+ int endIndex = index + separatorAdd;
if (prefix >= filename.length() || index < 0 || prefix >= endIndex) {
return "";
}
@@ -798,7 +810,7 @@ private static String doGetPath(String filename, int separatorAdd) {
*
* The output will be the same irrespective of the machine that the code is running on.
*
- * @param filename the filename to query, null returns null
+ * @param filename the filename to query, null returns null
* @return the path of the file, an empty string if none exists, null if invalid
*/
public static String getFullPath(String filename) {
@@ -828,7 +840,7 @@ public static String getFullPath(String filename) {
*
* The output will be the same irrespective of the machine that the code is running on.
*
- * @param filename the filename to query, null returns null
+ * @param filename the filename to query, null returns null
* @return the path of the file, an empty string if none exists, null if invalid
*/
public static String getFullPathNoEndSeparator(String filename) {
@@ -838,8 +850,8 @@ public static String getFullPathNoEndSeparator(String filename) {
/**
* Does the work of getting the path.
*
- * @param filename the filename
- * @param includeSeparator true to include the end separator
+ * @param filename the filename
+ * @param includeSeparator true to include the end separator
* @return the path
*/
private static String doGetFullPath(String filename, boolean includeSeparator) {
@@ -861,7 +873,7 @@ private static String doGetFullPath(String filename, boolean includeSeparator) {
if (index < 0) {
return filename.substring(0, prefix);
}
- int end = index + (includeSeparator ? 1 : 0);
+ int end = index + (includeSeparator ? 1 : 0);
if (end == 0) {
end++;
}
@@ -882,7 +894,7 @@ private static String doGetFullPath(String filename, boolean includeSeparator) {
*
* The output will be the same irrespective of the machine that the code is running on.
*
- * @param filename the filename to query, null returns null
+ * @param filename the filename to query, null returns null
* @return the name of the file without the path, or an empty string if none exists
*/
public static String getName(String filename) {
@@ -924,6 +936,7 @@ public static String getExtension(String filename) {
}
//-----------------------------------------------------------------------
+
/**
* Checks whether the extension of the filename is that specified.
*
@@ -932,7 +945,7 @@ public static String getExtension(String filename) {
* The extension check is case-sensitive on all platforms.
*
* @param filename the filename to query, null returns false
- * @param extension the extension to check for, null or empty checks for no extension
+ * @param extension the extension to check for, null or empty checks for no extension
* @return true if the filename has the specified extension
*/
public static boolean isExtension(String filename, String extension) {
@@ -953,8 +966,8 @@ public static boolean isExtension(String filename, String extension) {
* after the last dot. There must be no directory separator after the dot.
* The extension check is case-sensitive on all platforms.
*
- * @param filename the filename to query, null returns false
- * @param extensions the extensions to check for, null checks for no extension
+ * @param filename the filename to query, null returns false
+ * @param extensions the extensions to check for, null checks for no extension
* @return true if the filename is one of the extensions
*/
public static boolean isExtension(String filename, String[] extensions) {
@@ -980,8 +993,8 @@ public static boolean isExtension(String filename, String[] extensions) {
* after the last dot. There must be no directory separator after the dot.
* The extension check is case-sensitive on all platforms.
*
- * @param filename the filename to query, null returns false
- * @param extensions the extensions to check for, null checks for no extension
+ * @param filename the filename to query, null returns false
+ * @param extensions the extensions to check for, null checks for no extension
* @return true if the filename is one of the extensions
*/
public static boolean isExtension(String filename, Collection extensions) {
@@ -1007,7 +1020,7 @@ public static boolean isExtension(String filename, Collection extensions
* The text is split by '?' and '*'.
* Where multiple '*' occur consecutively they are collapsed into a single '*'.
*
- * @param text the text to split
+ * @param text the text to split
* @return the array of tokens, never null
*/
static String[] splitOnTokens(String text) {
@@ -1015,11 +1028,11 @@ static String[] splitOnTokens(String text) {
// package level so a unit test may run on this
if (text.indexOf('?') == -1 && text.indexOf('*') == -1) {
- return new String[] { text };
+ return new String[]{text};
}
char[] array = text.toCharArray();
- ArrayList list = new ArrayList();
+ ArrayList list = new ArrayList<>();
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < array.length; i++) {
if (array[i] == '?' || array[i] == '*') {
@@ -1030,7 +1043,7 @@ static String[] splitOnTokens(String text) {
if (array[i] == '?') {
list.add("?");
} else if (list.isEmpty() ||
- i > 0 && list.get(list.size() - 1).equals("*") == false) {
+ i > 0 && !list.get(list.size() - 1).equals("*")) {
list.add("*");
}
} else {
@@ -1041,7 +1054,7 @@ static String[] splitOnTokens(String text) {
list.add(buffer.toString());
}
- return list.toArray( new String[ list.size() ] );
+ return list.toArray(new String[list.size()]);
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/IOUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/IOUtils.java
index 2caa925e..f3120d25 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/IOUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/IOUtils.java
@@ -6,13 +6,13 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/7 上午9:45
*/
public class IOUtils {
public static void close(OutputStream stream) {
- if(stream != null) {
+ if (stream != null) {
try {
stream.close();
} catch (IOException e) {
@@ -22,7 +22,7 @@ public static void close(OutputStream stream) {
}
public static void close(InputStream stream) {
- if(stream != null) {
+ if (stream != null) {
try {
stream.close();
} catch (IOException e) {
@@ -32,7 +32,7 @@ public static void close(InputStream stream) {
}
public static void flush(OutputStream stream) {
- if(stream != null) {
+ if (stream != null) {
try {
stream.flush();
} catch (IOException e) {
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/Logger.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/Logger.java
index 36ec2e5b..aeff1bf4 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/Logger.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/Logger.java
@@ -6,40 +6,40 @@
/**
* Desction:日志工具
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/23 下午3:12
*/
public class Logger {
public static final String TAG = "RxGalleryFinal";
- public static final boolean DEBUG = BuildConfig.DEBUG;
-
- public static void d(String value){
- if(DEBUG) {
+ public static boolean DEBUG = BuildConfig.DEBUG;
+
+ public static void d(String value) {
+ if (DEBUG) {
Log.d(TAG, value);
}
}
public static void e(String value) {
- if(DEBUG) {
+ if (DEBUG) {
Log.e(TAG, value);
}
}
public static void e(Exception value) {
- if(DEBUG && value != null) {
+ if (DEBUG && value != null) {
Log.e(TAG, value.getMessage());
}
}
- public static void i(String value){
- if(DEBUG) {
+ public static void i(String value) {
+ if (DEBUG) {
Log.i(TAG, value);
}
}
- public static void w(String value){
- if(DEBUG) {
+ public static void w(String value) {
+ if (DEBUG) {
Log.w(TAG, value);
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaScanner.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaScanner.java
index b56b3ffd..1d66fc0b 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaScanner.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaScanner.java
@@ -6,12 +6,11 @@
/**
* Desction:媒体扫描工具类
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/6/8 上午11:36
*/
public class MediaScanner {
private MediaScannerConnection mediaScanConn = null;
- private MusicSannerClient client = null;
private String fileType = null;
private String[] filePaths = null;
private ScanCallback scanCallback;
@@ -20,40 +19,17 @@ public class MediaScanner {
* 然后调用MediaScanner.scanFile("/sdcard/2.mp3");
*/
public MediaScanner(Context context) {
- if (client == null) {
- client = new MusicSannerClient();
- }
+ MusicSannerClient client;
+ client = new MusicSannerClient();
if (mediaScanConn == null) {
mediaScanConn = new MediaScannerConnection(context, client);
}
}
- class MusicSannerClient implements MediaScannerConnection.MediaScannerConnectionClient {
- @Override
- public void onMediaScannerConnected() {
- Logger.i("onMediaScannerConnected");
- if (filePaths != null) {
- for (String file : filePaths) {
- mediaScanConn.scanFile(file, fileType);
- }
- }
- }
-
- @Override
- public void onScanCompleted(String path, Uri uri) {
- Logger.i("onScanCompleted");
- mediaScanConn.disconnect();
- if(scanCallback != null) {
- scanCallback.onScanCompleted(filePaths);
- }
- fileType = null;
- filePaths = null;
- }
- }
-
/**
* 扫描文件标签信息
+ *
* @param filePath 文件路径
* @param fileType 文件类型
*/
@@ -68,7 +44,7 @@ public void scanFile(String filePath, String fileType, ScanCallback callback) {
/**
* @param filePaths 文件路径
- * @param fileType 文件类型
+ * @param fileType 文件类型
*/
public void scanFile(String[] filePaths, String fileType, ScanCallback callback) {
this.filePaths = filePaths;
@@ -77,11 +53,34 @@ public void scanFile(String[] filePaths, String fileType, ScanCallback callback)
mediaScanConn.connect();
}
- public void unScanFile(){
+ public void unScanFile() {
mediaScanConn.disconnect();
}
- public interface ScanCallback{
+ public interface ScanCallback {
void onScanCompleted(String[] images);
}
+
+ private class MusicSannerClient implements MediaScannerConnection.MediaScannerConnectionClient {
+ @Override
+ public void onMediaScannerConnected() {
+ Logger.i("onMediaScannerConnected");
+ if (filePaths != null) {
+ for (String file : filePaths) {
+ mediaScanConn.scanFile(file, fileType);
+ }
+ }
+ }
+
+ @Override
+ public void onScanCompleted(String path, Uri uri) {
+ Logger.i("onScanCompleted");
+ mediaScanConn.disconnect();
+ if (scanCallback != null) {
+ scanCallback.onScanCompleted(filePaths);
+ }
+ fileType = null;
+ filePaths = null;
+ }
+ }
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaType.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaType.java
index e4afd010..8bc97872 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaType.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaType.java
@@ -4,11 +4,11 @@
/**
* Desction:支持的Media类型
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/5 下午5:03
*/
-public enum MediaType implements Serializable{
- JPG,PNG,WEBP,GIF,MP4;
+public enum MediaType implements Serializable {
+ JPG, PNG, WEBP, GIF, MP4;
public boolean hasVideo() {
return this == MP4;
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java
index 990af20a..3397165d 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java
@@ -3,10 +3,11 @@
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
-import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
+import androidx.annotation.Nullable;
+import androidx.exifinterface.media.ExifInterface;
import android.text.TextUtils;
import java.io.File;
@@ -20,7 +21,7 @@
/**
* Desction:媒体获取工具
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/4 下午4:11
*/
public class MediaUtils {
@@ -28,16 +29,12 @@ public class MediaUtils {
public static List getMediaWithImageList(Context context, int page, int limit) {
return getMediaWithImageList(context, String.valueOf(Integer.MIN_VALUE), page, limit);
}
+
/**
* 从数据库中读取图片
- * @param context
- * @param bucketId
- * @param page
- * @param limit
- * @return
*/
public static List getMediaWithImageList(Context context, String bucketId, int page, int limit) {
- int offset = (page -1) * limit;
+ int offset = (page - 1) * limit;
List mediaBeanList = new ArrayList<>();
ContentResolver contentResolver = context.getContentResolver();
List projection = new ArrayList<>();
@@ -53,34 +50,35 @@ public static List getMediaWithImageList(Context context, String buck
projection.add(MediaStore.Images.Media.LONGITUDE);
projection.add(MediaStore.Images.Media.ORIENTATION);
projection.add(MediaStore.Images.Media.SIZE);
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
projection.add(MediaStore.Images.Media.WIDTH);
projection.add(MediaStore.Images.Media.HEIGHT);
}
String selection = null;
- String []selectionArgs = null;
- if(!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) {
+ String[] selectionArgs = null;
+ if (!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) {
selection = MediaStore.Images.Media.BUCKET_ID + "=?";
selectionArgs = new String[]{bucketId};
}
Cursor cursor = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), selection,
- selectionArgs, MediaStore.Images.Media.DATE_ADDED +" DESC LIMIT " + limit +" OFFSET " + offset);
- if(cursor != null) {
+ selectionArgs, MediaStore.Images.Media.DATE_ADDED + " DESC LIMIT " + limit + " OFFSET " + offset);
+ if (cursor != null) {
int count = cursor.getCount();
- if(count > 0) {
+ if (count > 0) {
cursor.moveToFirst();
do {
MediaBean mediaBean = parseImageCursorAndCreateThumImage(context, cursor);
- mediaBeanList.add(mediaBean);
+ if (mediaBean != null) {
+ mediaBeanList.add(mediaBean);
+ }
} while (cursor.moveToNext());
}
}
- if(cursor != null && !cursor.isClosed()){
+ if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
- cursor = null;
return mediaBeanList;
}
@@ -90,14 +88,9 @@ public static List getMediaWithVideoList(Context context, int page, i
/**
* 从数据库中读取视频
- * @param context
- * @param bucketId
- * @param page
- * @param limit
- * @return
*/
public static List getMediaWithVideoList(Context context, String bucketId, int page, int limit) {
- int offset = (page -1) * limit;
+ int offset = (page - 1) * limit;
List mediaBeanList = new ArrayList<>();
ContentResolver contentResolver = context.getContentResolver();
List projection = new ArrayList<>();
@@ -112,23 +105,23 @@ public static List getMediaWithVideoList(Context context, String buck
projection.add(MediaStore.Video.Media.LATITUDE);
projection.add(MediaStore.Video.Media.LONGITUDE);
projection.add(MediaStore.Video.Media.SIZE);
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
projection.add(MediaStore.Video.Media.WIDTH);
projection.add(MediaStore.Video.Media.HEIGHT);
}
String selection = null;
- String []selectionArgs = null;
- if(!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) {
+ String[] selectionArgs = null;
+ if (!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) {
selection = MediaStore.Video.Media.BUCKET_ID + "=?";
selectionArgs = new String[]{bucketId};
}
Cursor cursor = contentResolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), selection,
- selectionArgs, MediaStore.Video.Media.DATE_ADDED +" DESC LIMIT " + limit +" OFFSET " + offset);
- if(cursor != null) {
+ selectionArgs, MediaStore.Video.Media.DATE_ADDED + " DESC LIMIT " + limit + " OFFSET " + offset);
+ if (cursor != null) {
int count = cursor.getCount();
- if(count > 0) {
+ if (count > 0) {
cursor.moveToFirst();
do {
MediaBean mediaBean = parseVideoCursorAndCreateThumImage(context, cursor);
@@ -137,18 +130,14 @@ public static List getMediaWithVideoList(Context context, String buck
}
}
- if(cursor != null && !cursor.isClosed()){
+ if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
- cursor = null;
return mediaBeanList;
}
/**
* 根据原图获取图片相关信息
- * @param context
- * @param originalPath
- * @return
*/
public static MediaBean getMediaBeanWithImage(Context context, String originalPath) {
ContentResolver contentResolver = context.getContentResolver();
@@ -165,54 +154,98 @@ public static MediaBean getMediaBeanWithImage(Context context, String originalPa
projection.add(MediaStore.Images.Media.LONGITUDE);
projection.add(MediaStore.Images.Media.ORIENTATION);
projection.add(MediaStore.Images.Media.SIZE);
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
projection.add(MediaStore.Images.Media.WIDTH);
projection.add(MediaStore.Images.Media.HEIGHT);
}
Cursor cursor = contentResolver.query(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), MediaStore.Images.Media.DATA +"=?",
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), MediaStore.Images.Media.DATA + "=?",
new String[]{originalPath}, null);
MediaBean mediaBean = null;
- if(cursor != null && cursor.getCount() > 0) {
+ if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
- mediaBean = parseImageCursorAndCreateThumImage(context, cursor);
+ mediaBean = parseImageCursorAndCreateThumImage(context, cursor);
}
- if(cursor != null && !cursor.isClosed()){
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+ return mediaBean;
+ }
+
+ /**
+ * 根据地址获取视频相关信息
+ */
+ public static MediaBean getMediaBeanWithVideo(Context context, String originalPath) {
+ ContentResolver contentResolver = context.getContentResolver();
+ List projection = new ArrayList<>();
+ projection.add(MediaStore.Video.Media._ID);
+ projection.add(MediaStore.Video.Media.TITLE);
+ projection.add(MediaStore.Video.Media.DATA);
+ projection.add(MediaStore.Video.Media.BUCKET_ID);
+ projection.add(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
+ projection.add(MediaStore.Video.Media.MIME_TYPE);
+ projection.add(MediaStore.Video.Media.DATE_ADDED);
+ projection.add(MediaStore.Video.Media.DATE_MODIFIED);
+ projection.add(MediaStore.Video.Media.LATITUDE);
+ projection.add(MediaStore.Video.Media.LONGITUDE);
+ projection.add(MediaStore.Video.Media.SIZE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ projection.add(MediaStore.Video.Media.WIDTH);
+ projection.add(MediaStore.Video.Media.HEIGHT);
+ }
+ Cursor cursor = contentResolver.query(
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+ projection.toArray(new String[projection.size()]),
+ MediaStore.Images.Media.DATA + "=?",
+ new String[]{originalPath}, null);
+ MediaBean mediaBean = null;
+ if (cursor != null && cursor.getCount() > 0) {
+ cursor.moveToFirst();
+ mediaBean = parseVideoCursorAndCreateThumImage(context, cursor);
+ }
+ if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
- cursor = null;
return mediaBean;
}
/**
* 解析图片cursor并且创建缩略图
- * @param context
- * @param cursor
- * @return
+ *
+ * update 17.07.23 log
+ *
+ * 判断图片 Size ,如果小于等于0则返回 Null,避免出现 No such file or directory
*/
+ @Nullable
private static MediaBean parseImageCursorAndCreateThumImage(Context context, Cursor cursor) {
- MediaBean mediaBean = new MediaBean();
+ long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.SIZE));
+ String originalPath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
+ if (TextUtils.isEmpty(originalPath) || size <= 0 || !new File(originalPath).exists()) {
+ return null;
+ }
+
long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID));
- mediaBean.setId(id);
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.TITLE));
+ String bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID));
+ String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
+ String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE));
+ long createDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));
+ long modifiedDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED));
+
+ MediaBean mediaBean = new MediaBean();
+ mediaBean.setId(id);
mediaBean.setTitle(title);
- String originalPath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
mediaBean.setOriginalPath(originalPath);
- String bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID));
mediaBean.setBucketId(bucketId);
- String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
mediaBean.setBucketDisplayName(bucketDisplayName);
- String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE));
mediaBean.setMimeType(mimeType);
- long createDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));
mediaBean.setCreateDate(createDate);
- long modifiedDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED));
mediaBean.setModifiedDate(modifiedDate);
mediaBean.setThumbnailBigPath(createThumbnailBigFileName(context, originalPath).getAbsolutePath());
mediaBean.setThumbnailSmallPath(createThumbnailSmallFileName(context, originalPath).getAbsolutePath());
int width = 0, height = 0;
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
width = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.WIDTH));
height = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT));
} else {
@@ -240,9 +273,6 @@ private static MediaBean parseImageCursorAndCreateThumImage(Context context, Cur
/**
* 解析视频cursor并且创建缩略图
- * @param context
- * @param cursor
- * @return
*/
private static MediaBean parseVideoCursorAndCreateThumImage(Context context, Cursor cursor) {
MediaBean mediaBean = new MediaBean();
@@ -270,7 +300,7 @@ private static MediaBean parseVideoCursorAndCreateThumImage(Context context, Cur
mediaBean.setThumbnailSmallPath(createThumbnailSmallFileName(context, originalPath).getAbsolutePath());
int width = 0, height = 0;
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
width = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.WIDTH));
height = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT));
} else {
@@ -294,20 +324,16 @@ private static MediaBean parseVideoCursorAndCreateThumImage(Context context, Cur
public static File createThumbnailBigFileName(Context context, String originalPath) {
File storeFile = StorageUtils.getCacheDirectory(context);
- File bigThumFile = new File(storeFile, "big_" + FilenameUtils.getName(originalPath));
- return bigThumFile;
+ return new File(storeFile, "big_" + FilenameUtils.getName(originalPath));
}
public static File createThumbnailSmallFileName(Context context, String originalPath) {
File storeFile = StorageUtils.getCacheDirectory(context);
- File smallThumFile = new File(storeFile, "small_" + FilenameUtils.getName(originalPath));
- return smallThumFile;
+ return new File(storeFile, "small_" + FilenameUtils.getName(originalPath));
}
/**
* 获取所有的图片文件夹
- * @param context
- * @return
*/
public static List getAllBucketByImage(Context context) {
return getAllBucket(context, true);
@@ -315,8 +341,6 @@ public static List getAllBucketByImage(Context context) {
/**
* 获取所以视频文件夹
- * @param context
- * @return
*/
public static List getAllBucketByVideo(Context context) {
return getAllBucket(context, false);
@@ -324,23 +348,20 @@ public static List getAllBucketByVideo(Context context) {
/**
* 获取所有的问media文件夹
- * @param context
- * @param isImage
- * @return
*/
public static List getAllBucket(Context context, boolean isImage) {
List bucketBeenList = new ArrayList<>();
ContentResolver contentResolver = context.getContentResolver();
String[] projection;
- if(isImage){
- projection = new String[] {
+ if (isImage) {
+ projection = new String[]{
MediaStore.Images.Media.BUCKET_ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.ORIENTATION,
};
} else {
- projection = new String[] {
+ projection = new String[]{
MediaStore.Video.Media.BUCKET_ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
@@ -349,7 +370,7 @@ public static List getAllBucket(Context context, boolean isImage) {
BucketBean allMediaBucket = new BucketBean();
allMediaBucket.setBucketId(String.valueOf(Integer.MIN_VALUE));
Uri uri;
- if(isImage) {
+ if (isImage) {
allMediaBucket.setBucketName(context.getString(R.string.gallery_all_image));
uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else {
@@ -359,19 +380,19 @@ public static List getAllBucket(Context context, boolean isImage) {
bucketBeenList.add(allMediaBucket);
Cursor cursor = null;
try {
- cursor = contentResolver.query(uri, projection, null, null, MediaStore.Video.Media.DATE_ADDED + " DESC");
- } catch (Exception e){
+ cursor = contentResolver.query(uri, projection, null, null, MediaStore.Video.Media.DATE_ADDED + " DESC");
+ } catch (Exception e) {
Logger.e(e);
}
- if(cursor != null && cursor.getCount() > 0) {
+ if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
do {
BucketBean bucketBean = new BucketBean();
String bucketId;
String bucketKey;
String cover;
- if(isImage) {
+ if (isImage) {
bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID));
bucketBean.setBucketId(bucketId);
String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
@@ -388,33 +409,28 @@ public static List getAllBucket(Context context, boolean isImage) {
bucketKey = MediaStore.Video.Media.BUCKET_ID;
cover = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
}
- if(TextUtils.isEmpty(allMediaBucket.getCover())) {
+ if (TextUtils.isEmpty(allMediaBucket.getCover())) {
allMediaBucket.setCover(cover);
}
- if(bucketBeenList.contains(bucketBean)) {
- bucketBean = null;
- bucketId = null;
- bucketKey = null;
- continue;
+ if (bucketBeenList.contains(bucketBean)) {
+ continue;
}
//获取数量
- Cursor c = contentResolver.query(uri, projection, bucketKey +"=?", new String[]{bucketId}, null);
- if(c != null && c.getCount() > 0) {
+ Cursor c = contentResolver.query(uri, projection, bucketKey + "=?", new String[]{bucketId}, null);
+ if (c != null && c.getCount() > 0) {
bucketBean.setImageCount(c.getCount());
}
bucketBean.setCover(cover);
- if(c != null && !c.isClosed()) {
+ if (c != null && !c.isClosed()) {
c.close();
}
- c = null;
bucketBeenList.add(bucketBean);
} while (cursor.moveToNext());
}
- if(cursor != null && !cursor.isClosed()){
+ if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
- cursor = null;
return bucketBeenList;
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ModelUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ModelUtils.java
new file mode 100644
index 00000000..b4a61c88
--- /dev/null
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ModelUtils.java
@@ -0,0 +1,32 @@
+package cn.finalteam.rxgalleryfinal.utils;
+
+
+import android.util.Log;
+
+import cn.finalteam.rxgalleryfinal.BuildConfig;
+
+/**
+ * 模式
+ * Created by KARL-dujinyang on 2017-03-17 02-24-08.
+ */
+public class ModelUtils {
+ private static final String TAG = "Test";
+
+ public static void logDebug() {
+ Log.w(TAG, "BuildConfig.DEBUG:--" + BuildConfig.DEBUG + "--");
+ if (BuildConfig.DEBUG)
+ Logger.w("is debug mode");
+ else
+ Logger.w("not debug mode");
+ }
+
+ /**
+ * 多层依赖时DEBUGCONFIG会出错,所以提供了内部接口更改
+ *
+ * @param f 是否打开
+ */
+ public static void setDebugModel(boolean f) {
+ Logger.DEBUG = f;
+ }
+
+}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/OsCompat.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/OsCompat.java
index 6e599720..10f5f880 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/OsCompat.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/OsCompat.java
@@ -6,15 +6,16 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/7/20 下午4:23
*/
public class OsCompat {
public static void setBackgroundDrawableCompat(View view, Drawable drawable) {
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setBackground(drawable);
} else {
+ //noinspection deprecation
view.setBackgroundDrawable(drawable);
}
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java
index 355910b9..e225d699 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/PermissionCheckUtils.java
@@ -5,57 +5,102 @@
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AlertDialog;
+import android.widget.Toast;
+
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.appcompat.app.AlertDialog;
+
+import com.hjq.permissions.OnPermissionCallback;
+import com.hjq.permissions.XXPermissions;
+
+import java.util.List;
/**
* Desction:权限检查工具
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
+ * Author:KARL-dujinyang
* Date:16/6/1 下午7:40
*/
public class PermissionCheckUtils {
+ /**
+ * 数组
+ */
+ public static void checkPermission(Activity activity, String permission, OnPermissionCallback callback) {
+
+ XXPermissions.with(activity)
+ // 申请单个权限
+ .permission(permission)
+ // 申请多个权限
+ //.permission(Permission.Group.CALENDAR)
+ // 申请安装包权限
+ //.permission(Permission.REQUEST_INSTALL_PACKAGES)
+ // 申请悬浮窗权限
+ //.permission(Permission.SYSTEM_ALERT_WINDOW)
+ // 申请通知栏权限
+ //.permission(Permission.NOTIFICATION_SERVICE)
+ // 申请系统设置权限
+ //.permission(Permission.WRITE_SETTINGS)
+ // 设置权限请求拦截器
+ //.interceptor(new PermissionInterceptor())
+ // 设置不触发错误检测机制
+ //.unchecked()
+ .request(new OnPermissionCallback() {
+
+ @Override
+ public void onGranted(List permissions, boolean all) {
+ if (all) {
+ //Toast.makeText(activity, "获取权限成功", Toast.LENGTH_SHORT).show();
+ } else {
+ //toast("获取部分权限成功,但部分权限未正常授予");
+ //Toast.makeText(activity, "", Toast.LENGTH_SHORT).show();
+ }
+ callback.onGranted(permissions,all);
+
+ }
+
+ @Override
+ public void onDenied(List permissions, boolean never) {
+ if (never) {
+ //toast("被永久拒绝授权,请手动授予录音和日历权限");
+ // 如果是被永久拒绝就跳转到应用权限系统设置页面
+ XXPermissions.startPermissionActivity(activity, permissions);
+ } else {
+ //toast("获取录音和日历权限失败");
+ callback.onDenied(permissions,never);
+ }
+
+ }
+ });
- public static boolean checkPermission(Activity activity, String permission, String permissionDesc, int requestCode) {
- int currentAPIVersion = Build.VERSION.SDK_INT;
- if (currentAPIVersion >= android.os.Build.VERSION_CODES.M) {
- if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
- if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
- AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity);
- alertBuilder.setCancelable(false);
- alertBuilder.setTitle("授权对话框");
- alertBuilder.setMessage(permissionDesc);
- alertBuilder.setPositiveButton(android.R.string.yes, (dialog, which) -> {
- ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode);
- });
- AlertDialog alert = alertBuilder.create();
- alert.show();
- } else {
- ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode);
- }
- return false;
- } else {
- return true;
- }
- } else {
- return true;
- }
}
/**
* 检查是否对sd卡读取授权
- * @param activity
- * @param permissionDesc
- * @param requestCode
- * @return
*/
@TargetApi(16)
- public static boolean checkReadExternalPermission(Activity activity, String permissionDesc, int requestCode) {
- return checkPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE, permissionDesc, requestCode);
+ public static void checkReadExternalPermission(Activity activity, String permissionDesc, int requestCode, OnPermissionCallback callback) {
+ checkPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE,callback);
}
+ /**
+ * 检查是否对sd卡读取授权
+ */
+ @TargetApi(16)
+ public static void checkWriteExternalPermission(Activity activity, String permissionDesc, int requestCode, OnPermissionCallback callback) {
+ checkPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, callback);
+ }
+
+ /**
+ * 检查是否对相机读取授权
+ */
+ @TargetApi(16)
+ public static void checkCameraPermission(Activity activity, String permissionDesc, int requestCode, OnPermissionCallback callback) {
+ checkPermission(activity, Manifest.permission.CAMERA, callback);
+ }
+
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/SimpleDateUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/SimpleDateUtils.java
new file mode 100644
index 00000000..65492b68
--- /dev/null
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/SimpleDateUtils.java
@@ -0,0 +1,17 @@
+package cn.finalteam.rxgalleryfinal.utils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * 时间工具类
+ * Created by KARL-dujinyang on 2017-04-13.
+ */
+public class SimpleDateUtils {
+
+ public static String getNowTime() {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
+ return dateFormat.format(new Date());
+ }
+}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java
index a2edc90d..da98d73d 100755
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java
@@ -1,5 +1,6 @@
package cn.finalteam.rxgalleryfinal.utils;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
@@ -31,7 +32,7 @@ private StorageUtils() {
* @param context Application context
* @return Cache {@link File directory}.
* NOTE: Can be null in some unpredictable cases (if SD card is unmounted and
- * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
+ * {@link Context#getCacheDir() Context.getCacheDir()} returns null).
*/
public static File getCacheDirectory(Context context) {
return getCacheDirectory(context, true);
@@ -46,7 +47,7 @@ public static File getCacheDirectory(Context context) {
* @param preferExternal Whether prefer external location for cache
* @return Cache {@link File directory}.
* NOTE: Can be null in some unpredictable cases (if SD card is unmounted and
- * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
+ * {@link Context#getCacheDir() Context.getCacheDir()} returns null).
*/
public static File getCacheDirectory(Context context, boolean preferExternal) {
File appCacheDir = null;
@@ -58,7 +59,7 @@ public static File getCacheDirectory(Context context, boolean preferExternal) {
appCacheDir = context.getCacheDir();
}
if (appCacheDir == null) {
- String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
+ @SuppressLint("SdCardPath") String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
Logger.w(String.format("Can't define system cache directory! '%s' will be used.", cacheDirPath));
appCacheDir = new File(cacheDirPath);
}
@@ -71,8 +72,6 @@ public static boolean existSDcard() {
externalStorageState = Environment.getExternalStorageState();
} catch (NullPointerException e) { // (sh)it happens (Issue #660)
externalStorageState = "";
- } catch (IncompatibleClassChangeError e) { // (sh)it happens too (Issue #989)
- externalStorageState = "";
}
return MEDIA_MOUNTED.equals(externalStorageState);
}
@@ -94,7 +93,7 @@ public static File getIndividualCacheDirectory(Context context) {
* created on SD card ("/Android/data/[app_package_name]/cache/uil-images") if card is mounted and app has
* appropriate permission. Else - Android defines cache directory on device's file system.
*
- * @param context Application context
+ * @param context Application context
* @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
* @return Cache {@link File directory}
*/
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ThemeUtils.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ThemeUtils.java
index 4b110364..2dd2d610 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ThemeUtils.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/utils/ThemeUtils.java
@@ -1,20 +1,25 @@
package cn.finalteam.rxgalleryfinal.utils;
-import android.annotation.TargetApi;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
-import android.support.annotation.AttrRes;
-import android.support.annotation.ColorInt;
-import android.support.v4.content.ContextCompat;
+import androidx.annotation.AttrRes;
+import androidx.annotation.ColorInt;
+import androidx.core.content.ContextCompat;
import android.text.TextUtils;
import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/7/14 下午7:10
*/
public class ThemeUtils {
@@ -25,7 +30,7 @@ public static int resolveColor(Context context, @AttrRes int attr) {
public static int resolveColor(Context context, @AttrRes int attr, int fallback) {
TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
int color = 0;
- if(fallback != 0){
+ if (fallback != 0) {
color = ContextCompat.getColor(context, fallback);
}
try {
@@ -42,7 +47,7 @@ public static float resolveDimen(Context context, @AttrRes int attr) {
public static float resolveDimen(Context context, @AttrRes int attr, int fallback) {
TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
float size = 0;
- if(fallback != 0){
+ if (fallback != 0) {
size = context.getResources().getDimension(fallback);
}
try {
@@ -61,7 +66,7 @@ public static String resolveString(Context context, @AttrRes int attr, int fallb
String value;
try {
String s = a.getString(0);
- if(TextUtils.isEmpty(s)){
+ if (TextUtils.isEmpty(s)) {
s = context.getString(fallback);
}
value = s;
@@ -79,7 +84,7 @@ public static boolean resolveBoolean(Context context, @AttrRes int attr) {
public static boolean resolveBoolean(Context context, @AttrRes int attr, int fallback) {
TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
boolean defValue = false;
- if(fallback!=0){
+ if (fallback != 0) {
defValue = context.getResources().getBoolean(fallback);
}
try {
@@ -96,7 +101,7 @@ public static int resolveInteger(Context context, @AttrRes int attr) {
public static int resolveInteger(Context context, @AttrRes int attr, int fallback) {
TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
int defValue = 0;
- if(fallback!=0){
+ if (fallback != 0) {
defValue = context.getResources().getInteger(fallback);
}
try {
@@ -126,12 +131,12 @@ public static Drawable resolveDrawable(Context context, @AttrRes int attr) {
public static Drawable resolveDrawable(Context context, @AttrRes int attr, int fallback) {
TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
Drawable drawable = null;
- if(fallback != 0){
+ if (fallback != 0) {
drawable = ContextCompat.getDrawable(context, fallback).mutate();
}
try {
Drawable d = a.getDrawable(0);
- if(d != null){
+ if (d != null) {
drawable = d;
}
} finally {
@@ -150,12 +155,35 @@ public static float applyDimensionDp(Context context, float value) {
*
* @param color - status-bar color
*/
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void setStatusBarColor(@ColorInt int color, Window window) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- if (window != null) {
+ if (window != null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(color);
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
+ View mChildView = mContentView.getChildAt(0);
+ if (mChildView != null) {
+ mChildView.setFitsSystemWindows(true);
+ }
+ View statusBarView = new View(window.getContext());
+ int statusBarHeight = getStatusBarHeight(window.getContext());
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, statusBarHeight);
+ params.gravity = Gravity.TOP;
+ statusBarView.setLayoutParams(params);
+ statusBarView.setBackgroundColor(color);
+ mContentView.addView(statusBarView);
}
}
}
+
+ private static int getStatusBarHeight(Context context) {
+ int statusBarHeight = 0;
+ Resources res = context.getResources();
+ int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
+ if (resourceId > 0) {
+ statusBarHeight = res.getDimensionPixelSize(resourceId);
+ }
+ return statusBarHeight;
+ }
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/view/ActivityFragmentView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/view/ActivityFragmentView.java
index 016e79e5..5fe7379c 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/view/ActivityFragmentView.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/view/ActivityFragmentView.java
@@ -6,12 +6,14 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/14 下午9:56
*/
public interface ActivityFragmentView {
void showMediaGridFragment();
+
void showMediaPageFragment(ArrayList list, int position);
+
void showMediaPreviewFragment();
}
diff --git a/library/src/main/java/cn/finalteam/rxgalleryfinal/view/MediaGridView.java b/library/src/main/java/cn/finalteam/rxgalleryfinal/view/MediaGridView.java
index c75c61ac..8408e5e3 100644
--- a/library/src/main/java/cn/finalteam/rxgalleryfinal/view/MediaGridView.java
+++ b/library/src/main/java/cn/finalteam/rxgalleryfinal/view/MediaGridView.java
@@ -7,10 +7,11 @@
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/14 上午11:00
*/
public interface MediaGridView {
void onRequestMediaCallback(List list);
+
void onRequestBucketCallback(List list);
}
diff --git a/library/src/main/java/com/yalantis/ucrop/UCropActivity.java b/library/src/main/java/com/yalantis/ucrop/UCropActivity.java
deleted file mode 100755
index ce998ab9..00000000
--- a/library/src/main/java/com/yalantis/ucrop/UCropActivity.java
+++ /dev/null
@@ -1,620 +0,0 @@
-package com.yalantis.ucrop;
-
-import android.graphics.Bitmap;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Animatable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.annotation.IdRes;
-import android.support.annotation.IntDef;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v7.app.ActionBar;
-import android.support.v7.widget.Toolbar;
-import android.text.TextUtils;
-import android.util.TypedValue;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import com.yalantis.ucrop.callback.BitmapCropCallback;
-import com.yalantis.ucrop.model.AspectRatio;
-import com.yalantis.ucrop.util.SelectedStateListDrawable;
-import com.yalantis.ucrop.view.CropImageView;
-import com.yalantis.ucrop.view.GestureCropImageView;
-import com.yalantis.ucrop.view.OverlayView;
-import com.yalantis.ucrop.view.TransformImageView;
-import com.yalantis.ucrop.view.UCropView;
-import com.yalantis.ucrop.view.widget.AspectRatioTextView;
-import com.yalantis.ucrop.view.widget.HorizontalProgressWheelView;
-
-import java.io.File;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-import cn.finalteam.rxgalleryfinal.R;
-import cn.finalteam.rxgalleryfinal.bean.ImageCropBean;
-import cn.finalteam.rxgalleryfinal.bean.MediaBean;
-import cn.finalteam.rxgalleryfinal.rxbus.RxBus;
-import cn.finalteam.rxgalleryfinal.rxbus.event.BaseResultEvent;
-import cn.finalteam.rxgalleryfinal.rxbus.event.CloseRxMediaGridPageEvent;
-import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent;
-import cn.finalteam.rxgalleryfinal.ui.activity.BaseActivity;
-import cn.finalteam.rxgalleryfinal.utils.FilenameUtils;
-import cn.finalteam.rxgalleryfinal.utils.Logger;
-import cn.finalteam.rxgalleryfinal.utils.OsCompat;
-import cn.finalteam.rxgalleryfinal.utils.ThemeUtils;
-
-/**
- * Created by Oleksii Shliama (https://github.com/shliama).//b2b7690
- */
-
-@SuppressWarnings("ConstantConditions")
-public class UCropActivity extends BaseActivity {
-
- public static final String EXTRA_INPUT_BEAN = EXTRA_PREFIX + ".InputBean";
- public static final String EXTRA_OUTPUT_URI = EXTRA_PREFIX + ".OutputUri";
-
- public static final int DEFAULT_COMPRESS_QUALITY = 90;
-
- public static final int NONE = 0;
- public static final int SCALE = 1;
- public static final int ROTATE = 2;
- public static final int ALL = 3;
-
- @IntDef({NONE, SCALE, ROTATE, ALL})
- @Retention(RetentionPolicy.SOURCE)
- public @interface GestureTypes {
- }
-
- private static final int TABS_COUNT = 3;
- private static final int SCALE_WIDGET_SENSITIVITY_COEFFICIENT = 15000;
- private static final int ROTATE_WIDGET_SENSITIVITY_COEFFICIENT = 42;
-
- private int mActiveWidgetColor;
- private int mToolbarWidgetColor;
-
- private boolean mShowBottomControls;
- private boolean mShowLoader = true;
-
- private UCropView mUCropView;
- private GestureCropImageView mGestureCropImageView;
- private OverlayView mOverlayView;
- private ViewGroup mWrapperStateAspectRatio, mWrapperStateRotate, mWrapperStateScale;
- private ViewGroup mLayoutAspectRatio, mLayoutRotate, mLayoutScale;
- private List mCropAspectRatioViews = new ArrayList<>();
- private TextView mTextViewRotateAngle, mTextViewScalePercent;
- private View mBlockingView;
- private Toolbar mToolbar;
- private ImageView mStateScaleImageView;
- private ImageView mStateRotateImageView;
- private ImageView mStateAspectRatioImageView;
- private TextView mTvToolbarTitle;
- private FrameLayout mUcropFrame;
-
- private Bitmap.CompressFormat mCompressFormat = Bitmap.CompressFormat.JPEG;
- private int mCompressQuality = DEFAULT_COMPRESS_QUALITY;
- private int[] mAllowedGestures = new int[]{SCALE, ROTATE, ALL};
- private MediaBean mMediaBean;
- private View mToolbarDivider;
-
- @Override
- public int getContentView() {
- return R.layout.gallery_ucrop_activity_photobox;
- }
-
- @Override
- protected void onCreateOk(@Nullable Bundle savedInstanceState) {
- setupViews();
- setImageData(savedInstanceState);
- setInitialState();
- addBlockingView();
-
- mGestureCropImageView.setTransformImageListener(mImageListener);
- }
-
- @Override
- public void findViews(){
- mToolbar = (Toolbar) findViewById(R.id.toolbar);
- mTvToolbarTitle = (TextView) findViewById(R.id.tv_toolbar_title);
- ViewGroup photoBox = (ViewGroup) findViewById(R.id.ucrop_photobox);
- View.inflate(this, R.layout.gallery_ucrop_controls, photoBox);
- mWrapperStateAspectRatio = (ViewGroup) findViewById(R.id.state_aspect_ratio);
- mWrapperStateAspectRatio.setOnClickListener(mStateClickListener);
- mWrapperStateRotate = (ViewGroup) findViewById(R.id.state_rotate);
- mWrapperStateRotate.setOnClickListener(mStateClickListener);
- mWrapperStateScale = (ViewGroup) findViewById(R.id.state_scale);
- mWrapperStateScale.setOnClickListener(mStateClickListener);
-
- mLayoutAspectRatio = (ViewGroup) findViewById(R.id.layout_aspect_ratio);
- mLayoutRotate = (ViewGroup) findViewById(R.id.layout_rotate_wheel);
- mLayoutScale = (ViewGroup) findViewById(R.id.layout_scale_wheel);
-
- mUCropView = (UCropView) findViewById(R.id.ucrop);
-
- mStateScaleImageView = (ImageView) findViewById(R.id.image_view_state_scale);
- mStateRotateImageView = (ImageView) findViewById(R.id.image_view_state_rotate);
- mStateAspectRatioImageView = (ImageView) findViewById(R.id.image_view_state_aspect_ratio);
-
- mTextViewRotateAngle = ((TextView) findViewById(R.id.text_view_rotate));
-
- mGestureCropImageView = mUCropView.getCropImageView();
- mOverlayView = mUCropView.getOverlayView();
- mUcropFrame = (FrameLayout) findViewById(R.id.ucrop_frame);
- mToolbarDivider = findViewById(R.id.toolbar_divider);
- }
-
- @Override
- protected void setTheme() {
- mActiveWidgetColor = ThemeUtils.resolveColor(this, R.attr.gallery_color_active_widget, R.color.gallery_default_ucrop_color_widget_active);
- mToolbarWidgetColor = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_widget_color, R.color.gallery_default_color_toolbar_icon);
-
- mStateScaleImageView.setImageDrawable(new SelectedStateListDrawable(mStateScaleImageView.getDrawable(), mActiveWidgetColor));
- mStateRotateImageView.setImageDrawable(new SelectedStateListDrawable(mStateRotateImageView.getDrawable(), mActiveWidgetColor));
- mStateAspectRatioImageView.setImageDrawable(new SelectedStateListDrawable(mStateAspectRatioImageView.getDrawable(), mActiveWidgetColor));
-
- int statusBarColor = ThemeUtils.resolveColor(this, R.attr.gallery_color_statusbar, R.color.gallery_default_color_statusbar);
- ThemeUtils.setStatusBarColor(statusBarColor, getWindow());
-
- Drawable closeDrawable = ThemeUtils.resolveDrawable(this, R.attr.gallery_toolbar_close_image, R.drawable.gallery_default_toolbar_close_image);
- int closeColor = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_close_color, R.color.gallery_default_toolbar_widget_color);
- closeDrawable.setColorFilter(closeColor, PorterDuff.Mode.SRC_ATOP);
- mToolbar.setNavigationIcon(closeDrawable);
-
- float titleTextSize = ThemeUtils.resolveDimen(this, R.attr.gallery_toolbar_text_size, R.dimen.gallery_default_toolbar_text_size);
- mTvToolbarTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleTextSize);
- int titleTextColor = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_text_color, R.color.gallery_default_toolbar_text_color);
- mTvToolbarTitle.setTextColor(titleTextColor);
- mTvToolbarTitle.setText(ThemeUtils.resolveString(this, R.attr.gallery_ucrop_title_text, R.string.gallery_ucrop_menu_crop));
- mToolbar.setTitleTextColor(titleTextColor);
-
- int toolbarBg = ThemeUtils.resolveColor(this, R.attr.gallery_toolbar_bg, R.color.gallery_default_color_toolbar_bg);
- mToolbar.setBackgroundColor(toolbarBg);
- int toolbarHeight = (int) ThemeUtils.resolveDimen(this, R.attr.gallery_toolbar_height, R.dimen.gallery_default_toolbar_height);
- mToolbar.setMinimumHeight(toolbarHeight);
-
- int gravity = ThemeUtils.resolveInteger(this, R.attr.gallery_toolbar_text_gravity, R.integer.gallery_default_toolbar_text_gravity);
- mTvToolbarTitle.setLayoutParams(new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.WRAP_CONTENT, gravity));
-
- setSupportActionBar(mToolbar);
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayShowTitleEnabled(false);
- }
-
- mOverlayView.setDimmedColor(ThemeUtils.resolveColor(this, R.attr.gallery_ucrop_image_outer_frame_bg, R.color.gallery_default_ucrop_color_default_dimmed));
- mOverlayView.setCropFrameColor(ThemeUtils.resolveColor(this, R.attr.gallery_ucrop_crop_frame_color, R.color.gallery_default_ucrop_color_default_crop_frame));
- mOverlayView.setCropFrameStrokeWidth((int)ThemeUtils.resolveDimen(this, R.attr.gallery_ucrop_crop_frame_stroke_width, R.dimen.gallery_ucrop_default_crop_frame_stroke_width));
- mOverlayView.setCropGridColor(ThemeUtils.resolveColor(this, R.attr.gallery_ucrop_image_grid_color, R.color.gallery_default_ucrop_color_default_crop_grid));
- mOverlayView.setCropGridStrokeWidth((int)ThemeUtils.resolveDimen(this, R.attr.gallery_ucrop_image_grid_stroke_size, R.dimen.gallery_ucrop_default_crop_grid_stroke_width));
- mUcropFrame.setBackgroundColor(ThemeUtils.resolveColor(this, R.attr.gallery_ucrop_color_crop_background, R.color.gallery_default_ucrop_color_crop_background));
-
- int dividerHeight = (int) ThemeUtils.resolveDimen(this, R.attr.gallery_toolbar_divider_height, R.dimen.gallery_default_toolbar_divider_height);
- int dividerBottomMargin = (int) ThemeUtils.resolveDimen(this, R.attr.gallery_toolbar_bottom_margin, R.dimen.gallery_default_toolbar_bottom_margin);
- LinearLayout.LayoutParams dividerLP = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dividerHeight);
- dividerLP.bottomMargin = dividerBottomMargin;
- mToolbarDivider.setLayoutParams(dividerLP);
-
- Drawable dividerDrawable = ThemeUtils.resolveDrawable(this, R.attr.gallery_toolbar_divider_bg, R.color.gallery_default_toolbar_divider_bg);
- OsCompat.setBackgroundDrawableCompat(mToolbarDivider, dividerDrawable);
- }
-
- @Override
- public boolean onCreateOptionsMenu(final Menu menu) {
- getMenuInflater().inflate(R.menu.gallery_ucrop_menu_activity, menu);
-
- // Change crop & loader menu icons color to match the rest of the UI colors
-
- MenuItem menuItemLoader = menu.findItem(R.id.menu_loader);
- Drawable menuItemLoaderIcon = menuItemLoader.getIcon();
- if (menuItemLoaderIcon != null) {
- try {
- menuItemLoaderIcon.mutate();
- menuItemLoaderIcon.setColorFilter(mToolbarWidgetColor, PorterDuff.Mode.SRC_ATOP);
- menuItemLoader.setIcon(menuItemLoaderIcon);
- } catch (IllegalStateException e) {
- Logger.e(String.format("%s - %s", e.getMessage(), getString(R.string.gallery_ucrop_mutate_exception_hint)));
- }
- ((Animatable) menuItemLoader.getIcon()).start();
- }
-
- MenuItem menuItemCrop = menu.findItem(R.id.menu_crop);
- Drawable menuItemCropIcon = menuItemCrop.getIcon();
- if (menuItemCropIcon != null) {
- menuItemCropIcon.mutate();
- menuItemCropIcon.setColorFilter(mToolbarWidgetColor, PorterDuff.Mode.SRC_ATOP);
- menuItemCrop.setIcon(menuItemCropIcon);
- }
-
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- menu.findItem(R.id.menu_crop).setVisible(!mShowLoader);
- menu.findItem(R.id.menu_loader).setVisible(mShowLoader);
- return super.onPrepareOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == R.id.menu_crop) {
- cropAndSaveImage();
- } else if (item.getItemId() == android.R.id.home) {
- onBackPressed();
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (mGestureCropImageView != null) {
- mGestureCropImageView.cancelAllAnimations();
- }
- }
-
- /**
- * This method extracts all data from the incoming intent and setups views properly.
- */
- private void setImageData(@NonNull Bundle savedInstanceState) {
- mMediaBean = savedInstanceState.getParcelable(EXTRA_INPUT_BEAN);
-
- File file = new File(mMediaBean.getOriginalPath());
- Uri inputUri = Uri.fromFile(file);
- Uri outputUri = savedInstanceState.getParcelable(EXTRA_OUTPUT_URI);
-
- processOptions();
-
- if (inputUri != null && outputUri != null) {
- try {
- mGestureCropImageView.setImageUri(inputUri, outputUri);
- } catch (Exception e) {
- setResultError(e);
- }
- } else {
- setResultError(new NullPointerException(getString(R.string.gallery_ucrop_error_input_data_is_absent)));
- }
- }
-
- @SuppressWarnings("deprecation")
- private void processOptions() {
- // Bitmap compression options
- String ext = FilenameUtils.getExtension(mMediaBean.getOriginalPath());
- mCompressFormat = Bitmap.CompressFormat.JPEG;
- if (ext != null && TextUtils.equals(ext.toLowerCase(), "png")) {
- mCompressFormat = Bitmap.CompressFormat.PNG;
- } else if (ext != null && TextUtils.equals(ext.toLowerCase(), "webp")) {
- mCompressFormat = Bitmap.CompressFormat.WEBP;
- }
-
- mCompressQuality = mConfiguration.getCompressionQuality();
-
- // Gestures options
- int[] allowedGestures = mConfiguration.getAllowedGestures();
- if (allowedGestures != null && allowedGestures.length == TABS_COUNT) {
- mAllowedGestures = allowedGestures;
- }
-
- // Crop image view options
- mGestureCropImageView.setMaxBitmapSize(mConfiguration.getMaxBitmapSize());
- mGestureCropImageView.setMaxScaleMultiplier(mConfiguration.getMaxScaleMultiplier());
- mGestureCropImageView.setImageToWrapCropBoundsAnimDuration(CropImageView.DEFAULT_IMAGE_TO_CROP_BOUNDS_ANIM_DURATION);
-
- // Overlay view options
-// boolean freeStyleCrop = ThemeUtils.resolveBoolean(this, R.attr.gallery_ucrop_free_style_crop, R.bool.gallery_default_ucrop_free_style_crop);
- mOverlayView.setFreestyleCropEnabled(mConfiguration.isFreestyleCropEnabled());
-// boolean ovalDimmedLayer = ThemeUtils.resolveBoolean(this, R.attr.gallery_ucrop_oval_dimmed_layer_enabled, R.bool.gallery_default_ucrop_oval_dimmed_layer_enabled);
-// mOverlayView.setOvalDimmedLayer(ovalDimmedLayer);
- mOverlayView.setOvalDimmedLayer(mConfiguration.isOvalDimmedLayer());
- boolean showCropFrame = ThemeUtils.resolveBoolean(this, R.attr.gallery_ucrop_show_crop_frame, R.bool.gallery_default_ucrop_show_crop_frame);
- mOverlayView.setShowCropFrame(showCropFrame);
- boolean showCropGrid = ThemeUtils.resolveBoolean(this, R.attr.gallery_ucrop_show_crop_grid, R.bool.gallery_default_ucrop_show_crop_grid);
- mOverlayView.setShowCropGrid(showCropGrid);
- int gridRowCount = ThemeUtils.resolveInteger(this, R.attr.gallery_ucrop_grid_column_count, R.integer.gallery_default_ucrop_show_crop_grid_row_count);
- mOverlayView.setCropGridRowCount(gridRowCount);
- int gridColumnCount = ThemeUtils.resolveInteger(this, R.attr.gallery_ucrop_grid_column_count, R.integer.gallery_default_ucrop_show_crop_grid_column_count);
- mOverlayView.setCropGridColumnCount(gridColumnCount);
-
- // Aspect ratio options宽高比
- float aspectRatioX = mConfiguration.getAspectRatioX();
- float aspectRatioY = mConfiguration.getAspectRatioY();
-
- int aspectRationSelectedByDefault = mConfiguration.getSelectedByDefault();
- AspectRatio []aspectRatios = mConfiguration.getAspectRatio();
-
- if (aspectRatioX > 0 && aspectRatioY > 0) {
- if (mWrapperStateAspectRatio != null) {
- mWrapperStateAspectRatio.setVisibility(View.GONE);
- }
- mGestureCropImageView.setTargetAspectRatio(aspectRatioX / aspectRatioY);
- } else if (aspectRatios != null && aspectRationSelectedByDefault < aspectRatios.length) {
- float x = aspectRatios[aspectRationSelectedByDefault].getAspectRatioX();
- float y = aspectRatios[aspectRationSelectedByDefault].getAspectRatioY();
- mGestureCropImageView.setTargetAspectRatio(x /y);
- } else {
- mGestureCropImageView.setTargetAspectRatio(CropImageView.SOURCE_IMAGE_ASPECT_RATIO);
- }
-
- // Result bitmap max size options
- int maxSizeX = mConfiguration.getMaxResultWidth();
- int maxSizeY = mConfiguration.getMaxResultHeight();
- if (maxSizeX > 0 && maxSizeY > 0) {
- mGestureCropImageView.setMaxResultImageSizeX(maxSizeX);
- mGestureCropImageView.setMaxResultImageSizeY(maxSizeY);
- }
- }
-
- private void setupViews() {
- mShowBottomControls = !mConfiguration.isHideBottomControls();
- if (mShowBottomControls) {
- setupAspectRatioWidget();
- setupRotateWidget();
- setupScaleWidget();
- } else {
- findViewById(R.id.wrapper_controls).setVisibility(View.GONE);
- findViewById(R.id.wrapper_states).setVisibility(View.GONE);
- }
- }
-
- private TransformImageView.TransformImageListener mImageListener = new TransformImageView.TransformImageListener() {
- @Override
- public void onRotate(float currentAngle) {
- setAngleText(currentAngle);
- }
-
- @Override
- public void onScale(float currentScale) {
- setScaleText(currentScale);
- }
-
- @Override
- public void onLoadComplete() {
- mUCropView.animate().alpha(1).setDuration(300).setInterpolator(new AccelerateInterpolator());
- mBlockingView.setClickable(false);
- mShowLoader = false;
- supportInvalidateOptionsMenu();
- }
-
- @Override
- public void onLoadFailure(@NonNull Exception e) {
- setResultError(e);
- }
-
- };
-
- private void setupAspectRatioWidget() {
-
- int aspectRationSelectedByDefault = mConfiguration.getSelectedByDefault();
- AspectRatio []aspectRatios = mConfiguration.getAspectRatio();//intent.getParcelableArrayListExtra(UCrop.Options.EXTRA_ASPECT_RATIO_OPTIONS);
-
- if (aspectRatios == null || aspectRatios.length == 0) {
- aspectRationSelectedByDefault = 2;
- aspectRatios = new AspectRatio[]{new AspectRatio(null, 1, 1),
- new AspectRatio(null, 3, 4),
- new AspectRatio(getString(R.string.gallery_ucrop_label_original).toUpperCase(),
- CropImageView.SOURCE_IMAGE_ASPECT_RATIO, CropImageView.SOURCE_IMAGE_ASPECT_RATIO),
- new AspectRatio(null, 3, 2),
- new AspectRatio(null, 16, 9)
- };
- }
-
- LinearLayout wrapperAspectRatioList = (LinearLayout) findViewById(R.id.layout_aspect_ratio);
-
- FrameLayout wrapperAspectRatio;
- AspectRatioTextView aspectRatioTextView;
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
- lp.weight = 1;
- for (AspectRatio aspectRatio : aspectRatios) {
- wrapperAspectRatio = (FrameLayout) getLayoutInflater().inflate(R.layout.gallery_ucrop_aspect_ratio, null);
- wrapperAspectRatio.setLayoutParams(lp);
- aspectRatioTextView = ((AspectRatioTextView) wrapperAspectRatio.getChildAt(0));
- aspectRatioTextView.setActiveColor(mActiveWidgetColor);
- aspectRatioTextView.setAspectRatio(aspectRatio);
-
- wrapperAspectRatioList.addView(wrapperAspectRatio);
- mCropAspectRatioViews.add(wrapperAspectRatio);
- }
-
- mCropAspectRatioViews.get(aspectRationSelectedByDefault).setSelected(true);
-
- for (ViewGroup cropAspectRatioView : mCropAspectRatioViews) {
- cropAspectRatioView.setOnClickListener(v -> {
- mGestureCropImageView.setTargetAspectRatio(
- ((AspectRatioTextView) ((ViewGroup) v).getChildAt(0)).getAspectRatio(v.isSelected()));
- mGestureCropImageView.setImageToWrapCropBounds();
- if (!v.isSelected()) {
- for (ViewGroup cropAspectRatioView1 : mCropAspectRatioViews) {
- cropAspectRatioView1.setSelected(cropAspectRatioView1 == v);
- }
- }
- });
- }
- }
-
- private void setupRotateWidget() {
-
- ((HorizontalProgressWheelView) findViewById(R.id.rotate_scroll_wheel))
- .setScrollingListener(new HorizontalProgressWheelView.ScrollingListener() {
- @Override
- public void onScroll(float delta, float totalDistance) {
- mGestureCropImageView.postRotate(delta / ROTATE_WIDGET_SENSITIVITY_COEFFICIENT);
- }
-
- @Override
- public void onScrollEnd() {
- mGestureCropImageView.setImageToWrapCropBounds();
- }
-
- @Override
- public void onScrollStart() {
- mGestureCropImageView.cancelAllAnimations();
- }
- });
-
- ((HorizontalProgressWheelView) findViewById(R.id.rotate_scroll_wheel)).setMiddleLineColor(mActiveWidgetColor);
-
-
- findViewById(R.id.wrapper_reset_rotate).setOnClickListener(v -> resetRotation());
- findViewById(R.id.wrapper_rotate_by_angle).setOnClickListener(v -> rotateByAngle(90));
- }
-
- private void setupScaleWidget() {
- mTextViewScalePercent = ((TextView) findViewById(R.id.text_view_scale));
- ((HorizontalProgressWheelView) findViewById(R.id.scale_scroll_wheel))
- .setScrollingListener(new HorizontalProgressWheelView.ScrollingListener() {
- @Override
- public void onScroll(float delta, float totalDistance) {
- if (delta > 0) {
- mGestureCropImageView.zoomInImage(mGestureCropImageView.getCurrentScale()
- + delta * ((mGestureCropImageView.getMaxScale() - mGestureCropImageView.getMinScale()) / SCALE_WIDGET_SENSITIVITY_COEFFICIENT));
- } else {
- mGestureCropImageView.zoomOutImage(mGestureCropImageView.getCurrentScale()
- + delta * ((mGestureCropImageView.getMaxScale() - mGestureCropImageView.getMinScale()) / SCALE_WIDGET_SENSITIVITY_COEFFICIENT));
- }
- }
-
- @Override
- public void onScrollEnd() {
- mGestureCropImageView.setImageToWrapCropBounds();
- }
-
- @Override
- public void onScrollStart() {
- mGestureCropImageView.cancelAllAnimations();
- }
- });
- ((HorizontalProgressWheelView) findViewById(R.id.scale_scroll_wheel)).setMiddleLineColor(mActiveWidgetColor);
- }
-
- private void setAngleText(float angle) {
- if (mTextViewRotateAngle != null) {
- mTextViewRotateAngle.setText(String.format(Locale.getDefault(), "%.1f°", angle));
- }
- }
-
- private void setScaleText(float scale) {
- if (mTextViewScalePercent != null) {
- mTextViewScalePercent.setText(String.format(Locale.getDefault(), "%d%%", (int) (scale * 100)));
- }
- }
-
- private void resetRotation() {
- mGestureCropImageView.postRotate(-mGestureCropImageView.getCurrentAngle());
- mGestureCropImageView.setImageToWrapCropBounds();
- }
-
- private void rotateByAngle(int angle) {
- mGestureCropImageView.postRotate(angle);
- mGestureCropImageView.setImageToWrapCropBounds();
- }
-
- private final View.OnClickListener mStateClickListener = v -> {
- if (!v.isSelected()) {
- setWidgetState(v.getId());
- }
- };
-
- private void setInitialState() {
- if (mShowBottomControls) {
- if (mWrapperStateAspectRatio.getVisibility() == View.VISIBLE) {
- setWidgetState(R.id.state_aspect_ratio);
- } else {
- setWidgetState(R.id.state_scale);
- }
- } else {
- mGestureCropImageView.setScaleEnabled(true);
- mGestureCropImageView.setRotateEnabled(true);
- }
- }
-
- private void setWidgetState(@IdRes int stateViewId) {
- if (!mShowBottomControls) return;
-
- mWrapperStateAspectRatio.setSelected(stateViewId == R.id.state_aspect_ratio);
- mWrapperStateRotate.setSelected(stateViewId == R.id.state_rotate);
- mWrapperStateScale.setSelected(stateViewId == R.id.state_scale);
-
- mLayoutAspectRatio.setVisibility(stateViewId == R.id.state_aspect_ratio ? View.VISIBLE : View.GONE);
- mLayoutRotate.setVisibility(stateViewId == R.id.state_rotate ? View.VISIBLE : View.GONE);
- mLayoutScale.setVisibility(stateViewId == R.id.state_scale ? View.VISIBLE : View.GONE);
-
- if (stateViewId == R.id.state_scale) {
- setAllowedGestures(0);
- } else if (stateViewId == R.id.state_rotate) {
- setAllowedGestures(1);
- } else {
- setAllowedGestures(2);
- }
- }
-
- private void setAllowedGestures(int tab) {
- mGestureCropImageView.setScaleEnabled(mAllowedGestures[tab] == ALL || mAllowedGestures[tab] == SCALE);
- mGestureCropImageView.setRotateEnabled(mAllowedGestures[tab] == ALL || mAllowedGestures[tab] == ROTATE);
- }
-
- /**
- * Adds view that covers everything below the Toolbar.
- * When it's clickable - user won't be able to click/touch anything below the Toolbar.
- * Need to block user input while loading and cropping an image.
- */
- private void addBlockingView() {
- if (mBlockingView == null) {
- mBlockingView = new View(this);
- RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- lp.addRule(RelativeLayout.BELOW, R.id.toolbar);
- mBlockingView.setLayoutParams(lp);
- mBlockingView.setClickable(true);
- }
-
- ((RelativeLayout) findViewById(R.id.ucrop_photobox)).addView(mBlockingView);
- }
-
- protected void cropAndSaveImage() {
- mBlockingView.setClickable(true);
- mShowLoader = true;
- supportInvalidateOptionsMenu();
-
- mGestureCropImageView.cropAndSaveImage(mCompressFormat, mCompressQuality, new BitmapCropCallback() {
-
- @Override
- public void onBitmapCropped(@NonNull Uri resultUri) {
- setResultUri(resultUri, mGestureCropImageView.getTargetAspectRatio());
- }
-
- @Override
- public void onCropFailure(@NonNull Throwable t) {
- setResultError(t);
- }
- });
- }
-
- protected void setResultUri(Uri uri, float resultAspectRatio) {
- ImageCropBean bean = new ImageCropBean();
- bean.copyMediaBean(mMediaBean);
- bean.setCropPath(uri.getPath());
- bean.setAspectRatio(resultAspectRatio);
- BaseResultEvent event = new ImageRadioResultEvent(bean);
- RxBus.getDefault().post(event);
- RxBus.getDefault().post(new CloseRxMediaGridPageEvent());
- finish();
- }
-
- protected void setResultError(Throwable throwable) {
- Logger.e(String.format("Image crop error:%s", throwable.getMessage()));
- RxBus.getDefault().post(new CloseRxMediaGridPageEvent());
- finish();
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/callback/BitmapCropCallback.java b/library/src/main/java/com/yalantis/ucrop/callback/BitmapCropCallback.java
deleted file mode 100755
index b28012c1..00000000
--- a/library/src/main/java/com/yalantis/ucrop/callback/BitmapCropCallback.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.yalantis.ucrop.callback;
-
-import android.net.Uri;
-import android.support.annotation.NonNull;
-
-public interface BitmapCropCallback {
-
- void onBitmapCropped(@NonNull Uri resultUri);
-
- void onCropFailure(@NonNull Throwable t);
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/callback/BitmapLoadCallback.java b/library/src/main/java/com/yalantis/ucrop/callback/BitmapLoadCallback.java
deleted file mode 100755
index b66d87eb..00000000
--- a/library/src/main/java/com/yalantis/ucrop/callback/BitmapLoadCallback.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.yalantis.ucrop.callback;
-
-import android.graphics.Bitmap;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import com.yalantis.ucrop.model.ExifInfo;
-
-public interface BitmapLoadCallback {
-
- void onBitmapLoaded(@NonNull Bitmap bitmap, @NonNull ExifInfo exifInfo, @NonNull String imageInputPath, @Nullable String imageOutputPath);
-
- void onFailure(@NonNull Exception bitmapWorkerException);
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/callback/CropBoundsChangeListener.java b/library/src/main/java/com/yalantis/ucrop/callback/CropBoundsChangeListener.java
deleted file mode 100755
index 38c1badb..00000000
--- a/library/src/main/java/com/yalantis/ucrop/callback/CropBoundsChangeListener.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.yalantis.ucrop.callback;
-
-/**
- * Interface for crop bound change notifying.
- */
-public interface CropBoundsChangeListener {
-
- void onCropAspectRatioChanged(float cropRatio);
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/callback/OverlayViewChangeListener.java b/library/src/main/java/com/yalantis/ucrop/callback/OverlayViewChangeListener.java
deleted file mode 100755
index 29218aeb..00000000
--- a/library/src/main/java/com/yalantis/ucrop/callback/OverlayViewChangeListener.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.yalantis.ucrop.callback;
-
-import android.graphics.RectF;
-
-/**
- * Created by Oleksii Shliama.
- */
-public interface OverlayViewChangeListener {
-
- void onCropRectUpdated(RectF cropRect);
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/model/AspectRatio.java b/library/src/main/java/com/yalantis/ucrop/model/AspectRatio.java
deleted file mode 100755
index 65ca4548..00000000
--- a/library/src/main/java/com/yalantis/ucrop/model/AspectRatio.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.yalantis.ucrop.model;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.support.annotation.Nullable;
-
-/**
- * Created by Oleksii Shliama [https://github.com/shliama] on 6/24/16.
- */
-public class AspectRatio implements Parcelable {
-
- @Nullable
- private final String mAspectRatioTitle;
- private final float mAspectRatioX;
- private final float mAspectRatioY;
-
- public AspectRatio(@Nullable String aspectRatioTitle, float aspectRatioX, float aspectRatioY) {
- mAspectRatioTitle = aspectRatioTitle;
- mAspectRatioX = aspectRatioX;
- mAspectRatioY = aspectRatioY;
- }
-
- protected AspectRatio(Parcel in) {
- mAspectRatioTitle = in.readString();
- mAspectRatioX = in.readFloat();
- mAspectRatioY = in.readFloat();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mAspectRatioTitle);
- dest.writeFloat(mAspectRatioX);
- dest.writeFloat(mAspectRatioY);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator CREATOR = new Creator() {
- @Override
- public AspectRatio createFromParcel(Parcel in) {
- return new AspectRatio(in);
- }
-
- @Override
- public AspectRatio[] newArray(int size) {
- return new AspectRatio[size];
- }
- };
-
- @Nullable
- public String getAspectRatioTitle() {
- return mAspectRatioTitle;
- }
-
- public float getAspectRatioX() {
- return mAspectRatioX;
- }
-
- public float getAspectRatioY() {
- return mAspectRatioY;
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/model/CropParameters.java b/library/src/main/java/com/yalantis/ucrop/model/CropParameters.java
deleted file mode 100755
index 17d8a7e7..00000000
--- a/library/src/main/java/com/yalantis/ucrop/model/CropParameters.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.yalantis.ucrop.model;
-
-import android.graphics.Bitmap;
-
-/**
- * Created by Oleksii Shliama [https://github.com/shliama] on 6/21/16.
- */
-public class CropParameters {
-
- private int mMaxResultImageSizeX, mMaxResultImageSizeY;
-
- private Bitmap.CompressFormat mCompressFormat;
- private int mCompressQuality;
- private String mImageInputPath, mImageOutputPath;
- private ExifInfo mExifInfo;
-
-
- public CropParameters(int maxResultImageSizeX, int maxResultImageSizeY,
- Bitmap.CompressFormat compressFormat, int compressQuality,
- String imageInputPath, String imageOutputPath, ExifInfo exifInfo) {
- mMaxResultImageSizeX = maxResultImageSizeX;
- mMaxResultImageSizeY = maxResultImageSizeY;
- mCompressFormat = compressFormat;
- mCompressQuality = compressQuality;
- mImageInputPath = imageInputPath;
- mImageOutputPath = imageOutputPath;
- mExifInfo = exifInfo;
- }
-
- public int getMaxResultImageSizeX() {
- return mMaxResultImageSizeX;
- }
-
- public int getMaxResultImageSizeY() {
- return mMaxResultImageSizeY;
- }
-
- public Bitmap.CompressFormat getCompressFormat() {
- return mCompressFormat;
- }
-
- public int getCompressQuality() {
- return mCompressQuality;
- }
-
- public String getImageInputPath() {
- return mImageInputPath;
- }
-
- public String getImageOutputPath() {
- return mImageOutputPath;
- }
-
- public ExifInfo getExifInfo() {
- return mExifInfo;
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/model/ExifInfo.java b/library/src/main/java/com/yalantis/ucrop/model/ExifInfo.java
deleted file mode 100755
index 96da038a..00000000
--- a/library/src/main/java/com/yalantis/ucrop/model/ExifInfo.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.yalantis.ucrop.model;
-
-/**
- * Created by Oleksii Shliama [https://github.com/shliama] on 6/21/16.
- */
-public class ExifInfo {
-
- private int mExifOrientation;
- private int mExifDegrees;
- private int mExifTranslation;
-
- public ExifInfo(int exifOrientation, int exifDegrees, int exifTranslation) {
- mExifOrientation = exifOrientation;
- mExifDegrees = exifDegrees;
- mExifTranslation = exifTranslation;
- }
-
- public int getExifOrientation() {
- return mExifOrientation;
- }
-
- public int getExifDegrees() {
- return mExifDegrees;
- }
-
- public int getExifTranslation() {
- return mExifTranslation;
- }
-
- public void setExifOrientation(int exifOrientation) {
- mExifOrientation = exifOrientation;
- }
-
- public void setExifDegrees(int exifDegrees) {
- mExifDegrees = exifDegrees;
- }
-
- public void setExifTranslation(int exifTranslation) {
- mExifTranslation = exifTranslation;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- ExifInfo exifInfo = (ExifInfo) o;
-
- if (mExifOrientation != exifInfo.mExifOrientation) return false;
- if (mExifDegrees != exifInfo.mExifDegrees) return false;
- return mExifTranslation == exifInfo.mExifTranslation;
-
- }
-
- @Override
- public int hashCode() {
- int result = mExifOrientation;
- result = 31 * result + mExifDegrees;
- result = 31 * result + mExifTranslation;
- return result;
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/model/ImageState.java b/library/src/main/java/com/yalantis/ucrop/model/ImageState.java
deleted file mode 100755
index ebaab9c1..00000000
--- a/library/src/main/java/com/yalantis/ucrop/model/ImageState.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.yalantis.ucrop.model;
-
-import android.graphics.RectF;
-
-/**
- * Created by Oleksii Shliama [https://github.com/shliama] on 6/21/16.
- */
-public class ImageState {
-
- private RectF mCropRect;
- private RectF mCurrentImageRect;
-
- private float mCurrentScale, mCurrentAngle;
-
- public ImageState(RectF cropRect, RectF currentImageRect, float currentScale, float currentAngle) {
- mCropRect = cropRect;
- mCurrentImageRect = currentImageRect;
- mCurrentScale = currentScale;
- mCurrentAngle = currentAngle;
- }
-
- public RectF getCropRect() {
- return mCropRect;
- }
-
- public RectF getCurrentImageRect() {
- return mCurrentImageRect;
- }
-
- public float getCurrentScale() {
- return mCurrentScale;
- }
-
- public float getCurrentAngle() {
- return mCurrentAngle;
- }
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java b/library/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java
deleted file mode 100755
index 452368fc..00000000
--- a/library/src/main/java/com/yalantis/ucrop/task/BitmapCropTask.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.yalantis.ucrop.task;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.RectF;
-import android.media.ExifInterface;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.Log;
-
-import com.yalantis.ucrop.callback.BitmapCropCallback;
-import com.yalantis.ucrop.model.CropParameters;
-import com.yalantis.ucrop.model.ExifInfo;
-import com.yalantis.ucrop.model.ImageState;
-import com.yalantis.ucrop.util.FileUtils;
-import com.yalantis.ucrop.util.ImageHeaderParser;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Crops part of image that fills the crop bounds.
- *
- * First image is downscaled if max size was set and if resulting image is larger that max size.
- * Then image is rotated accordingly.
- * Finally new Bitmap object is created and saved to file.
- */
-public class BitmapCropTask extends AsyncTask {
-
- private static final String TAG = "BitmapCropTask";
-
- static {
- System.loadLibrary("ucrop");
- }
-
- private Bitmap mViewBitmap;
-
- private final RectF mCropRect;
- private final RectF mCurrentImageRect;
-
- private float mCurrentScale, mCurrentAngle;
- private final int mMaxResultImageSizeX, mMaxResultImageSizeY;
-
- private final Bitmap.CompressFormat mCompressFormat;
- private final int mCompressQuality;
- private final String mImageInputPath, mImageOutputPath;
- private final ExifInfo mExifInfo;
- private final BitmapCropCallback mCropCallback;
-
- public BitmapCropTask(@Nullable Bitmap viewBitmap, @NonNull ImageState imageState, @NonNull CropParameters cropParameters,
- @Nullable BitmapCropCallback cropCallback) {
-
- mViewBitmap = viewBitmap;
- mCropRect = imageState.getCropRect();
- mCurrentImageRect = imageState.getCurrentImageRect();
-
- mCurrentScale = imageState.getCurrentScale();
- mCurrentAngle = imageState.getCurrentAngle();
- mMaxResultImageSizeX = cropParameters.getMaxResultImageSizeX();
- mMaxResultImageSizeY = cropParameters.getMaxResultImageSizeY();
-
- mCompressFormat = cropParameters.getCompressFormat();
- mCompressQuality = cropParameters.getCompressQuality();
-
- mImageInputPath = cropParameters.getImageInputPath();
- mImageOutputPath = cropParameters.getImageOutputPath();
- mExifInfo = cropParameters.getExifInfo();
-
- mCropCallback = cropCallback;
- }
-
- @Override
- @Nullable
- protected Throwable doInBackground(Void... params) {
- if (mViewBitmap == null) {
- return new NullPointerException("ViewBitmap is null");
- } else if (mViewBitmap.isRecycled()) {
- return new NullPointerException("ViewBitmap is recycled");
- } else if (mCurrentImageRect.isEmpty()) {
- return new NullPointerException("CurrentImageRect is empty");
- }
-
- float resizeScale = resize();
-
- try {
- crop(resizeScale);
- mViewBitmap = null;
- } catch (Throwable throwable) {
- return throwable;
- }
-
- return null;
- }
-
- private float resize() {
- final BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(mImageInputPath, options);
-
- boolean swapSides = mExifInfo.getExifDegrees() == 90 || mExifInfo.getExifDegrees() == 270;
- float scaleX = (swapSides ? options.outHeight : options.outWidth) / (float) mViewBitmap.getWidth();
- float scaleY = (swapSides ? options.outWidth : options.outHeight) / (float) mViewBitmap.getHeight();
-
- float resizeScale = Math.min(scaleX, scaleY);
-
- mCurrentScale /= resizeScale;
-
- resizeScale = 1;
- if (mMaxResultImageSizeX > 0 && mMaxResultImageSizeY > 0) {
- float cropWidth = mCropRect.width() / mCurrentScale;
- float cropHeight = mCropRect.height() / mCurrentScale;
-
- if (cropWidth > mMaxResultImageSizeX || cropHeight > mMaxResultImageSizeY) {
-
- scaleX = mMaxResultImageSizeX / cropWidth;
- scaleY = mMaxResultImageSizeY / cropHeight;
- resizeScale = Math.min(scaleX, scaleY);
-
- mCurrentScale /= resizeScale;
- }
- }
- return resizeScale;
- }
-
- private boolean crop(float resizeScale) throws IOException {
- ExifInterface originalExif = new ExifInterface(mImageInputPath);
-
- int top = Math.round((mCropRect.top - mCurrentImageRect.top) / mCurrentScale);
- int left = Math.round((mCropRect.left - mCurrentImageRect.left) / mCurrentScale);
- int width = Math.round(mCropRect.width() / mCurrentScale);
- int height = Math.round(mCropRect.height() / mCurrentScale);
-
- boolean shouldCrop = shouldCrop(width, height);
- Log.i(TAG, "Should crop: " + shouldCrop);
-
- if (shouldCrop) {
- boolean cropped = cropCImg(mImageInputPath, mImageOutputPath,
- left, top, width, height, mCurrentAngle, resizeScale,
- mCompressFormat.ordinal(), mCompressQuality,
- mExifInfo.getExifDegrees(), mExifInfo.getExifTranslation());
- if (cropped) {
- ImageHeaderParser.copyExif(originalExif, width, height, mImageOutputPath);
- }
- return cropped;
- } else {
- FileUtils.copyFile(mImageInputPath, mImageOutputPath);
- return false;
- }
- }
-
- /**
- * Check whether an image should be cropped at all or just file can be copied to the destination path.
- * For each 1000 pixels there is one pixel of error due to matrix calculations etc.
- *
- * @param width - crop area width
- * @param height - crop area height
- * @return - true if image must be cropped, false - if original image fits requirements
- */
- private boolean shouldCrop(int width, int height) {
- int pixelError = 1;
- pixelError += Math.round(Math.max(width, height) / 1000f);
- return (mMaxResultImageSizeX > 0 && mMaxResultImageSizeY > 0)
- || Math.abs(mCropRect.left - mCurrentImageRect.left) > pixelError
- || Math.abs(mCropRect.top - mCurrentImageRect.top) > pixelError
- || Math.abs(mCropRect.bottom - mCurrentImageRect.bottom) > pixelError
- || Math.abs(mCropRect.right - mCurrentImageRect.right) > pixelError;
- }
-
- @SuppressWarnings("JniMissingFunction")
- native public boolean
- cropCImg(String inputPath, String outputPath,
- int left, int top, int width, int height,
- float angle, float resizeScale,
- int format, int quality,
- int exifDegrees, int exifTranslation) throws IOException, OutOfMemoryError;
-
- @Override
- protected void onPostExecute(@Nullable Throwable t) {
- if (mCropCallback != null) {
- if (t == null) {
- mCropCallback.onBitmapCropped(Uri.fromFile(new File(mImageOutputPath)));
- } else {
- mCropCallback.onCropFailure(t);
- }
- }
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java b/library/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java
deleted file mode 100755
index 22587c43..00000000
--- a/library/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java
+++ /dev/null
@@ -1,214 +0,0 @@
-package com.yalantis.ucrop.task;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.yalantis.ucrop.callback.BitmapLoadCallback;
-import com.yalantis.ucrop.model.ExifInfo;
-import com.yalantis.ucrop.util.BitmapLoadUtils;
-import com.yalantis.ucrop.util.FileUtils;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Creates and returns a Bitmap for a given Uri(String url).
- * inSampleSize is calculated based on requiredWidth property. However can be adjusted if OOM occurs.
- * If any EXIF config is found - bitmap is transformed properly.
- */
-public class BitmapLoadTask extends AsyncTask {
-
- private static final String TAG = "BitmapWorkerTask";
-
- private final Context mContext;
- private Uri mInputUri;
- private Uri mOutputUri;
- private final int mRequiredWidth;
- private final int mRequiredHeight;
-
- private final BitmapLoadCallback mBitmapLoadCallback;
-
- public static class BitmapWorkerResult {
-
- Bitmap mBitmapResult;
- ExifInfo mExifInfo;
- Exception mBitmapWorkerException;
-
- public BitmapWorkerResult(@NonNull Bitmap bitmapResult, @NonNull ExifInfo exifInfo) {
- mBitmapResult = bitmapResult;
- mExifInfo = exifInfo;
- }
-
- public BitmapWorkerResult(@NonNull Exception bitmapWorkerException) {
- mBitmapWorkerException = bitmapWorkerException;
- }
-
- }
-
- public BitmapLoadTask(@NonNull Context context,
- @NonNull Uri inputUri, @Nullable Uri outputUri,
- int requiredWidth, int requiredHeight,
- BitmapLoadCallback loadCallback) {
- mContext = context;
- mInputUri = inputUri;
- mOutputUri = outputUri;
- mRequiredWidth = requiredWidth;
- mRequiredHeight = requiredHeight;
- mBitmapLoadCallback = loadCallback;
- }
-
- @Override
- @NonNull
- protected BitmapWorkerResult doInBackground(Void... params) {
- if (mInputUri == null) {
- return new BitmapWorkerResult(new NullPointerException("Input Uri cannot be null"));
- }
-
- try {
- processInputUri();
- } catch (NullPointerException | IOException e) {
- return new BitmapWorkerResult(e);
- }
-
- final ParcelFileDescriptor parcelFileDescriptor;
- try {
- parcelFileDescriptor = mContext.getContentResolver().openFileDescriptor(mInputUri, "r");
- } catch (FileNotFoundException e) {
- return new BitmapWorkerResult(e);
- }
-
- final FileDescriptor fileDescriptor;
- if (parcelFileDescriptor != null) {
- fileDescriptor = parcelFileDescriptor.getFileDescriptor();
- } else {
- return new BitmapWorkerResult(new NullPointerException("ParcelFileDescriptor was null for given Uri: [" + mInputUri + "]"));
- }
-
- final BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
- if (options.outWidth == -1 || options.outHeight == -1) {
- return new BitmapWorkerResult(new IllegalArgumentException("Bounds for bitmap could not be retrieved from the Uri: [" + mInputUri + "]"));
- }
-
- options.inSampleSize = BitmapLoadUtils.calculateInSampleSize(options, mRequiredWidth, mRequiredHeight);
- options.inJustDecodeBounds = false;
-
- Bitmap decodeSampledBitmap = null;
-
- boolean decodeAttemptSuccess = false;
- while (!decodeAttemptSuccess) {
- try {
- decodeSampledBitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
- decodeAttemptSuccess = true;
- } catch (OutOfMemoryError error) {
- Log.e(TAG, "doInBackground: BitmapFactory.decodeFileDescriptor: ", error);
- options.inSampleSize *= 2;
- }
- }
-
- if (decodeSampledBitmap == null) {
- return new BitmapWorkerResult(new IllegalArgumentException("Bitmap could not be decoded from the Uri: [" + mInputUri + "]"));
- }
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- BitmapLoadUtils.close(parcelFileDescriptor);
- }
-
- int exifOrientation = BitmapLoadUtils.getExifOrientation(mContext, mInputUri);
- int exifDegrees = BitmapLoadUtils.exifToDegrees(exifOrientation);
- int exifTranslation = BitmapLoadUtils.exifToTranslation(exifOrientation);
-
- ExifInfo exifInfo = new ExifInfo(exifOrientation, exifDegrees, exifTranslation);
-
- Matrix matrix = new Matrix();
- if (exifDegrees != 0) {
- matrix.preRotate(exifDegrees);
- }
- if (exifTranslation != 1) {
- matrix.postScale(exifTranslation, 1);
- }
- if (!matrix.isIdentity()) {
- return new BitmapWorkerResult(BitmapLoadUtils.transformBitmap(decodeSampledBitmap, matrix), exifInfo);
- }
-
- return new BitmapWorkerResult(decodeSampledBitmap, exifInfo);
- }
-
- private void processInputUri() throws NullPointerException, IOException {
- String inputUriScheme = mInputUri.getScheme();
- Log.d(TAG, "Uri scheme: " + inputUriScheme);
- if ("content".equals(inputUriScheme)) {
- String path = FileUtils.getPath(mContext, mInputUri);
- if (!TextUtils.isEmpty(path) && new File(path).exists()) {
- mInputUri = Uri.fromFile(new File(path));
- } else {
- try {
- copyFile(mInputUri, mOutputUri);
- } catch (NullPointerException | IOException e) {
- Log.e(TAG, "Copying failed", e);
- throw e;
- }
- }
- } else if (!"file".equals(inputUriScheme)) {
- Log.e(TAG, "Invalid Uri scheme " + inputUriScheme);
- throw new IllegalArgumentException("Invalid Uri scheme" + inputUriScheme);
- }
- }
-
- private void copyFile(@NonNull Uri inputUri, @Nullable Uri outputUri) throws NullPointerException, IOException {
- Log.d(TAG, "copyFile");
-
- if (outputUri == null) {
- throw new NullPointerException("Output Uri is null - cannot copy image");
- }
-
- InputStream inputStream = null;
- OutputStream outputStream = null;
- try {
- inputStream = mContext.getContentResolver().openInputStream(inputUri);
- outputStream = new FileOutputStream(new File(outputUri.getPath()));
- if (inputStream == null) {
- throw new NullPointerException("InputStream for given input Uri is null");
- }
-
- byte buffer[] = new byte[1024];
- int length;
- while ((length = inputStream.read(buffer)) > 0) {
- outputStream.write(buffer, 0, length);
- }
- } finally {
- BitmapLoadUtils.close(outputStream);
- BitmapLoadUtils.close(inputStream);
-
- // swap uris, because input image was copied to the output destination
- // (cropped image will override it later)
- mInputUri = mOutputUri;
- }
- }
-
- @Override
- protected void onPostExecute(@NonNull BitmapWorkerResult result) {
- if (result.mBitmapWorkerException == null) {
- mBitmapLoadCallback.onBitmapLoaded(result.mBitmapResult, result.mExifInfo, mInputUri.getPath(), (mOutputUri == null) ? null : mOutputUri.getPath());
- } else {
- mBitmapLoadCallback.onFailure(result.mBitmapWorkerException);
- }
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/util/BitmapLoadUtils.java b/library/src/main/java/com/yalantis/ucrop/util/BitmapLoadUtils.java
deleted file mode 100755
index 97b43078..00000000
--- a/library/src/main/java/com/yalantis/ucrop/util/BitmapLoadUtils.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.yalantis.ucrop.util;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Point;
-import android.media.ExifInterface;
-import android.net.Uri;
-import android.os.Build;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.Log;
-import android.view.Display;
-import android.view.WindowManager;
-
-import com.yalantis.ucrop.callback.BitmapLoadCallback;
-import com.yalantis.ucrop.task.BitmapLoadTask;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Created by Oleksii Shliama (https://github.com/shliama).
- */
-public class BitmapLoadUtils {
-
- private static final String TAG = "BitmapLoadUtils";
-
- public static void decodeBitmapInBackground(@NonNull Context context,
- @NonNull Uri uri, @Nullable Uri outputUri,
- int requiredWidth, int requiredHeight,
- BitmapLoadCallback loadCallback) {
-
- new BitmapLoadTask(context, uri, outputUri, requiredWidth, requiredHeight, loadCallback).execute();
- }
-
- public static Bitmap transformBitmap(@NonNull Bitmap bitmap, @NonNull Matrix transformMatrix) {
- try {
- Bitmap converted = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), transformMatrix, true);
- if (!bitmap.sameAs(converted)) {
- bitmap = converted;
- }
- } catch (OutOfMemoryError error) {
- Log.e(TAG, "transformBitmap: ", error);
- }
- return bitmap;
- }
-
- public static int calculateInSampleSize(@NonNull BitmapFactory.Options options, int reqWidth, int reqHeight) {
- // Raw height and width of image
- final int height = options.outHeight;
- final int width = options.outWidth;
- int inSampleSize = 1;
-
- if (height > reqHeight || width > reqWidth) {
- // Calculate the largest inSampleSize value that is a power of 2 and keeps both
- // height and width lower or equal to the requested height and width.
- while ((height / inSampleSize) > reqHeight || (width / inSampleSize) > reqWidth) {
- inSampleSize *= 2;
- }
- }
- return inSampleSize;
- }
-
- public static int getExifOrientation(@NonNull Context context, @NonNull Uri imageUri) {
- int orientation = ExifInterface.ORIENTATION_UNDEFINED;
- try {
- InputStream stream = context.getContentResolver().openInputStream(imageUri);
- if (stream == null) {
- return orientation;
- }
- orientation = new ImageHeaderParser(stream).getOrientation();
- close(stream);
- } catch (IOException e) {
- Log.e(TAG, "getExifOrientation: " + imageUri.toString(), e);
- }
- return orientation;
- }
-
- public static int exifToDegrees(int exifOrientation) {
- int rotation;
- switch (exifOrientation) {
- case ExifInterface.ORIENTATION_ROTATE_90:
- case ExifInterface.ORIENTATION_TRANSPOSE:
- rotation = 90;
- break;
- case ExifInterface.ORIENTATION_ROTATE_180:
- case ExifInterface.ORIENTATION_FLIP_VERTICAL:
- rotation = 180;
- break;
- case ExifInterface.ORIENTATION_ROTATE_270:
- case ExifInterface.ORIENTATION_TRANSVERSE:
- rotation = 270;
- break;
- default:
- rotation = 0;
- }
- return rotation;
- }
-
- public static int exifToTranslation(int exifOrientation) {
- int translation;
- switch (exifOrientation) {
- case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
- case ExifInterface.ORIENTATION_FLIP_VERTICAL:
- case ExifInterface.ORIENTATION_TRANSPOSE:
- case ExifInterface.ORIENTATION_TRANSVERSE:
- translation = -1;
- break;
- default:
- translation = 1;
- }
- return translation;
- }
-
- /**
- * This method calculates maximum size of both width and height of bitmap.
- * It is twice the device screen diagonal for default implementation (extra quality to zoom image).
- * Size cannot exceed max texture size.
- *
- * @return - max bitmap size in pixels.
- */
- @SuppressWarnings({"SuspiciousNameCombination", "deprecation"})
- public static int calculateMaxBitmapSize(@NonNull Context context) {
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
-
- Point size = new Point();
- int width, height;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
- display.getSize(size);
- width = size.x;
- height = size.y;
- } else {
- width = display.getWidth();
- height = display.getHeight();
- }
-
- int screenDiagonal = (int) Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
-
- Canvas canvas = new Canvas();
- return Math.min(screenDiagonal * 2, Math.min(canvas.getMaximumBitmapWidth(), canvas.getMaximumBitmapHeight()));
- }
-
- @SuppressWarnings("ConstantConditions")
- public static void close(@Nullable Closeable c) {
- if (c != null && c instanceof Closeable) { // java.lang.IncompatibleClassChangeError: interface not implemented
- try {
- c.close();
- } catch (IOException e) {
- // silence
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/util/CubicEasing.java b/library/src/main/java/com/yalantis/ucrop/util/CubicEasing.java
deleted file mode 100755
index 3c81b8ec..00000000
--- a/library/src/main/java/com/yalantis/ucrop/util/CubicEasing.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.yalantis.ucrop.util;
-
-public final class CubicEasing {
-
- public static float easeOut(float time, float start, float end, float duration) {
- return end * ((time = time / duration - 1.0f) * time * time + 1.0f) + start;
- }
-
- public static float easeIn(float time, float start, float end, float duration) {
- return end * (time /= duration) * time * time + start;
- }
-
- public static float easeInOut(float time, float start, float end, float duration) {
- return (time /= duration / 2.0f) < 1.0f ? end / 2.0f * time * time * time + start : end / 2.0f * ((time -= 2.0f) * time * time + 2.0f) + start;
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/util/FastBitmapDrawable.java b/library/src/main/java/com/yalantis/ucrop/util/FastBitmapDrawable.java
deleted file mode 100755
index 53c621bb..00000000
--- a/library/src/main/java/com/yalantis/ucrop/util/FastBitmapDrawable.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.yalantis.ucrop.util;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-
-public class FastBitmapDrawable extends Drawable {
-
- private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
- private Bitmap mBitmap;
- private int mAlpha;
- private int mWidth, mHeight;
-
- public FastBitmapDrawable(Bitmap b) {
- mAlpha = 255;
- setBitmap(b);
- }
-
- @Override
- public void draw(Canvas canvas) {
- if (mBitmap != null && !mBitmap.isRecycled()) {
- canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
- }
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- mPaint.setColorFilter(cf);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- public void setFilterBitmap(boolean filterBitmap) {
- mPaint.setFilterBitmap(filterBitmap);
- }
-
- public int getAlpha() {
- return mAlpha;
- }
-
- @Override
- public void setAlpha(int alpha) {
- mAlpha = alpha;
- mPaint.setAlpha(alpha);
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mWidth;
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mHeight;
- }
-
- @Override
- public int getMinimumWidth() {
- return mWidth;
- }
-
- @Override
- public int getMinimumHeight() {
- return mHeight;
- }
-
- public Bitmap getBitmap() {
- return mBitmap;
- }
-
- public void setBitmap(Bitmap b) {
- mBitmap = b;
- if (b != null) {
- mWidth = mBitmap.getWidth();
- mHeight = mBitmap.getHeight();
- } else {
- mWidth = mHeight = 0;
- }
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/util/FileUtils.java b/library/src/main/java/com/yalantis/ucrop/util/FileUtils.java
deleted file mode 100755
index 5481ce6e..00000000
--- a/library/src/main/java/com/yalantis/ucrop/util/FileUtils.java
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (C) 2007-2008 OpenIntents.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.yalantis.ucrop.util;
-
-import android.annotation.SuppressLint;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
-import android.provider.DocumentsContract;
-import android.provider.MediaStore;
-import android.support.annotation.NonNull;
-import android.util.Log;
-import android.webkit.MimeTypeMap;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.channels.FileChannel;
-import java.text.DecimalFormat;
-import java.util.Comparator;
-
-/**
- * @author Peli
- * @author paulburke (ipaulpro)
- * @version 2013-12-11
- */
-public class FileUtils {
- private FileUtils() {
- } //private constructor to enforce Singleton pattern
-
- /**
- * TAG for log messages.
- */
- static final String TAG = "FileUtils";
- private static final boolean DEBUG = false; // Set to true to enable logging
-
- public static final String MIME_TYPE_AUDIO = "audio/*";
- public static final String MIME_TYPE_TEXT = "text/*";
- public static final String MIME_TYPE_IMAGE = "image/*";
- public static final String MIME_TYPE_VIDEO = "video/*";
- public static final String MIME_TYPE_APP = "application/*";
-
- public static final String HIDDEN_PREFIX = ".";
-
- /**
- * Gets the extension of a file name, like ".png" or ".jpg".
- *
- * @param uri
- * @return Extension including the dot("."); "" if there is no extension;
- * null if uri was null.
- */
- public static String getExtension(String uri) {
- if (uri == null) {
- return null;
- }
-
- int dot = uri.lastIndexOf(".");
- if (dot >= 0) {
- return uri.substring(dot);
- } else {
- // No extension.
- return "";
- }
- }
-
- /**
- * @return Whether the URI is a local one.
- */
- public static boolean isLocal(String url) {
- if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) {
- return true;
- }
- return false;
- }
-
- /**
- * @return True if Uri is a MediaStore Uri.
- * @author paulburke
- */
- public static boolean isMediaUri(Uri uri) {
- return "media".equalsIgnoreCase(uri.getAuthority());
- }
-
- /**
- * Convert File into Uri.
- *
- * @param file
- * @return uri
- */
- public static Uri getUri(File file) {
- if (file != null) {
- return Uri.fromFile(file);
- }
- return null;
- }
-
- /**
- * Returns the path only (without file name).
- *
- * @param file
- * @return
- */
- public static File getPathWithoutFilename(File file) {
- if (file != null) {
- if (file.isDirectory()) {
- // no file to be split off. Return everything
- return file;
- } else {
- String filename = file.getName();
- String filepath = file.getAbsolutePath();
-
- // Construct path without file name.
- String pathwithoutname = filepath.substring(0,
- filepath.length() - filename.length());
- if (pathwithoutname.endsWith("/")) {
- pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
- }
- return new File(pathwithoutname);
- }
- }
- return null;
- }
-
- /**
- * @return The MIME type for the given file.
- */
- public static String getMimeType(File file) {
-
- String extension = getExtension(file.getName());
-
- if (extension.length() > 0)
- return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));
-
- return "application/octet-stream";
- }
-
- /**
- * @return The MIME type for the give Uri.
- */
- public static String getMimeType(Context context, Uri uri) {
- File file = new File(getPath(context, uri));
- return getMimeType(file);
- }
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is ExternalStorageProvider.
- * @author paulburke
- */
- public static boolean isExternalStorageDocument(Uri uri) {
- return "com.android.externalstorage.documents".equals(uri.getAuthority());
- }
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is DownloadsProvider.
- * @author paulburke
- */
- public static boolean isDownloadsDocument(Uri uri) {
- return "com.android.providers.downloads.documents".equals(uri.getAuthority());
- }
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is MediaProvider.
- * @author paulburke
- */
- public static boolean isMediaDocument(Uri uri) {
- return "com.android.providers.media.documents".equals(uri.getAuthority());
- }
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is Google Photos.
- */
- public static boolean isGooglePhotosUri(Uri uri) {
- return "com.google.android.apps.photos.content".equals(uri.getAuthority());
- }
-
- /**
- * Get the value of the data column for this Uri. This is useful for
- * MediaStore Uris, and other file-based ContentProviders.
- *
- * @param context The context.
- * @param uri The Uri to query.
- * @param selection (Optional) Filter used in the query.
- * @param selectionArgs (Optional) Selection arguments used in the query.
- * @return The value of the _data column, which is typically a file path.
- * @author paulburke
- */
- public static String getDataColumn(Context context, Uri uri, String selection,
- String[] selectionArgs) {
-
- Cursor cursor = null;
- final String column = "_data";
- final String[] projection = {
- column
- };
-
- try {
- cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
- null);
- if (cursor != null && cursor.moveToFirst()) {
- if (DEBUG)
- DatabaseUtils.dumpCursor(cursor);
-
- final int column_index = cursor.getColumnIndexOrThrow(column);
- return cursor.getString(column_index);
- }
- } catch (IllegalArgumentException ex) {
- Log.i(TAG, "getDataColumn: _data", ex);
- } finally {
- if (cursor != null)
- cursor.close();
- }
- return null;
- }
-
- /**
- * Get a file path from a Uri. This will get the the path for Storage Access
- * Framework Documents, as well as the _data field for the MediaStore and
- * other file-based ContentProviders.
- *
- * Callers should check whether the path is local before assuming it
- * represents a local file.
- *
- * @param context The context.
- * @param uri The Uri to query.
- * @author paulburke
- * @see #isLocal(String)
- * @see #getFile(Context, Uri)
- */
- @SuppressLint("NewApi")
- public static String getPath(final Context context, final Uri uri) {
-
- if (DEBUG)
- Log.d(TAG + " File -",
- "Authority: " + uri.getAuthority() +
- ", Fragment: " + uri.getFragment() +
- ", Port: " + uri.getPort() +
- ", Query: " + uri.getQuery() +
- ", Scheme: " + uri.getScheme() +
- ", Host: " + uri.getHost() +
- ", Segments: " + uri.getPathSegments().toString()
- );
-
- final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
-
- // DocumentProvider
- if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
- if (isExternalStorageDocument(uri)) {
- final String docId = DocumentsContract.getDocumentId(uri);
- final String[] split = docId.split(":");
- final String type = split[0];
-
- if ("primary".equalsIgnoreCase(type)) {
- return Environment.getExternalStorageDirectory() + "/" + split[1];
- }
-
- // TODO handle non-primary volumes
- }
- // DownloadsProvider
- else if (isDownloadsDocument(uri)) {
-
- final String id = DocumentsContract.getDocumentId(uri);
- final Uri contentUri = ContentUris.withAppendedId(
- Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
-
- return getDataColumn(context, contentUri, null, null);
- }
- // MediaProvider
- else if (isMediaDocument(uri)) {
- final String docId = DocumentsContract.getDocumentId(uri);
- final String[] split = docId.split(":");
- final String type = split[0];
-
- Uri contentUri = null;
- if ("image".equals(type)) {
- contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
- } else if ("video".equals(type)) {
- contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
- } else if ("audio".equals(type)) {
- contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
- }
-
- final String selection = "_id=?";
- final String[] selectionArgs = new String[]{
- split[1]
- };
-
- return getDataColumn(context, contentUri, selection, selectionArgs);
- }
- }
- // MediaStore (and general)
- else if ("content".equalsIgnoreCase(uri.getScheme())) {
-
- // Return the remote address
- if (isGooglePhotosUri(uri))
- return uri.getLastPathSegment();
-
- return getDataColumn(context, uri, null, null);
- }
- // File
- else if ("file".equalsIgnoreCase(uri.getScheme())) {
- return uri.getPath();
- }
-
- return null;
- }
-
- /**
- * Convert Uri into File, if possible.
- *
- * @return file A local file that the Uri was pointing to, or null if the
- * Uri is unsupported or pointed to a remote resource.
- * @author paulburke
- * @see #getPath(Context, Uri)
- */
- public static File getFile(Context context, Uri uri) {
- if (uri != null) {
- String path = getPath(context, uri);
- if (path != null && isLocal(path)) {
- return new File(path);
- }
- }
- return null;
- }
-
- /**
- * Get the file size in a human-readable string.
- *
- * @param size
- * @return
- * @author paulburke
- */
- public static String getReadableFileSize(int size) {
- final int BYTES_IN_KILOBYTES = 1024;
- final DecimalFormat dec = new DecimalFormat("###.#");
- final String KILOBYTES = " KB";
- final String MEGABYTES = " MB";
- final String GIGABYTES = " GB";
- float fileSize = 0;
- String suffix = KILOBYTES;
-
- if (size > BYTES_IN_KILOBYTES) {
- fileSize = size / BYTES_IN_KILOBYTES;
- if (fileSize > BYTES_IN_KILOBYTES) {
- fileSize = fileSize / BYTES_IN_KILOBYTES;
- if (fileSize > BYTES_IN_KILOBYTES) {
- fileSize = fileSize / BYTES_IN_KILOBYTES;
- suffix = GIGABYTES;
- } else {
- suffix = MEGABYTES;
- }
- }
- }
- return String.valueOf(dec.format(fileSize) + suffix);
- }
-
- /**
- * Attempt to retrieve the thumbnail of given File from the MediaStore. This
- * should not be called on the UI thread.
- *
- * @param context
- * @param file
- * @return
- * @author paulburke
- */
- public static Bitmap getThumbnail(Context context, File file) {
- return getThumbnail(context, getUri(file), getMimeType(file));
- }
-
- /**
- * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
- * should not be called on the UI thread.
- *
- * @param context
- * @param uri
- * @return
- * @author paulburke
- */
- public static Bitmap getThumbnail(Context context, Uri uri) {
- return getThumbnail(context, uri, getMimeType(context, uri));
- }
-
- /**
- * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
- * should not be called on the UI thread.
- *
- * @param context
- * @param uri
- * @param mimeType
- * @return
- * @author paulburke
- */
- public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
- if (DEBUG)
- Log.d(TAG, "Attempting to get thumbnail");
-
- if (!isMediaUri(uri)) {
- Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
- return null;
- }
-
- Bitmap bm = null;
- if (uri != null) {
- final ContentResolver resolver = context.getContentResolver();
- Cursor cursor = null;
- try {
- cursor = resolver.query(uri, null, null, null, null);
- if (cursor.moveToFirst()) {
- final int id = cursor.getInt(0);
- if (DEBUG)
- Log.d(TAG, "Got thumb ID: " + id);
-
- if (mimeType.contains("video")) {
- bm = MediaStore.Video.Thumbnails.getThumbnail(
- resolver,
- id,
- MediaStore.Video.Thumbnails.MINI_KIND,
- null);
- } else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
- bm = MediaStore.Images.Thumbnails.getThumbnail(
- resolver,
- id,
- MediaStore.Images.Thumbnails.MINI_KIND,
- null);
- }
- }
- } catch (Exception e) {
- if (DEBUG)
- Log.e(TAG, "getThumbnail", e);
- } finally {
- if (cursor != null)
- cursor.close();
- }
- }
- return bm;
- }
-
- /**
- * File and folder comparator. TODO Expose sorting option method
- *
- * @author paulburke
- */
- public static Comparator sComparator = new Comparator() {
- @Override
- public int compare(File f1, File f2) {
- // Sort alphabetically by lower case, which is much cleaner
- return f1.getName().toLowerCase().compareTo(
- f2.getName().toLowerCase());
- }
- };
-
- /**
- * File (not directories) filter.
- *
- * @author paulburke
- */
- public static FileFilter sFileFilter = new FileFilter() {
- @Override
- public boolean accept(File file) {
- final String fileName = file.getName();
- // Return files only (not directories) and skip hidden files
- return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
- }
- };
-
- /**
- * Folder (directories) filter.
- *
- * @author paulburke
- */
- public static FileFilter sDirFilter = new FileFilter() {
- @Override
- public boolean accept(File file) {
- final String fileName = file.getName();
- // Return directories only and skip hidden directories
- return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
- }
- };
-
- /**
- * Get the Intent for selecting content to be used in an Intent Chooser.
- *
- * @return The intent for opening a file with Intent.createChooser()
- * @author paulburke
- */
- public static Intent createGetContentIntent() {
- // Implicitly allow the user to select a particular kind of data
- final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- // The MIME data type filter
- intent.setType("*/*");
- // Only return URIs that can be opened with ContentResolver
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- return intent;
- }
-
- public static void copyFile(@NonNull String pathFrom, @NonNull String pathTo) throws IOException {
- FileChannel outputChannel = null;
- FileChannel inputChannel = null;
- try {
- inputChannel = new FileInputStream(new File(pathFrom)).getChannel();
- outputChannel = new FileOutputStream(new File(pathTo)).getChannel();
- inputChannel.transferTo(0, inputChannel.size(), outputChannel);
- inputChannel.close();
- } finally {
- if (inputChannel != null) inputChannel.close();
- if (outputChannel != null) outputChannel.close();
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/util/ImageHeaderParser.java b/library/src/main/java/com/yalantis/ucrop/util/ImageHeaderParser.java
deleted file mode 100755
index 6b476f4e..00000000
--- a/library/src/main/java/com/yalantis/ucrop/util/ImageHeaderParser.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright 2015 Google, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of Google, Inc.
- *
- * Adapted for the uCrop library.
- */
-
-package com.yalantis.ucrop.util;
-
-import android.media.ExifInterface;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.charset.Charset;
-
-/**
- * A class for parsing the exif orientation from an image header.
- */
-public class ImageHeaderParser {
- private static final String TAG = "ImageHeaderParser";
- /**
- * A constant indicating we were unable to parse the orientation from the image either because
- * no exif segment containing orientation data existed, or because of an I/O error attempting to
- * read the exif segment.
- */
- public static final int UNKNOWN_ORIENTATION = -1;
-
- private static final int EXIF_MAGIC_NUMBER = 0xFFD8;
- // "MM".
- private static final int MOTOROLA_TIFF_MAGIC_NUMBER = 0x4D4D;
- // "II".
- private static final int INTEL_TIFF_MAGIC_NUMBER = 0x4949;
- private static final String JPEG_EXIF_SEGMENT_PREAMBLE = "Exif\0\0";
- private static final byte[] JPEG_EXIF_SEGMENT_PREAMBLE_BYTES =
- JPEG_EXIF_SEGMENT_PREAMBLE.getBytes(Charset.forName("UTF-8"));
- private static final int SEGMENT_SOS = 0xDA;
- private static final int MARKER_EOI = 0xD9;
- private static final int SEGMENT_START_ID = 0xFF;
- private static final int EXIF_SEGMENT_TYPE = 0xE1;
- private static final int ORIENTATION_TAG_TYPE = 0x0112;
- private static final int[] BYTES_PER_FORMAT = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
-
- private final Reader reader;
-
- public ImageHeaderParser(InputStream is) {
- reader = new StreamReader(is);
- }
-
- /**
- * Parse the orientation from the image header. If it doesn't handle this image type (or this is
- * not an image) it will return a default value rather than throwing an exception.
- *
- * @return The exif orientation if present or -1 if the header couldn't be parsed or doesn't
- * contain an orientation
- * @throws IOException
- */
- public int getOrientation() throws IOException {
- final int magicNumber = reader.getUInt16();
-
- if (!handles(magicNumber)) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Parser doesn't handle magic number: " + magicNumber);
- }
- return UNKNOWN_ORIENTATION;
- } else {
- int exifSegmentLength = moveToExifSegmentAndGetLength();
- if (exifSegmentLength == -1) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Failed to parse exif segment length, or exif segment not found");
- }
- return UNKNOWN_ORIENTATION;
- }
-
- byte[] exifData = new byte[exifSegmentLength];
- return parseExifSegment(exifData, exifSegmentLength);
- }
- }
-
- private int parseExifSegment(byte[] tempArray, int exifSegmentLength) throws IOException {
- int read = reader.read(tempArray, exifSegmentLength);
- if (read != exifSegmentLength) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Unable to read exif segment data"
- + ", length: " + exifSegmentLength
- + ", actually read: " + read);
- }
- return UNKNOWN_ORIENTATION;
- }
-
- boolean hasJpegExifPreamble = hasJpegExifPreamble(tempArray, exifSegmentLength);
- if (hasJpegExifPreamble) {
- return parseExifSegment(new RandomAccessReader(tempArray, exifSegmentLength));
- } else {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Missing jpeg exif preamble");
- }
- return UNKNOWN_ORIENTATION;
- }
- }
-
- private boolean hasJpegExifPreamble(byte[] exifData, int exifSegmentLength) {
- boolean result =
- exifData != null && exifSegmentLength > JPEG_EXIF_SEGMENT_PREAMBLE_BYTES.length;
- if (result) {
- for (int i = 0; i < JPEG_EXIF_SEGMENT_PREAMBLE_BYTES.length; i++) {
- if (exifData[i] != JPEG_EXIF_SEGMENT_PREAMBLE_BYTES[i]) {
- result = false;
- break;
- }
- }
- }
- return result;
- }
-
- /**
- * Moves reader to the start of the exif segment and returns the length of the exif segment or
- * {@code -1} if no exif segment is found.
- */
- private int moveToExifSegmentAndGetLength() throws IOException {
- short segmentId, segmentType;
- int segmentLength;
- while (true) {
- segmentId = reader.getUInt8();
- if (segmentId != SEGMENT_START_ID) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Unknown segmentId=" + segmentId);
- }
- return -1;
- }
-
- segmentType = reader.getUInt8();
-
- if (segmentType == SEGMENT_SOS) {
- return -1;
- } else if (segmentType == MARKER_EOI) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Found MARKER_EOI in exif segment");
- }
- return -1;
- }
-
- // Segment length includes bytes for segment length.
- segmentLength = reader.getUInt16() - 2;
-
- if (segmentType != EXIF_SEGMENT_TYPE) {
- long skipped = reader.skip(segmentLength);
- if (skipped != segmentLength) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Unable to skip enough data"
- + ", type: " + segmentType
- + ", wanted to skip: " + segmentLength
- + ", but actually skipped: " + skipped);
- }
- return -1;
- }
- } else {
- return segmentLength;
- }
- }
- }
-
- private static int parseExifSegment(RandomAccessReader segmentData) {
- final int headerOffsetSize = JPEG_EXIF_SEGMENT_PREAMBLE.length();
-
- short byteOrderIdentifier = segmentData.getInt16(headerOffsetSize);
- final ByteOrder byteOrder;
- if (byteOrderIdentifier == MOTOROLA_TIFF_MAGIC_NUMBER) {
- byteOrder = ByteOrder.BIG_ENDIAN;
- } else if (byteOrderIdentifier == INTEL_TIFF_MAGIC_NUMBER) {
- byteOrder = ByteOrder.LITTLE_ENDIAN;
- } else {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Unknown endianness = " + byteOrderIdentifier);
- }
- byteOrder = ByteOrder.BIG_ENDIAN;
- }
-
- segmentData.order(byteOrder);
-
- int firstIfdOffset = segmentData.getInt32(headerOffsetSize + 4) + headerOffsetSize;
- int tagCount = segmentData.getInt16(firstIfdOffset);
-
- int tagOffset, tagType, formatCode, componentCount;
- for (int i = 0; i < tagCount; i++) {
- tagOffset = calcTagOffset(firstIfdOffset, i);
- tagType = segmentData.getInt16(tagOffset);
-
- // We only want orientation.
- if (tagType != ORIENTATION_TAG_TYPE) {
- continue;
- }
-
- formatCode = segmentData.getInt16(tagOffset + 2);
-
- // 12 is max format code.
- if (formatCode < 1 || formatCode > 12) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Got invalid format code = " + formatCode);
- }
- continue;
- }
-
- componentCount = segmentData.getInt32(tagOffset + 4);
-
- if (componentCount < 0) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Negative tiff component count");
- }
- continue;
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Got tagIndex=" + i + " tagType=" + tagType + " formatCode=" + formatCode
- + " componentCount=" + componentCount);
- }
-
- final int byteCount = componentCount + BYTES_PER_FORMAT[formatCode];
-
- if (byteCount > 4) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Got byte count > 4, not orientation, continuing, formatCode=" + formatCode);
- }
- continue;
- }
-
- final int tagValueOffset = tagOffset + 8;
-
- if (tagValueOffset < 0 || tagValueOffset > segmentData.length()) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Illegal tagValueOffset=" + tagValueOffset + " tagType=" + tagType);
- }
- continue;
- }
-
- if (byteCount < 0 || tagValueOffset + byteCount > segmentData.length()) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Illegal number of bytes for TI tag data tagType=" + tagType);
- }
- continue;
- }
-
- //assume componentCount == 1 && fmtCode == 3
- return segmentData.getInt16(tagValueOffset);
- }
-
- return -1;
- }
-
- private static int calcTagOffset(int ifdOffset, int tagIndex) {
- return ifdOffset + 2 + 12 * tagIndex;
- }
-
- private static boolean handles(int imageMagicNumber) {
- return (imageMagicNumber & EXIF_MAGIC_NUMBER) == EXIF_MAGIC_NUMBER
- || imageMagicNumber == MOTOROLA_TIFF_MAGIC_NUMBER
- || imageMagicNumber == INTEL_TIFF_MAGIC_NUMBER;
- }
-
- private static class RandomAccessReader {
- private final ByteBuffer data;
-
- public RandomAccessReader(byte[] data, int length) {
- this.data = (ByteBuffer) ByteBuffer.wrap(data)
- .order(ByteOrder.BIG_ENDIAN)
- .limit(length);
- }
-
- public void order(ByteOrder byteOrder) {
- this.data.order(byteOrder);
- }
-
- public int length() {
- return data.remaining();
- }
-
- public int getInt32(int offset) {
- return data.getInt(offset);
- }
-
- public short getInt16(int offset) {
- return data.getShort(offset);
- }
- }
-
- private interface Reader {
- int getUInt16() throws IOException;
-
- short getUInt8() throws IOException;
-
- long skip(long total) throws IOException;
-
- int read(byte[] buffer, int byteCount) throws IOException;
- }
-
- private static class StreamReader implements Reader {
- private final InputStream is;
-
- // Motorola / big endian byte order.
- public StreamReader(InputStream is) {
- this.is = is;
- }
-
- @Override
- public int getUInt16() throws IOException {
- return (is.read() << 8 & 0xFF00) | (is.read() & 0xFF);
- }
-
- @Override
- public short getUInt8() throws IOException {
- return (short) (is.read() & 0xFF);
- }
-
- @Override
- public long skip(long total) throws IOException {
- if (total < 0) {
- return 0;
- }
-
- long toSkip = total;
- while (toSkip > 0) {
- long skipped = is.skip(toSkip);
- if (skipped > 0) {
- toSkip -= skipped;
- } else {
- // Skip has no specific contract as to what happens when you reach the end of
- // the stream. To differentiate between temporarily not having more data and
- // having finished the stream, we read a single byte when we fail to skip any
- // amount of data.
- int testEofByte = is.read();
- if (testEofByte == -1) {
- break;
- } else {
- toSkip--;
- }
- }
- }
- return total - toSkip;
- }
-
- @Override
- public int read(byte[] buffer, int byteCount) throws IOException {
- int toRead = byteCount;
- int read;
- while (toRead > 0 && ((read = is.read(buffer, byteCount - toRead, toRead)) != -1)) {
- toRead -= read;
- }
- return byteCount - toRead;
- }
- }
-
- public static void copyExif(ExifInterface originalExif, int width, int height, String imageOutputPath) throws IOException {
- String[] attributes = new String[]{
- ExifInterface.TAG_APERTURE,
- ExifInterface.TAG_DATETIME,
- ExifInterface.TAG_DATETIME_DIGITIZED,
- ExifInterface.TAG_EXPOSURE_TIME,
- ExifInterface.TAG_FLASH,
- ExifInterface.TAG_FOCAL_LENGTH,
- ExifInterface.TAG_GPS_ALTITUDE,
- ExifInterface.TAG_GPS_ALTITUDE_REF,
- ExifInterface.TAG_GPS_DATESTAMP,
- ExifInterface.TAG_GPS_LATITUDE,
- ExifInterface.TAG_GPS_LATITUDE_REF,
- ExifInterface.TAG_GPS_LONGITUDE,
- ExifInterface.TAG_GPS_LONGITUDE_REF,
- ExifInterface.TAG_GPS_PROCESSING_METHOD,
- ExifInterface.TAG_GPS_TIMESTAMP,
- ExifInterface.TAG_ISO,
- ExifInterface.TAG_MAKE,
- ExifInterface.TAG_MODEL,
- ExifInterface.TAG_SUBSEC_TIME,
- ExifInterface.TAG_SUBSEC_TIME_DIG,
- ExifInterface.TAG_SUBSEC_TIME_ORIG,
- ExifInterface.TAG_WHITE_BALANCE
- };
-
- ExifInterface newExif = new ExifInterface(imageOutputPath);
- String value;
- for (String attribute : attributes) {
- value = originalExif.getAttribute(attribute);
- if (!TextUtils.isEmpty(value)) {
- newExif.setAttribute(attribute, value);
- }
- }
- newExif.setAttribute(ExifInterface.TAG_IMAGE_WIDTH, String.valueOf(width));
- newExif.setAttribute(ExifInterface.TAG_IMAGE_LENGTH, String.valueOf(height));
- newExif.setAttribute(ExifInterface.TAG_ORIENTATION, "0");
-
- newExif.saveAttributes();
- }
-
-}
-
diff --git a/library/src/main/java/com/yalantis/ucrop/util/RectUtils.java b/library/src/main/java/com/yalantis/ucrop/util/RectUtils.java
deleted file mode 100755
index 867f8e06..00000000
--- a/library/src/main/java/com/yalantis/ucrop/util/RectUtils.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.yalantis.ucrop.util;
-
-import android.graphics.RectF;
-
-public class RectUtils {
-
- /**
- * Gets a float array of the 2D coordinates representing a rectangles
- * corners.
- * The order of the corners in the float array is:
- * 0------->1
- * ^ |
- * | |
- * | v
- * 3<-------2
- *
- * @param r the rectangle to get the corners of
- * @return the float array of corners (8 floats)
- */
- public static float[] getCornersFromRect(RectF r) {
- return new float[]{
- r.left, r.top,
- r.right, r.top,
- r.right, r.bottom,
- r.left, r.bottom
- };
- }
-
- /**
- * Gets a float array of two lengths representing a rectangles width and height
- * The order of the corners in the input float array is:
- * 0------->1
- * ^ |
- * | |
- * | v
- * 3<-------2
- *
- * @param corners the float array of corners (8 floats)
- * @return the float array of width and height (2 floats)
- */
- public static float[] getRectSidesFromCorners(float[] corners) {
- return new float[]{(float) Math.sqrt(Math.pow(corners[0] - corners[2], 2) + Math.pow(corners[1] - corners[3], 2)),
- (float) Math.sqrt(Math.pow(corners[2] - corners[4], 2) + Math.pow(corners[3] - corners[5], 2))};
- }
-
- public static float[] getCenterFromRect(RectF r) {
- return new float[]{r.centerX(), r.centerY()};
- }
-
- /**
- * Takes an array of 2D coordinates representing corners and returns the
- * smallest rectangle containing those coordinates.
- *
- * @param array array of 2D coordinates
- * @return smallest rectangle containing coordinates
- */
- public static RectF trapToRect(float[] array) {
- RectF r = new RectF(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY,
- Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
- for (int i = 1; i < array.length; i += 2) {
- float x = array[i - 1];
- float y = array[i];
- r.left = (x < r.left) ? x : r.left;
- r.top = (y < r.top) ? y : r.top;
- r.right = (x > r.right) ? x : r.right;
- r.bottom = (y > r.bottom) ? y : r.bottom;
- }
- r.sort();
- return r;
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/util/RotationGestureDetector.java b/library/src/main/java/com/yalantis/ucrop/util/RotationGestureDetector.java
deleted file mode 100755
index 4fd8e5c3..00000000
--- a/library/src/main/java/com/yalantis/ucrop/util/RotationGestureDetector.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.yalantis.ucrop.util;
-
-import android.support.annotation.NonNull;
-import android.view.MotionEvent;
-
-public class RotationGestureDetector {
-
- private static final int INVALID_POINTER_INDEX = -1;
-
- private float fX, fY, sX, sY;
-
- private int mPointerIndex1, mPointerIndex2;
- private float mAngle;
- private boolean mIsFirstTouch;
-
- private OnRotationGestureListener mListener;
-
- public RotationGestureDetector(OnRotationGestureListener listener) {
- mListener = listener;
- mPointerIndex1 = INVALID_POINTER_INDEX;
- mPointerIndex2 = INVALID_POINTER_INDEX;
- }
-
- public float getAngle() {
- return mAngle;
- }
-
- public boolean onTouchEvent(@NonNull MotionEvent event) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- sX = event.getX();
- sY = event.getY();
- mPointerIndex1 = event.findPointerIndex(event.getPointerId(0));
- mAngle = 0;
- mIsFirstTouch = true;
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- fX = event.getX();
- fY = event.getY();
- mPointerIndex2 = event.findPointerIndex(event.getPointerId(event.getActionIndex()));
- mAngle = 0;
- mIsFirstTouch = true;
- break;
- case MotionEvent.ACTION_MOVE:
- if (mPointerIndex1 != INVALID_POINTER_INDEX && mPointerIndex2 != INVALID_POINTER_INDEX && event.getPointerCount() > mPointerIndex2) {
- float nfX, nfY, nsX, nsY;
-
- nsX = event.getX(mPointerIndex1);
- nsY = event.getY(mPointerIndex1);
- nfX = event.getX(mPointerIndex2);
- nfY = event.getY(mPointerIndex2);
-
- if (mIsFirstTouch) {
- mAngle = 0;
- mIsFirstTouch = false;
- } else {
- calculateAngleBetweenLines(fX, fY, sX, sY, nfX, nfY, nsX, nsY);
- }
-
- if (mListener != null) {
- mListener.onRotation(this);
- }
- fX = nfX;
- fY = nfY;
- sX = nsX;
- sY = nsY;
- }
- break;
- case MotionEvent.ACTION_UP:
- mPointerIndex1 = INVALID_POINTER_INDEX;
- break;
- case MotionEvent.ACTION_POINTER_UP:
- mPointerIndex2 = INVALID_POINTER_INDEX;
- break;
- }
- return true;
- }
-
- private float calculateAngleBetweenLines(float fx1, float fy1, float fx2, float fy2,
- float sx1, float sy1, float sx2, float sy2) {
- return calculateAngleDelta(
- (float) Math.toDegrees((float) Math.atan2((fy1 - fy2), (fx1 - fx2))),
- (float) Math.toDegrees((float) Math.atan2((sy1 - sy2), (sx1 - sx2))));
- }
-
- private float calculateAngleDelta(float angleFrom, float angleTo) {
- mAngle = angleTo % 360.0f - angleFrom % 360.0f;
-
- if (mAngle < -180.0f) {
- mAngle += 360.0f;
- } else if (mAngle > 180.0f) {
- mAngle -= 360.0f;
- }
-
- return mAngle;
- }
-
- public static class SimpleOnRotationGestureListener implements OnRotationGestureListener {
-
- @Override
- public boolean onRotation(RotationGestureDetector rotationDetector) {
- return false;
- }
- }
-
- public interface OnRotationGestureListener {
-
- boolean onRotation(RotationGestureDetector rotationDetector);
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/util/SelectedStateListDrawable.java b/library/src/main/java/com/yalantis/ucrop/util/SelectedStateListDrawable.java
deleted file mode 100755
index 825fec75..00000000
--- a/library/src/main/java/com/yalantis/ucrop/util/SelectedStateListDrawable.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.yalantis.ucrop.util;
-
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-
-/**
- * Hack class to properly support state drawable back to Android 1.6
- */
-public class SelectedStateListDrawable extends StateListDrawable {
-
- private int mSelectionColor;
-
- public SelectedStateListDrawable(Drawable drawable, int selectionColor) {
- super();
- this.mSelectionColor = selectionColor;
- addState(new int[]{android.R.attr.state_selected}, drawable);
- addState(new int[]{}, drawable);
- }
-
- @Override
- protected boolean onStateChange(int[] states) {
- boolean isStatePressedInArray = false;
- for (int state : states) {
- if (state == android.R.attr.state_selected) {
- isStatePressedInArray = true;
- }
- }
- if (isStatePressedInArray) {
- super.setColorFilter(mSelectionColor, PorterDuff.Mode.SRC_ATOP);
- } else {
- super.clearColorFilter();
- }
- return super.onStateChange(states);
- }
-
- @Override
- public boolean isStateful() {
- return true;
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/view/CropImageView.java b/library/src/main/java/com/yalantis/ucrop/view/CropImageView.java
deleted file mode 100755
index e19d2476..00000000
--- a/library/src/main/java/com/yalantis/ucrop/view/CropImageView.java
+++ /dev/null
@@ -1,622 +0,0 @@
-package com.yalantis.ucrop.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.AttributeSet;
-
-import com.yalantis.ucrop.callback.BitmapCropCallback;
-import com.yalantis.ucrop.callback.CropBoundsChangeListener;
-import com.yalantis.ucrop.model.CropParameters;
-import com.yalantis.ucrop.model.ImageState;
-import com.yalantis.ucrop.task.BitmapCropTask;
-import com.yalantis.ucrop.util.CubicEasing;
-import com.yalantis.ucrop.util.RectUtils;
-
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-
-import cn.finalteam.rxgalleryfinal.R;
-
-/**
- * Created by Oleksii Shliama (https://github.com/shliama).
- *
- * This class adds crop feature, methods to draw crop guidelines, and keep image in correct state.
- * Also it extends parent class methods to add checks for scale; animating zoom in/out.
- */
-public class CropImageView extends TransformImageView {
-
- public static final int DEFAULT_MAX_BITMAP_SIZE = 0;
- public static final int DEFAULT_IMAGE_TO_CROP_BOUNDS_ANIM_DURATION = 500;
- public static final float DEFAULT_MAX_SCALE_MULTIPLIER = 10.0f;
- public static final float SOURCE_IMAGE_ASPECT_RATIO = 0f;
- public static final float DEFAULT_ASPECT_RATIO = SOURCE_IMAGE_ASPECT_RATIO;
-
- private final RectF mCropRect = new RectF();
-
- private final Matrix mTempMatrix = new Matrix();
-
- private float mTargetAspectRatio;
- private float mMaxScaleMultiplier = DEFAULT_MAX_SCALE_MULTIPLIER;
-
- private CropBoundsChangeListener mCropBoundsChangeListener;
-
- private Runnable mWrapCropBoundsRunnable, mZoomImageToPositionRunnable = null;
-
- private float mMaxScale, mMinScale;
- private int mMaxResultImageSizeX = 0, mMaxResultImageSizeY = 0;
- private long mImageToWrapCropBoundsAnimDuration = DEFAULT_IMAGE_TO_CROP_BOUNDS_ANIM_DURATION;
-
- public CropImageView(Context context) {
- this(context, null);
- }
-
- public CropImageView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CropImageView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- /**
- * Cancels all current animations and sets image to fill crop area (without animation).
- * Then creates and executes {@link BitmapCropTask} with proper parameters.
- */
- public void cropAndSaveImage(@NonNull Bitmap.CompressFormat compressFormat, int compressQuality,
- @Nullable BitmapCropCallback cropCallback) {
- cancelAllAnimations();
- setImageToWrapCropBounds(false);
-
- final ImageState imageState = new ImageState(
- mCropRect, RectUtils.trapToRect(mCurrentImageCorners),
- getCurrentScale(), getCurrentAngle());
-
- final CropParameters cropParameters = new CropParameters(
- mMaxResultImageSizeX, mMaxResultImageSizeY,
- compressFormat, compressQuality,
- getImageInputPath(), getImageOutputPath(), getExifInfo());
-
- new BitmapCropTask(getViewBitmap(), imageState, cropParameters, cropCallback).execute();
- }
-
- /**
- * @return - maximum scale value for current image and crop ratio
- */
- public float getMaxScale() {
- return mMaxScale;
- }
-
- /**
- * @return - minimum scale value for current image and crop ratio
- */
- public float getMinScale() {
- return mMinScale;
- }
-
- /**
- * @return - aspect ratio for crop bounds
- */
- public float getTargetAspectRatio() {
- return mTargetAspectRatio;
- }
-
- /**
- * Updates current crop rectangle with given. Also recalculates image properties and position
- * to fit new crop rectangle.
- *
- * @param cropRect - new crop rectangle
- */
- public void setCropRect(RectF cropRect) {
- mCropRect.set(cropRect.left - getPaddingLeft(), cropRect.top - getPaddingTop(),
- cropRect.right - getPaddingRight(), cropRect.bottom - getPaddingBottom());
- calculateImageScaleBounds();
- setImageToWrapCropBounds();
- }
-
- /**
- * This method sets aspect ratio for crop bounds.
- * If {@link #SOURCE_IMAGE_ASPECT_RATIO} value is passed - aspect ratio is calculated
- * based on current image width and height.
- *
- * @param targetAspectRatio - aspect ratio for image crop (e.g. 1.77(7) for 16:9)
- */
- public void setTargetAspectRatio(float targetAspectRatio) {
- final Drawable drawable = getDrawable();
- if (drawable == null) {
- mTargetAspectRatio = targetAspectRatio;
- return;
- }
-
- if (targetAspectRatio == SOURCE_IMAGE_ASPECT_RATIO) {
- mTargetAspectRatio = drawable.getIntrinsicWidth() / (float) drawable.getIntrinsicHeight();
- } else {
- mTargetAspectRatio = targetAspectRatio;
- }
-
- if (mCropBoundsChangeListener != null) {
- mCropBoundsChangeListener.onCropAspectRatioChanged(mTargetAspectRatio);
- }
- }
-
- @Nullable
- public CropBoundsChangeListener getCropBoundsChangeListener() {
- return mCropBoundsChangeListener;
- }
-
- public void setCropBoundsChangeListener(@Nullable CropBoundsChangeListener cropBoundsChangeListener) {
- mCropBoundsChangeListener = cropBoundsChangeListener;
- }
-
- /**
- * This method sets maximum width for resulting cropped image
- *
- * @param maxResultImageSizeX - size in pixels
- */
- public void setMaxResultImageSizeX(@IntRange(from = 10) int maxResultImageSizeX) {
- mMaxResultImageSizeX = maxResultImageSizeX;
- }
-
- /**
- * This method sets maximum width for resulting cropped image
- *
- * @param maxResultImageSizeY - size in pixels
- */
- public void setMaxResultImageSizeY(@IntRange(from = 10) int maxResultImageSizeY) {
- mMaxResultImageSizeY = maxResultImageSizeY;
- }
-
- /**
- * This method sets animation duration for image to wrap the crop bounds
- *
- * @param imageToWrapCropBoundsAnimDuration - duration in milliseconds
- */
- public void setImageToWrapCropBoundsAnimDuration(@IntRange(from = 100) long imageToWrapCropBoundsAnimDuration) {
- if (imageToWrapCropBoundsAnimDuration > 0) {
- mImageToWrapCropBoundsAnimDuration = imageToWrapCropBoundsAnimDuration;
- } else {
- throw new IllegalArgumentException("Animation duration cannot be negative value.");
- }
- }
-
- /**
- * This method sets multiplier that is used to calculate max image scale from min image scale.
- *
- * @param maxScaleMultiplier - (minScale * maxScaleMultiplier) = maxScale
- */
- public void setMaxScaleMultiplier(float maxScaleMultiplier) {
- mMaxScaleMultiplier = maxScaleMultiplier;
- }
-
- /**
- * This method scales image down for given value related to image center.
- */
- public void zoomOutImage(float deltaScale) {
- zoomOutImage(deltaScale, mCropRect.centerX(), mCropRect.centerY());
- }
-
- /**
- * This method scales image down for given value related given coords (x, y).
- */
- public void zoomOutImage(float scale, float centerX, float centerY) {
- if (scale >= getMinScale()) {
- postScale(scale / getCurrentScale(), centerX, centerY);
- }
- }
-
- /**
- * This method scales image up for given value related to image center.
- */
- public void zoomInImage(float deltaScale) {
- zoomInImage(deltaScale, mCropRect.centerX(), mCropRect.centerY());
- }
-
- /**
- * This method scales image up for given value related to given coords (x, y).
- */
- public void zoomInImage(float scale, float centerX, float centerY) {
- if (scale <= getMaxScale()) {
- postScale(scale / getCurrentScale(), centerX, centerY);
- }
- }
-
- /**
- * This method changes image scale for given value related to point (px, py) but only if
- * resulting scale is in min/max bounds.
- *
- * @param deltaScale - scale value
- * @param px - scale center X
- * @param py - scale center Y
- */
- public void postScale(float deltaScale, float px, float py) {
- if (deltaScale > 1 && getCurrentScale() * deltaScale <= getMaxScale()) {
- super.postScale(deltaScale, px, py);
- } else if (deltaScale < 1 && getCurrentScale() * deltaScale >= getMinScale()) {
- super.postScale(deltaScale, px, py);
- }
- }
-
- /**
- * This method rotates image for given angle related to the image center.
- *
- * @param deltaAngle - angle to rotate
- */
- public void postRotate(float deltaAngle) {
- postRotate(deltaAngle, mCropRect.centerX(), mCropRect.centerY());
- }
-
- /**
- * This method cancels all current Runnable objects that represent animations.
- */
- public void cancelAllAnimations() {
- removeCallbacks(mWrapCropBoundsRunnable);
- removeCallbacks(mZoomImageToPositionRunnable);
- }
-
- public void setImageToWrapCropBounds() {
- setImageToWrapCropBounds(true);
- }
-
- /**
- * If image doesn't fill the crop bounds it must be translated and scaled properly to fill those.
- *
- * Therefore this method calculates delta X, Y and scale values and passes them to the
- * {@link WrapCropBoundsRunnable} which animates image.
- * Scale value must be calculated only if image won't fill the crop bounds after it's translated to the
- * crop bounds rectangle center. Using temporary variables this method checks this case.
- */
- public void setImageToWrapCropBounds(boolean animate) {
- if (mBitmapLaidOut && !isImageWrapCropBounds()) {
-
- float currentX = mCurrentImageCenter[0];
- float currentY = mCurrentImageCenter[1];
- float currentScale = getCurrentScale();
-
- float deltaX = mCropRect.centerX() - currentX;
- float deltaY = mCropRect.centerY() - currentY;
- float deltaScale = 0;
-
- mTempMatrix.reset();
- mTempMatrix.setTranslate(deltaX, deltaY);
-
- final float[] tempCurrentImageCorners = Arrays.copyOf(mCurrentImageCorners, mCurrentImageCorners.length);
- mTempMatrix.mapPoints(tempCurrentImageCorners);
-
- boolean willImageWrapCropBoundsAfterTranslate = isImageWrapCropBounds(tempCurrentImageCorners);
-
- if (willImageWrapCropBoundsAfterTranslate) {
- final float[] imageIndents = calculateImageIndents();
- deltaX = -(imageIndents[0] + imageIndents[2]);
- deltaY = -(imageIndents[1] + imageIndents[3]);
- } else {
- RectF tempCropRect = new RectF(mCropRect);
- mTempMatrix.reset();
- mTempMatrix.setRotate(getCurrentAngle());
- mTempMatrix.mapRect(tempCropRect);
-
- final float[] currentImageSides = RectUtils.getRectSidesFromCorners(mCurrentImageCorners);
-
- deltaScale = Math.max(tempCropRect.width() / currentImageSides[0],
- tempCropRect.height() / currentImageSides[1]);
- deltaScale = deltaScale * currentScale - currentScale;
- }
-
- if (animate) {
- post(mWrapCropBoundsRunnable = new WrapCropBoundsRunnable(
- CropImageView.this, mImageToWrapCropBoundsAnimDuration, currentX, currentY, deltaX, deltaY,
- currentScale, deltaScale, willImageWrapCropBoundsAfterTranslate));
- } else {
- postTranslate(deltaX, deltaY);
- if (!willImageWrapCropBoundsAfterTranslate) {
- zoomInImage(currentScale + deltaScale, mCropRect.centerX(), mCropRect.centerY());
- }
- }
- }
- }
-
- /**
- * First, un-rotate image and crop rectangles (make image rectangle axis-aligned).
- * Second, calculate deltas between those rectangles sides.
- * Third, depending on delta (its sign) put them or zero inside an array.
- * Fourth, using Matrix, rotate back those points (indents).
- *
- * @return - the float array of image indents (4 floats) - in this order [left, top, right, bottom]
- */
- private float[] calculateImageIndents() {
- mTempMatrix.reset();
- mTempMatrix.setRotate(-getCurrentAngle());
-
- float[] unrotatedImageCorners = Arrays.copyOf(mCurrentImageCorners, mCurrentImageCorners.length);
- float[] unrotatedCropBoundsCorners = RectUtils.getCornersFromRect(mCropRect);
-
- mTempMatrix.mapPoints(unrotatedImageCorners);
- mTempMatrix.mapPoints(unrotatedCropBoundsCorners);
-
- RectF unrotatedImageRect = RectUtils.trapToRect(unrotatedImageCorners);
- RectF unrotatedCropRect = RectUtils.trapToRect(unrotatedCropBoundsCorners);
-
- float deltaLeft = unrotatedImageRect.left - unrotatedCropRect.left;
- float deltaTop = unrotatedImageRect.top - unrotatedCropRect.top;
- float deltaRight = unrotatedImageRect.right - unrotatedCropRect.right;
- float deltaBottom = unrotatedImageRect.bottom - unrotatedCropRect.bottom;
-
- float indents[] = new float[4];
- indents[0] = (deltaLeft > 0) ? deltaLeft : 0;
- indents[1] = (deltaTop > 0) ? deltaTop : 0;
- indents[2] = (deltaRight < 0) ? deltaRight : 0;
- indents[3] = (deltaBottom < 0) ? deltaBottom : 0;
-
- mTempMatrix.reset();
- mTempMatrix.setRotate(getCurrentAngle());
- mTempMatrix.mapPoints(indents);
-
- return indents;
- }
-
- /**
- * When image is laid out it must be centered properly to fit current crop bounds.
- */
- @Override
- protected void onImageLaidOut() {
- super.onImageLaidOut();
- final Drawable drawable = getDrawable();
- if (drawable == null) {
- return;
- }
-
- float drawableWidth = drawable.getIntrinsicWidth();
- float drawableHeight = drawable.getIntrinsicHeight();
-
- if (mTargetAspectRatio == SOURCE_IMAGE_ASPECT_RATIO) {
- mTargetAspectRatio = drawableWidth / drawableHeight;
- }
-
- int height = (int) (mThisWidth / mTargetAspectRatio);
- if (height > mThisHeight) {
- int width = (int) (mThisHeight * mTargetAspectRatio);
- int halfDiff = (mThisWidth - width) / 2;
- mCropRect.set(halfDiff, 0, width + halfDiff, mThisHeight);
- } else {
- int halfDiff = (mThisHeight - height) / 2;
- mCropRect.set(0, halfDiff, mThisWidth, height + halfDiff);
- }
-
- calculateImageScaleBounds(drawableWidth, drawableHeight);
- setupInitialImagePosition(drawableWidth, drawableHeight);
-
- if (mCropBoundsChangeListener != null) {
- mCropBoundsChangeListener.onCropAspectRatioChanged(mTargetAspectRatio);
- }
- if (mTransformImageListener != null) {
- mTransformImageListener.onScale(getCurrentScale());
- mTransformImageListener.onRotate(getCurrentAngle());
- }
- }
-
- /**
- * This method checks whether current image fills the crop bounds.
- */
- protected boolean isImageWrapCropBounds() {
- return isImageWrapCropBounds(mCurrentImageCorners);
- }
-
- /**
- * This methods checks whether a rectangle that is represented as 4 corner points (8 floats)
- * fills the crop bounds rectangle.
- *
- * @param imageCorners - corners of a rectangle
- * @return - true if it wraps crop bounds, false - otherwise
- */
- protected boolean isImageWrapCropBounds(float[] imageCorners) {
- mTempMatrix.reset();
- mTempMatrix.setRotate(-getCurrentAngle());
-
- float[] unrotatedImageCorners = Arrays.copyOf(imageCorners, imageCorners.length);
- mTempMatrix.mapPoints(unrotatedImageCorners);
-
- float[] unrotatedCropBoundsCorners = RectUtils.getCornersFromRect(mCropRect);
- mTempMatrix.mapPoints(unrotatedCropBoundsCorners);
-
- return RectUtils.trapToRect(unrotatedImageCorners).contains(RectUtils.trapToRect(unrotatedCropBoundsCorners));
- }
-
- /**
- * This method changes image scale (animating zoom for given duration), related to given center (x,y).
- *
- * @param scale - target scale
- * @param centerX - scale center X
- * @param centerY - scale center Y
- * @param durationMs - zoom animation duration
- */
- protected void zoomImageToPosition(float scale, float centerX, float centerY, long durationMs) {
- if (scale > getMaxScale()) {
- scale = getMaxScale();
- }
-
- final float oldScale = getCurrentScale();
- final float deltaScale = scale - oldScale;
-
- post(mZoomImageToPositionRunnable = new ZoomImageToPosition(CropImageView.this,
- durationMs, oldScale, deltaScale, centerX, centerY));
- }
-
- private void calculateImageScaleBounds() {
- final Drawable drawable = getDrawable();
- if (drawable == null) {
- return;
- }
- calculateImageScaleBounds(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
- }
-
- /**
- * This method calculates image minimum and maximum scale values for current {@link #mCropRect}.
- *
- * @param drawableWidth - image width
- * @param drawableHeight - image height
- */
- private void calculateImageScaleBounds(float drawableWidth, float drawableHeight) {
- float widthScale = mCropRect.width() / drawableWidth;
- float heightScale = mCropRect.height() / drawableHeight;
-
- mMinScale = Math.max(widthScale, heightScale);
- mMaxScale = mMinScale * mMaxScaleMultiplier;
- }
-
- /**
- * This method calculates initial image position so it is positioned properly.
- * Then it sets those values to the current image matrix.
- *
- * @param drawableWidth - image width
- * @param drawableHeight - image height
- */
- private void setupInitialImagePosition(float drawableWidth, float drawableHeight) {
- float cropRectWidth = mCropRect.width();
- float cropRectHeight = mCropRect.height();
-
- float tw = (cropRectWidth - drawableWidth * mMinScale) / 2.0f + mCropRect.left;
- float th = (cropRectHeight - drawableHeight * mMinScale) / 2.0f + mCropRect.top;
-
- mCurrentImageMatrix.reset();
- mCurrentImageMatrix.postScale(mMinScale, mMinScale);
- mCurrentImageMatrix.postTranslate(tw, th);
- setImageMatrix(mCurrentImageMatrix);
- }
-
- /**
- * This method extracts all needed values from the styled attributes.
- * Those are used to configure the view.
- */
- @SuppressWarnings("deprecation")
- protected void processStyledAttributes(@NonNull TypedArray a) {
- float targetAspectRatioX = Math.abs(a.getFloat(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_aspect_ratio_x, DEFAULT_ASPECT_RATIO));
- float targetAspectRatioY = Math.abs(a.getFloat(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_aspect_ratio_y, DEFAULT_ASPECT_RATIO));
-
- if (targetAspectRatioX == SOURCE_IMAGE_ASPECT_RATIO || targetAspectRatioY == SOURCE_IMAGE_ASPECT_RATIO) {
- mTargetAspectRatio = SOURCE_IMAGE_ASPECT_RATIO;
- } else {
- mTargetAspectRatio = targetAspectRatioX / targetAspectRatioY;
- }
- }
-
- /**
- * This Runnable is used to animate an image so it fills the crop bounds entirely.
- * Given values are interpolated during the animation time.
- * Runnable can be terminated either vie {@link #cancelAllAnimations()} method
- * or when certain conditions inside {@link WrapCropBoundsRunnable#run()} method are triggered.
- */
- private static class WrapCropBoundsRunnable implements Runnable {
-
- private final WeakReference mCropImageView;
-
- private final long mDurationMs, mStartTime;
- private final float mOldX, mOldY;
- private final float mCenterDiffX, mCenterDiffY;
- private final float mOldScale;
- private final float mDeltaScale;
- private final boolean mWillBeImageInBoundsAfterTranslate;
-
- public WrapCropBoundsRunnable(CropImageView cropImageView,
- long durationMs,
- float oldX, float oldY,
- float centerDiffX, float centerDiffY,
- float oldScale, float deltaScale,
- boolean willBeImageInBoundsAfterTranslate) {
-
- mCropImageView = new WeakReference<>(cropImageView);
-
- mDurationMs = durationMs;
- mStartTime = System.currentTimeMillis();
- mOldX = oldX;
- mOldY = oldY;
- mCenterDiffX = centerDiffX;
- mCenterDiffY = centerDiffY;
- mOldScale = oldScale;
- mDeltaScale = deltaScale;
- mWillBeImageInBoundsAfterTranslate = willBeImageInBoundsAfterTranslate;
- }
-
- @Override
- public void run() {
- CropImageView cropImageView = mCropImageView.get();
- if (cropImageView == null) {
- return;
- }
-
- long now = System.currentTimeMillis();
- float currentMs = Math.min(mDurationMs, now - mStartTime);
-
- float newX = CubicEasing.easeOut(currentMs, 0, mCenterDiffX, mDurationMs);
- float newY = CubicEasing.easeOut(currentMs, 0, mCenterDiffY, mDurationMs);
- float newScale = CubicEasing.easeInOut(currentMs, 0, mDeltaScale, mDurationMs);
-
- if (currentMs < mDurationMs) {
- cropImageView.postTranslate(newX - (cropImageView.mCurrentImageCenter[0] - mOldX), newY - (cropImageView.mCurrentImageCenter[1] - mOldY));
- if (!mWillBeImageInBoundsAfterTranslate) {
- cropImageView.zoomInImage(mOldScale + newScale, cropImageView.mCropRect.centerX(), cropImageView.mCropRect.centerY());
- }
- if (!cropImageView.isImageWrapCropBounds()) {
- cropImageView.post(this);
- }
- }
- }
- }
-
- /**
- * This Runnable is used to animate an image zoom.
- * Given values are interpolated during the animation time.
- * Runnable can be terminated either vie {@link #cancelAllAnimations()} method
- * or when certain conditions inside {@link ZoomImageToPosition#run()} method are triggered.
- */
- private static class ZoomImageToPosition implements Runnable {
-
- private final WeakReference mCropImageView;
-
- private final long mDurationMs, mStartTime;
- private final float mOldScale;
- private final float mDeltaScale;
- private final float mDestX;
- private final float mDestY;
-
- public ZoomImageToPosition(CropImageView cropImageView,
- long durationMs,
- float oldScale, float deltaScale,
- float destX, float destY) {
-
- mCropImageView = new WeakReference<>(cropImageView);
-
- mStartTime = System.currentTimeMillis();
- mDurationMs = durationMs;
- mOldScale = oldScale;
- mDeltaScale = deltaScale;
- mDestX = destX;
- mDestY = destY;
- }
-
- @Override
- public void run() {
- CropImageView cropImageView = mCropImageView.get();
- if (cropImageView == null) {
- return;
- }
-
- long now = System.currentTimeMillis();
- float currentMs = Math.min(mDurationMs, now - mStartTime);
- float newScale = CubicEasing.easeInOut(currentMs, 0, mDeltaScale, mDurationMs);
-
- if (currentMs < mDurationMs) {
- cropImageView.zoomInImage(mOldScale + newScale, mDestX, mDestY);
- cropImageView.post(this);
- } else {
- cropImageView.setImageToWrapCropBounds();
- }
- }
-
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/view/GestureCropImageView.java b/library/src/main/java/com/yalantis/ucrop/view/GestureCropImageView.java
deleted file mode 100755
index b0f3cff9..00000000
--- a/library/src/main/java/com/yalantis/ucrop/view/GestureCropImageView.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.yalantis.ucrop.view;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-
-import com.yalantis.ucrop.util.RotationGestureDetector;
-
-/**
- * Created by Oleksii Shliama (https://github.com/shliama).
- */
-public class GestureCropImageView extends CropImageView {
-
- private static final int DOUBLE_TAP_ZOOM_DURATION = 200;
-
- private ScaleGestureDetector mScaleDetector;
- private RotationGestureDetector mRotateDetector;
- private GestureDetector mGestureDetector;
-
- private float mMidPntX, mMidPntY;
-
- private boolean mIsRotateEnabled = true, mIsScaleEnabled = true;
- private int mDoubleTapScaleSteps = 5;
-
- public GestureCropImageView(Context context) {
- super(context);
- }
-
- public GestureCropImageView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public GestureCropImageView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public void setScaleEnabled(boolean scaleEnabled) {
- mIsScaleEnabled = scaleEnabled;
- }
-
- public boolean isScaleEnabled() {
- return mIsScaleEnabled;
- }
-
- public void setRotateEnabled(boolean rotateEnabled) {
- mIsRotateEnabled = rotateEnabled;
- }
-
- public boolean isRotateEnabled() {
- return mIsRotateEnabled;
- }
-
- public void setDoubleTapScaleSteps(int doubleTapScaleSteps) {
- mDoubleTapScaleSteps = doubleTapScaleSteps;
- }
-
- public int getDoubleTapScaleSteps() {
- return mDoubleTapScaleSteps;
- }
-
- /**
- * If it's ACTION_DOWN event - user touches the screen and all current animation must be canceled.
- * If it's ACTION_UP event - user removed all fingers from the screen and current image position must be corrected.
- * If there are more than 2 fingers - update focal point coordinates.
- * Pass the event to the gesture detectors if those are enabled.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
- cancelAllAnimations();
- }
-
- if (event.getPointerCount() > 1) {
- mMidPntX = (event.getX(0) + event.getX(1)) / 2;
- mMidPntY = (event.getY(0) + event.getY(1)) / 2;
- }
-
- mGestureDetector.onTouchEvent(event);
-
- if (mIsScaleEnabled) {
- mScaleDetector.onTouchEvent(event);
- }
-
- if (mIsRotateEnabled) {
- mRotateDetector.onTouchEvent(event);
- }
-
- if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
- setImageToWrapCropBounds();
- }
- return true;
- }
-
- @Override
- protected void init() {
- super.init();
- setupGestureListeners();
- }
-
- /**
- * This method calculates target scale value for double tap gesture.
- * User is able to zoom the image from min scale value
- * to the max scale value with {@link #mDoubleTapScaleSteps} double taps.
- */
- protected float getDoubleTapTargetScale() {
- return getCurrentScale() * (float) Math.pow(getMaxScale() / getMinScale(), 1.0f / mDoubleTapScaleSteps);
- }
-
- private void setupGestureListeners() {
- mGestureDetector = new GestureDetector(getContext(), new GestureListener(), null, true);
- mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
- mRotateDetector = new RotationGestureDetector(new RotateListener());
- }
-
- private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
-
- @Override
- public boolean onScale(ScaleGestureDetector detector) {
- postScale(detector.getScaleFactor(), mMidPntX, mMidPntY);
- return true;
- }
- }
-
- private class GestureListener extends GestureDetector.SimpleOnGestureListener {
-
- @Override
- public boolean onDoubleTap(MotionEvent e) {
- zoomImageToPosition(getDoubleTapTargetScale(), e.getX(), e.getY(), DOUBLE_TAP_ZOOM_DURATION);
- return super.onDoubleTap(e);
- }
-
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- postTranslate(-distanceX, -distanceY);
- return true;
- }
-
- }
-
- private class RotateListener extends RotationGestureDetector.SimpleOnRotationGestureListener {
-
- @Override
- public boolean onRotation(RotationGestureDetector rotationDetector) {
- postRotate(rotationDetector.getAngle(), mMidPntX, mMidPntY);
- return true;
- }
-
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/view/OverlayView.java b/library/src/main/java/com/yalantis/ucrop/view/OverlayView.java
deleted file mode 100755
index 31cff934..00000000
--- a/library/src/main/java/com/yalantis/ucrop/view/OverlayView.java
+++ /dev/null
@@ -1,485 +0,0 @@
-package com.yalantis.ucrop.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.graphics.Region;
-import android.os.Build;
-import android.support.annotation.ColorInt;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.yalantis.ucrop.callback.OverlayViewChangeListener;
-import com.yalantis.ucrop.util.RectUtils;
-
-import cn.finalteam.rxgalleryfinal.R;
-
-/**
- * Created by Oleksii Shliama (https://github.com/shliama).
- *
- * This view is used for drawing the overlay on top of the image. It may have frame, crop guidelines and dimmed area.
- * This must have LAYER_TYPE_SOFTWARE to draw itself properly.
- */
-public class OverlayView extends View {
-
- public static final boolean DEFAULT_SHOW_CROP_FRAME = true;
- public static final boolean DEFAULT_SHOW_CROP_GRID = true;
- public static final boolean DEFAULT_OVAL_DIMMED_LAYER = false;
- public static final boolean DEFAULT_FREESTYLE_CROP_ENABLED = false;
- public static final int DEFAULT_CROP_GRID_ROW_COUNT = 2;
- public static final int DEFAULT_CROP_GRID_COLUMN_COUNT = 2;
-
- private final RectF mCropViewRect = new RectF();
- private final RectF mTempRect = new RectF();
-
- private int mCropGridRowCount, mCropGridColumnCount;
- private float mTargetAspectRatio;
- private float[] mGridPoints = null;
- private boolean mShowCropFrame, mShowCropGrid;
- private boolean mOvalDimmedLayer;
- private int mDimmedColor;
- private Path mCircularPath = new Path();
- private Paint mDimmedStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private Paint mCropGridPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private Paint mCropFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private Paint mCropFrameCornersPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-
- protected int mThisWidth, mThisHeight;
-
- private boolean mIsFreestyleCropEnabled = DEFAULT_FREESTYLE_CROP_ENABLED;
- protected float[] mCropGridCorners;
- private int mCurrentTouchCornerIndex = -1;
- private int mTouchPointThreshold;
- private int mCropRectMinSize;
- private int mCropRectCornerTouchAreaLineLength;
-
- private OverlayViewChangeListener mCallback;
-
- {
- mTouchPointThreshold = getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_rect_corner_touch_threshold);
- mCropRectMinSize = getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_rect_min_size);
- mCropRectCornerTouchAreaLineLength = getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_rect_corner_touch_area_line_length);
- }
-
- public OverlayView(Context context) {
- this(context, null);
- }
-
- public OverlayView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public OverlayView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- public OverlayViewChangeListener getOverlayViewChangeListener() {
- return mCallback;
- }
-
- public void setOverlayViewChangeListener(OverlayViewChangeListener callback) {
- mCallback = callback;
- }
-
- @NonNull
- public RectF getCropViewRect() {
- return mCropViewRect;
- }
-
- public boolean isFreestyleCropEnabled() {
- return mIsFreestyleCropEnabled;
- }
-
- public void setFreestyleCropEnabled(boolean freestyleCropEnabled) {
- mIsFreestyleCropEnabled = freestyleCropEnabled;
- }
-
- /**
- * Setter for {@link #mOvalDimmedLayer} variable.
- *
- * @param ovalDimmedLayer - set it to true if you want dimmed layer to be an oval
- */
- public void setOvalDimmedLayer(boolean ovalDimmedLayer) {
- mOvalDimmedLayer = ovalDimmedLayer;
- }
-
- /**
- * Setter for crop grid rows count.
- * Resets {@link #mGridPoints} variable because it is not valid anymore.
- */
- public void setCropGridRowCount(@IntRange(from = 0) int cropGridRowCount) {
- mCropGridRowCount = cropGridRowCount;
- mGridPoints = null;
- }
-
- /**
- * Setter for crop grid columns count.
- * Resets {@link #mGridPoints} variable because it is not valid anymore.
- */
- public void setCropGridColumnCount(@IntRange(from = 0) int cropGridColumnCount) {
- mCropGridColumnCount = cropGridColumnCount;
- mGridPoints = null;
- }
-
- /**
- * Setter for {@link #mShowCropFrame} variable.
- *
- * @param showCropFrame - set to true if you want to see a crop frame rectangle on top of an image
- */
- public void setShowCropFrame(boolean showCropFrame) {
- mShowCropFrame = showCropFrame;
- }
-
- /**
- * Setter for {@link #mShowCropGrid} variable.
- *
- * @param showCropGrid - set to true if you want to see a crop grid on top of an image
- */
- public void setShowCropGrid(boolean showCropGrid) {
- mShowCropGrid = showCropGrid;
- }
-
- /**
- * Setter for {@link #mDimmedColor} variable.
- *
- * @param dimmedColor - desired color of dimmed area around the crop bounds
- */
- public void setDimmedColor(@ColorInt int dimmedColor) {
- mDimmedColor = dimmedColor;
- }
-
- /**
- * Setter for crop frame stroke width
- */
- public void setCropFrameStrokeWidth(@IntRange(from = 0) int width) {
- mCropFramePaint.setStrokeWidth(width);
- }
-
- /**
- * Setter for crop grid stroke width
- */
- public void setCropGridStrokeWidth(@IntRange(from = 0) int width) {
- mCropGridPaint.setStrokeWidth(width);
- }
-
- /**
- * Setter for crop frame color
- */
- public void setCropFrameColor(@ColorInt int color) {
- mCropFramePaint.setColor(color);
- }
-
- /**
- * Setter for crop grid color
- */
- public void setCropGridColor(@ColorInt int color) {
- mCropGridPaint.setColor(color);
- }
-
- /**
- * This method sets aspect ratio for crop bounds.
- *
- * @param targetAspectRatio - aspect ratio for image crop (e.g. 1.77(7) for 16:9)
- */
- public void setTargetAspectRatio(float targetAspectRatio) {
- mTargetAspectRatio = targetAspectRatio;
- setupCropBounds();
- postInvalidate();
- }
-
- /**
- * This method setups crop bounds rectangles for given aspect ratio and view size.
- * {@link #mCropViewRect} is used to draw crop bounds - uses padding.
- */
- public void setupCropBounds() {
- int height = (int) (mThisWidth / mTargetAspectRatio);
- if (height > mThisHeight) {
- int width = (int) (mThisHeight * mTargetAspectRatio);
- int halfDiff = (mThisWidth - width) / 2;
- mCropViewRect.set(getPaddingLeft() + halfDiff, getPaddingTop(),
- getPaddingLeft() + width + halfDiff, getPaddingTop() + mThisHeight);
- } else {
- int halfDiff = (mThisHeight - height) / 2;
- mCropViewRect.set(getPaddingLeft(), getPaddingTop() + halfDiff,
- getPaddingLeft() + mThisWidth, getPaddingTop() + height + halfDiff);
- }
-
- if (mCallback != null) {
- mCallback.onCropRectUpdated(mCropViewRect);
- }
-
- updateGridPoints();
- }
-
- private void updateGridPoints() {
- mCropGridCorners = RectUtils.getCornersFromRect(mCropViewRect);
-
- mGridPoints = null;
- mCircularPath.reset();
- mCircularPath.addOval(mCropViewRect, Path.Direction.CW);
- }
-
- protected void init() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 &&
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- setLayerType(LAYER_TYPE_SOFTWARE, null);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (changed) {
- left = getPaddingLeft();
- top = getPaddingTop();
- right = getWidth() - getPaddingRight();
- bottom = getHeight() - getPaddingBottom();
- mThisWidth = right - left;
- mThisHeight = bottom - top;
- }
- }
-
- /**
- * Along with image there are dimmed layer, crop bounds and crop guidelines that must be drawn.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- drawDimmedLayer(canvas);
- drawCropGrid(canvas);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (mCropViewRect.isEmpty() || !mIsFreestyleCropEnabled) return false;
-
- float x = event.getX();
- float y = event.getY();
-
- if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
- mCurrentTouchCornerIndex = getCurrentTouchCorner(x, y);
- return mCurrentTouchCornerIndex != -1;
- }
-
- if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE) {
- if (event.getPointerCount() == 1 && mCurrentTouchCornerIndex != -1) {
-
- x = Math.min(Math.max(x, getPaddingLeft()), getWidth() - getPaddingRight());
- y = Math.min(Math.max(y, getPaddingTop()), getHeight() - getPaddingBottom());
-
- resizeCropViewRect(x, y);
-
- return true;
- }
- }
-
- if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
- mCurrentTouchCornerIndex = -1;
- if (mCallback != null) {
- mCallback.onCropRectUpdated(mCropViewRect);
- }
- }
-
- return false;
- }
-
- /**
- * * The order of the corners is:
- * 0------->1
- * ^ |
- * | |
- * | v
- * 3<-------2
- */
- private void resizeCropViewRect(float touchX, float touchY) {
- mTempRect.set(mCropViewRect);
-
- switch (mCurrentTouchCornerIndex) {
- case 0:
- mTempRect.set(touchX, touchY, mCropViewRect.right, mCropViewRect.bottom);
- break;
- case 1:
- mTempRect.set(mCropViewRect.left, touchY, touchX, mCropViewRect.bottom);
- break;
- case 2:
- mTempRect.set(mCropViewRect.left, mCropViewRect.top, touchX, touchY);
- break;
- case 3:
- mTempRect.set(touchX, mCropViewRect.top, mCropViewRect.right, touchY);
- break;
- }
-
- boolean changeHeight = mTempRect.height() >= mCropRectMinSize;
- boolean changeWidth = mTempRect.width() >= mCropRectMinSize;
- mCropViewRect.set(
- changeWidth ? mTempRect.left : mCropViewRect.left,
- changeHeight ? mTempRect.top : mCropViewRect.top,
- changeWidth ? mTempRect.right : mCropViewRect.right,
- changeHeight ? mTempRect.bottom : mCropViewRect.bottom);
-
- if (changeHeight || changeWidth) {
- updateGridPoints();
- postInvalidate();
- }
- }
-
- /**
- * * The order of the corners in the float array is:
- * 0------->1
- * ^ |
- * | |
- * | v
- * 3<-------2
- *
- * @return - index of corner that is being dragged
- */
- private int getCurrentTouchCorner(float touchX, float touchY) {
- int closestPointIndex = -1;
- double closestPointDistance = mTouchPointThreshold;
- for (int i = 0; i < 8; i += 2) {
- double distanceToCorner = Math.sqrt(Math.pow(touchX - mCropGridCorners[i], 2)
- + Math.pow(touchY - mCropGridCorners[i + 1], 2));
- if (distanceToCorner < closestPointDistance) {
- closestPointDistance = distanceToCorner;
- closestPointIndex = i / 2;
- }
- }
- return closestPointIndex;
- }
-
- /**
- * This method draws dimmed area around the crop bounds.
- *
- * @param canvas - valid canvas object
- */
- protected void drawDimmedLayer(@NonNull Canvas canvas) {
- canvas.save();
- if (mOvalDimmedLayer) {
- canvas.clipPath(mCircularPath, Region.Op.DIFFERENCE);
- } else {
- canvas.clipRect(mCropViewRect, Region.Op.DIFFERENCE);
- }
- canvas.drawColor(mDimmedColor);
- canvas.restore();
-
- if (mOvalDimmedLayer) { // Draw 1px stroke to fix antialias
- canvas.drawOval(mCropViewRect, mDimmedStrokePaint);
- }
- }
-
- /**
- * This method draws crop bounds (empty rectangle)
- * and crop guidelines (vertical and horizontal lines inside the crop bounds) if needed.
- *
- * @param canvas - valid canvas object
- */
- protected void drawCropGrid(@NonNull Canvas canvas) {
- if (mShowCropGrid) {
- if (mGridPoints == null && !mCropViewRect.isEmpty()) {
-
- mGridPoints = new float[(mCropGridRowCount) * 4 + (mCropGridColumnCount) * 4];
-
- int index = 0;
- for (int i = 0; i < mCropGridRowCount; i++) {
- mGridPoints[index++] = mCropViewRect.left;
- mGridPoints[index++] = (mCropViewRect.height() * (((float) i + 1.0f) / (float) (mCropGridRowCount + 1))) + mCropViewRect.top;
- mGridPoints[index++] = mCropViewRect.right;
- mGridPoints[index++] = (mCropViewRect.height() * (((float) i + 1.0f) / (float) (mCropGridRowCount + 1))) + mCropViewRect.top;
- }
-
- for (int i = 0; i < mCropGridColumnCount; i++) {
- mGridPoints[index++] = (mCropViewRect.width() * (((float) i + 1.0f) / (float) (mCropGridColumnCount + 1))) + mCropViewRect.left;
- mGridPoints[index++] = mCropViewRect.top;
- mGridPoints[index++] = (mCropViewRect.width() * (((float) i + 1.0f) / (float) (mCropGridColumnCount + 1))) + mCropViewRect.left;
- mGridPoints[index++] = mCropViewRect.bottom;
- }
- }
-
- if (mGridPoints != null) {
- canvas.drawLines(mGridPoints, mCropGridPaint);
- }
- }
-
- if (mShowCropFrame) {
- canvas.drawRect(mCropViewRect, mCropFramePaint);
- }
-
- if (mIsFreestyleCropEnabled) {
- canvas.save();
-
- mTempRect.set(mCropViewRect);
- mTempRect.inset(mCropRectCornerTouchAreaLineLength, -mCropRectCornerTouchAreaLineLength);
- canvas.clipRect(mTempRect, Region.Op.DIFFERENCE);
-
- mTempRect.set(mCropViewRect);
- mTempRect.inset(-mCropRectCornerTouchAreaLineLength, mCropRectCornerTouchAreaLineLength);
- canvas.clipRect(mTempRect, Region.Op.DIFFERENCE);
-
- canvas.drawRect(mCropViewRect, mCropFrameCornersPaint);
-
- canvas.restore();
- }
- }
-
- /**
- * This method extracts all needed values from the styled attributes.
- * Those are used to configure the view.
- */
- @SuppressWarnings("deprecation")
- protected void processStyledAttributes(@NonNull TypedArray a) {
- mOvalDimmedLayer = a.getBoolean(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_oval_dimmed_layer, DEFAULT_OVAL_DIMMED_LAYER);
- mDimmedColor = a.getColor(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_dimmed_color,
- getResources().getColor(R.color.gallery_default_ucrop_color_default_dimmed));
- mDimmedStrokePaint.setColor(mDimmedColor);
- mDimmedStrokePaint.setStyle(Paint.Style.STROKE);
- mDimmedStrokePaint.setStrokeWidth(1);
-
- initCropFrameStyle(a);
- mShowCropFrame = a.getBoolean(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_show_frame, DEFAULT_SHOW_CROP_FRAME);
-
- initCropGridStyle(a);
- mShowCropGrid = a.getBoolean(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_show_grid, DEFAULT_SHOW_CROP_GRID);
- }
-
- /**
- * This method setups Paint object for the crop bounds.
- */
- @SuppressWarnings("deprecation")
- private void initCropFrameStyle(@NonNull TypedArray a) {
- int cropFrameStrokeSize = a.getDimensionPixelSize(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_frame_stroke_size,
- getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_frame_stroke_width));
- int cropFrameColor = a.getColor(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_frame_color,
- getResources().getColor(R.color.gallery_default_ucrop_color_default_crop_frame));
- mCropFramePaint.setStrokeWidth(cropFrameStrokeSize);
- mCropFramePaint.setColor(cropFrameColor);
- mCropFramePaint.setStyle(Paint.Style.STROKE);
-
- mCropFrameCornersPaint.setStrokeWidth(cropFrameStrokeSize * 3);
- mCropFrameCornersPaint.setColor(cropFrameColor);
- mCropFrameCornersPaint.setStyle(Paint.Style.STROKE);
- }
-
- /**
- * This method setups Paint object for the crop guidelines.
- */
- @SuppressWarnings("deprecation")
- private void initCropGridStyle(@NonNull TypedArray a) {
- int cropGridStrokeSize = a.getDimensionPixelSize(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_grid_stroke_size,
- getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_default_crop_grid_stroke_width));
- int cropGridColor = a.getColor(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_grid_color,
- getResources().getColor(R.color.gallery_default_ucrop_color_default_crop_grid));
- mCropGridPaint.setStrokeWidth(cropGridStrokeSize);
- mCropGridPaint.setColor(cropGridColor);
-
- mCropGridRowCount = a.getInt(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_grid_row_count, DEFAULT_CROP_GRID_ROW_COUNT);
- mCropGridColumnCount = a.getInt(R.styleable.gallery_ucrop_UCropView_gallery_ucrop_grid_column_count, DEFAULT_CROP_GRID_COLUMN_COUNT);
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/view/TransformImageView.java b/library/src/main/java/com/yalantis/ucrop/view/TransformImageView.java
deleted file mode 100755
index 869ea289..00000000
--- a/library/src/main/java/com/yalantis/ucrop/view/TransformImageView.java
+++ /dev/null
@@ -1,338 +0,0 @@
-package com.yalantis.ucrop.view;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.widget.ImageView;
-
-import com.yalantis.ucrop.callback.BitmapLoadCallback;
-import com.yalantis.ucrop.model.ExifInfo;
-import com.yalantis.ucrop.util.BitmapLoadUtils;
-import com.yalantis.ucrop.util.FastBitmapDrawable;
-import com.yalantis.ucrop.util.RectUtils;
-
-/**
- * Created by Oleksii Shliama (https://github.com/shliama).
- *
- * This class provides base logic to setup the image, transform it with matrix (move, scale, rotate),
- * and methods to get current matrix state.
- */
-public class TransformImageView extends ImageView {
-
- private static final String TAG = "TransformImageView";
-
- private static final int RECT_CORNER_POINTS_COORDS = 8;
- private static final int RECT_CENTER_POINT_COORDS = 2;
- private static final int MATRIX_VALUES_COUNT = 9;
-
- protected final float[] mCurrentImageCorners = new float[RECT_CORNER_POINTS_COORDS];
- protected final float[] mCurrentImageCenter = new float[RECT_CENTER_POINT_COORDS];
-
- private final float[] mMatrixValues = new float[MATRIX_VALUES_COUNT];
-
- protected Matrix mCurrentImageMatrix = new Matrix();
- protected int mThisWidth, mThisHeight;
-
- protected TransformImageListener mTransformImageListener;
-
- private float[] mInitialImageCorners;
- private float[] mInitialImageCenter;
-
- protected boolean mBitmapDecoded = false;
- protected boolean mBitmapLaidOut = false;
-
- private int mMaxBitmapSize = 0;
-
- private String mImageInputPath, mImageOutputPath;
- private ExifInfo mExifInfo;
-
- /**
- * Interface for rotation and scale change notifying.
- */
- public interface TransformImageListener {
-
- void onLoadComplete();
-
- void onLoadFailure(@NonNull Exception e);
-
- void onRotate(float currentAngle);
-
- void onScale(float currentScale);
-
- }
-
- public TransformImageView(Context context) {
- this(context, null);
- }
-
- public TransformImageView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TransformImageView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- public void setTransformImageListener(TransformImageListener transformImageListener) {
- mTransformImageListener = transformImageListener;
- }
-
- @Override
- public void setScaleType(ScaleType scaleType) {
- if (scaleType == ScaleType.MATRIX) {
- super.setScaleType(scaleType);
- } else {
- Log.w(TAG, "Invalid ScaleType. Only ScaleType.MATRIX can be used");
- }
- }
-
- /**
- * Setter for {@link #mMaxBitmapSize} value.
- * Be sure to call it before {@link #setImageURI(Uri)} or other image setters.
- *
- * @param maxBitmapSize - max size for both width and height of bitmap that will be used in the view.
- */
- public void setMaxBitmapSize(int maxBitmapSize) {
- mMaxBitmapSize = maxBitmapSize;
- }
-
- public int getMaxBitmapSize() {
- if (mMaxBitmapSize <= 0) {
- mMaxBitmapSize = BitmapLoadUtils.calculateMaxBitmapSize(getContext());
- }
- return mMaxBitmapSize;
- }
-
- @Override
- public void setImageBitmap(final Bitmap bitmap) {
- setImageDrawable(new FastBitmapDrawable(bitmap));
- }
-
- public String getImageInputPath() {
- return mImageInputPath;
- }
-
- public String getImageOutputPath() {
- return mImageOutputPath;
- }
-
- public ExifInfo getExifInfo() {
- return mExifInfo;
- }
-
- /**
- * This method takes an Uri as a parameter, then calls method to decode it into Bitmap with specified size.
- *
- * @param imageUri - image Uri
- * @throws Exception - can throw exception if having problems with decoding Uri or OOM.
- */
- public void setImageUri(@NonNull Uri imageUri, @Nullable Uri outputUri) throws Exception {
- int maxBitmapSize = getMaxBitmapSize();
-
- BitmapLoadUtils.decodeBitmapInBackground(getContext(), imageUri, outputUri, maxBitmapSize, maxBitmapSize,
- new BitmapLoadCallback() {
-
- @Override
- public void onBitmapLoaded(@NonNull Bitmap bitmap, @NonNull ExifInfo exifInfo, @NonNull String imageInputPath, @Nullable String imageOutputPath) {
- mImageInputPath = imageInputPath;
- mImageOutputPath = imageOutputPath;
- mExifInfo = exifInfo;
-
- mBitmapDecoded = true;
- setImageBitmap(bitmap);
- }
-
- @Override
- public void onFailure(@NonNull Exception bitmapWorkerException) {
- Log.e(TAG, "onFailure: setImageUri", bitmapWorkerException);
- if (mTransformImageListener != null) {
- mTransformImageListener.onLoadFailure(bitmapWorkerException);
- }
- }
- });
- }
-
- /**
- * @return - current image scale value.
- * [1.0f - for original image, 2.0f - for 200% scaled image, etc.]
- */
- public float getCurrentScale() {
- return getMatrixScale(mCurrentImageMatrix);
- }
-
- /**
- * This method calculates scale value for given Matrix object.
- */
- public float getMatrixScale(@NonNull Matrix matrix) {
- return (float) Math.sqrt(Math.pow(getMatrixValue(matrix, Matrix.MSCALE_X), 2)
- + Math.pow(getMatrixValue(matrix, Matrix.MSKEW_Y), 2));
- }
-
- /**
- * @return - current image rotation angle.
- */
- public float getCurrentAngle() {
- return getMatrixAngle(mCurrentImageMatrix);
- }
-
- /**
- * This method calculates rotation angle for given Matrix object.
- */
- public float getMatrixAngle(@NonNull Matrix matrix) {
- return (float) -(Math.atan2(getMatrixValue(matrix, Matrix.MSKEW_X),
- getMatrixValue(matrix, Matrix.MSCALE_X)) * (180 / Math.PI));
- }
-
- @Override
- public void setImageMatrix(Matrix matrix) {
- super.setImageMatrix(matrix);
- updateCurrentImagePoints();
- }
-
- @Nullable
- public Bitmap getViewBitmap() {
- if (getDrawable() == null || !(getDrawable() instanceof FastBitmapDrawable)) {
- return null;
- } else {
- return ((FastBitmapDrawable) getDrawable()).getBitmap();
- }
- }
-
- /**
- * This method translates current image.
- *
- * @param deltaX - horizontal shift
- * @param deltaY - vertical shift
- */
- public void postTranslate(float deltaX, float deltaY) {
- if (deltaX != 0 || deltaY != 0) {
- mCurrentImageMatrix.postTranslate(deltaX, deltaY);
- setImageMatrix(mCurrentImageMatrix);
- }
- }
-
- /**
- * This method scales current image.
- *
- * @param deltaScale - scale value
- * @param px - scale center X
- * @param py - scale center Y
- */
- public void postScale(float deltaScale, float px, float py) {
- if (deltaScale != 0) {
- mCurrentImageMatrix.postScale(deltaScale, deltaScale, px, py);
- setImageMatrix(mCurrentImageMatrix);
- if (mTransformImageListener != null) {
- mTransformImageListener.onScale(getMatrixScale(mCurrentImageMatrix));
- }
- }
- }
-
- /**
- * This method rotates current image.
- *
- * @param deltaAngle - rotation angle
- * @param px - rotation center X
- * @param py - rotation center Y
- */
- public void postRotate(float deltaAngle, float px, float py) {
- if (deltaAngle != 0) {
- mCurrentImageMatrix.postRotate(deltaAngle, px, py);
- setImageMatrix(mCurrentImageMatrix);
- if (mTransformImageListener != null) {
- mTransformImageListener.onRotate(getMatrixAngle(mCurrentImageMatrix));
- }
- }
- }
-
- protected void init() {
- setScaleType(ScaleType.MATRIX);
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (changed || (mBitmapDecoded && !mBitmapLaidOut)) {
-
- left = getPaddingLeft();
- top = getPaddingTop();
- right = getWidth() - getPaddingRight();
- bottom = getHeight() - getPaddingBottom();
- mThisWidth = right - left;
- mThisHeight = bottom - top;
-
- onImageLaidOut();
- }
- }
-
- /**
- * When image is laid out {@link #mInitialImageCenter} and {@link #mInitialImageCenter}
- * must be set.
- */
- protected void onImageLaidOut() {
- final Drawable drawable = getDrawable();
- if (drawable == null) {
- return;
- }
-
- float w = drawable.getIntrinsicWidth();
- float h = drawable.getIntrinsicHeight();
-
- Log.d(TAG, String.format("Image size: [%d:%d]", (int) w, (int) h));
-
- RectF initialImageRect = new RectF(0, 0, w, h);
- mInitialImageCorners = RectUtils.getCornersFromRect(initialImageRect);
- mInitialImageCenter = RectUtils.getCenterFromRect(initialImageRect);
-
- mBitmapLaidOut = true;
-
- if (mTransformImageListener != null) {
- mTransformImageListener.onLoadComplete();
- }
- }
-
- /**
- * This method returns Matrix value for given index.
- *
- * @param matrix - valid Matrix object
- * @param valueIndex - index of needed value. See {@link Matrix#MSCALE_X} and others.
- * @return - matrix value for index
- */
- protected float getMatrixValue(@NonNull Matrix matrix, @IntRange(from = 0, to = MATRIX_VALUES_COUNT) int valueIndex) {
- matrix.getValues(mMatrixValues);
- return mMatrixValues[valueIndex];
- }
-
- /**
- * This method logs given matrix X, Y, scale, and angle values.
- * Can be used for debug.
- */
- @SuppressWarnings("unused")
- protected void printMatrix(@NonNull String logPrefix, @NonNull Matrix matrix) {
- float x = getMatrixValue(matrix, Matrix.MTRANS_X);
- float y = getMatrixValue(matrix, Matrix.MTRANS_Y);
- float rScale = getMatrixScale(matrix);
- float rAngle = getMatrixAngle(matrix);
- Log.d(TAG, logPrefix + ": matrix: { x: " + x + ", y: " + y + ", scale: " + rScale + ", angle: " + rAngle + " }");
- }
-
- /**
- * This method updates current image corners and center points that are stored in
- * {@link #mCurrentImageCorners} and {@link #mCurrentImageCenter} arrays.
- * Those are used for several calculations.
- */
- private void updateCurrentImagePoints() {
- mCurrentImageMatrix.mapPoints(mCurrentImageCorners, mInitialImageCorners);
- mCurrentImageMatrix.mapPoints(mCurrentImageCenter, mInitialImageCenter);
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/view/UCropView.java b/library/src/main/java/com/yalantis/ucrop/view/UCropView.java
deleted file mode 100755
index 99447a03..00000000
--- a/library/src/main/java/com/yalantis/ucrop/view/UCropView.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.yalantis.ucrop.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.support.annotation.NonNull;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.widget.FrameLayout;
-
-import cn.finalteam.rxgalleryfinal.R;
-
-public class UCropView extends FrameLayout {
-
- private final GestureCropImageView mGestureCropImageView;
- private final OverlayView mViewOverlay;
-
- public UCropView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public UCropView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
-
- LayoutInflater.from(context).inflate(R.layout.gallery_ucrop_view, this, true);
- mGestureCropImageView = (GestureCropImageView) findViewById(R.id.image_view_crop);
- mViewOverlay = (OverlayView) findViewById(R.id.view_overlay);
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.gallery_ucrop_UCropView);
- mViewOverlay.processStyledAttributes(a);
- mGestureCropImageView.processStyledAttributes(a);
- a.recycle();
-
-
- mGestureCropImageView.setCropBoundsChangeListener(cropRatio -> mViewOverlay.setTargetAspectRatio(cropRatio));
- mViewOverlay.setOverlayViewChangeListener(cropRect -> mGestureCropImageView.setCropRect(cropRect));
- }
-
- @Override
- public boolean shouldDelayChildPressedState() {
- return false;
- }
-
- @NonNull
- public GestureCropImageView getCropImageView() {
- return mGestureCropImageView;
- }
-
- @NonNull
- public OverlayView getOverlayView() {
- return mViewOverlay;
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/yalantis/ucrop/view/widget/AspectRatioTextView.java b/library/src/main/java/com/yalantis/ucrop/view/widget/AspectRatioTextView.java
deleted file mode 100755
index 6720cd17..00000000
--- a/library/src/main/java/com/yalantis/ucrop/view/widget/AspectRatioTextView.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package com.yalantis.ucrop.view.widget;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.os.Build;
-import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
-import android.support.v4.content.ContextCompat;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.widget.TextView;
-
-import com.yalantis.ucrop.model.AspectRatio;
-import com.yalantis.ucrop.view.CropImageView;
-
-import java.util.Locale;
-
-import cn.finalteam.rxgalleryfinal.R;
-
-/**
- * Created by Oleksii Shliama (https://github.com/shliama).
- */
-public class AspectRatioTextView extends TextView {
-
- private final Rect mCanvasClipBounds = new Rect();
- private Paint mDotPaint;
- private int mDotSize;
- private float mAspectRatio;
-
- private String mAspectRatioTitle;
- private float mAspectRatioX, mAspectRatioY;
-
- public AspectRatioTextView(Context context) {
- this(context, null);
- }
-
- public AspectRatioTextView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AspectRatioTextView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.gallery_ucrop_AspectRatioTextView);
- init(a);
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public AspectRatioTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.gallery_ucrop_AspectRatioTextView);
- init(a);
- }
-
- /**
- * @param activeColor the resolved color for active elements
- */
-
- public void setActiveColor(@ColorInt int activeColor) {
- applyActiveColor(activeColor);
- invalidate();
- }
-
- public void setAspectRatio(@NonNull AspectRatio aspectRatio) {
- mAspectRatioTitle = aspectRatio.getAspectRatioTitle();
- mAspectRatioX = aspectRatio.getAspectRatioX();
- mAspectRatioY = aspectRatio.getAspectRatioY();
-
- if (mAspectRatioX == CropImageView.SOURCE_IMAGE_ASPECT_RATIO || mAspectRatioY == CropImageView.SOURCE_IMAGE_ASPECT_RATIO) {
- mAspectRatio = CropImageView.SOURCE_IMAGE_ASPECT_RATIO;
- } else {
- mAspectRatio = mAspectRatioX / mAspectRatioY;
- }
-
- setTitle();
- }
-
- public float getAspectRatio(boolean toggleRatio) {
- if (toggleRatio) {
- toggleAspectRatio();
- setTitle();
- }
- return mAspectRatio;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (isSelected()) {
- canvas.getClipBounds(mCanvasClipBounds);
- canvas.drawCircle((mCanvasClipBounds.right - mCanvasClipBounds.left) / 2.0f, mCanvasClipBounds.bottom - mDotSize,
- mDotSize / 2, mDotPaint);
- }
- }
-
- @SuppressWarnings("deprecation")
- private void init(@NonNull TypedArray a) {
- setGravity(Gravity.CENTER_HORIZONTAL);
-
- mAspectRatioTitle = a.getString(R.styleable.gallery_ucrop_AspectRatioTextView_gallery_ucrop_artv_ratio_title);
- mAspectRatioX = a.getFloat(R.styleable.gallery_ucrop_AspectRatioTextView_gallery_ucrop_artv_ratio_x, CropImageView.SOURCE_IMAGE_ASPECT_RATIO);
- mAspectRatioY = a.getFloat(R.styleable.gallery_ucrop_AspectRatioTextView_gallery_ucrop_artv_ratio_y, CropImageView.SOURCE_IMAGE_ASPECT_RATIO);
-
- if (mAspectRatioX == CropImageView.SOURCE_IMAGE_ASPECT_RATIO || mAspectRatioY == CropImageView.SOURCE_IMAGE_ASPECT_RATIO) {
- mAspectRatio = CropImageView.SOURCE_IMAGE_ASPECT_RATIO;
- } else {
- mAspectRatio = mAspectRatioX / mAspectRatioY;
- }
-
- mDotSize = getContext().getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_size_dot_scale_text_view);
- mDotPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mDotPaint.setStyle(Paint.Style.FILL);
-
- setTitle();
-
- int activeColor = getResources().getColor(R.color.gallery_default_ucrop_color_widget_active);
- applyActiveColor(activeColor);
-
- a.recycle();
- }
-
- private void applyActiveColor(@ColorInt int activeColor) {
- if (mDotPaint != null) {
- mDotPaint.setColor(activeColor);
- }
- ColorStateList textViewColorStateList = new ColorStateList(
- new int[][]{
- new int[]{android.R.attr.state_selected},
- new int[]{0}
- },
- new int[]{
- activeColor,
- ContextCompat.getColor(getContext(), R.color.gallery_default_ucrop_color_widget)
- }
- );
-
- setTextColor(textViewColorStateList);
- }
-
- private void toggleAspectRatio() {
- if (mAspectRatio != CropImageView.SOURCE_IMAGE_ASPECT_RATIO) {
- float tempRatioW = mAspectRatioX;
- mAspectRatioX = mAspectRatioY;
- mAspectRatioY = tempRatioW;
-
- mAspectRatio = mAspectRatioX / mAspectRatioY;
- }
- }
-
- private void setTitle() {
- if (!TextUtils.isEmpty(mAspectRatioTitle)) {
- setText(mAspectRatioTitle);
- } else {
- setText(String.format(Locale.US, "%d:%d", (int) mAspectRatioX, (int) mAspectRatioY));
- }
- }
-
-}
diff --git a/library/src/main/java/com/yalantis/ucrop/view/widget/HorizontalProgressWheelView.java b/library/src/main/java/com/yalantis/ucrop/view/widget/HorizontalProgressWheelView.java
deleted file mode 100755
index cdf8affc..00000000
--- a/library/src/main/java/com/yalantis/ucrop/view/widget/HorizontalProgressWheelView.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.yalantis.ucrop.view.widget;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.os.Build;
-import android.support.annotation.ColorInt;
-import android.support.v4.content.ContextCompat;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-import cn.finalteam.rxgalleryfinal.R;
-
-
-/**
- * Created by Oleksii Shliama (https://github.com/shliama).
- */
-public class HorizontalProgressWheelView extends View {
-
- private final Rect mCanvasClipBounds = new Rect();
-
- private ScrollingListener mScrollingListener;
- private float mLastTouchedPosition;
-
- private Paint mProgressLinePaint;
- private int mProgressLineWidth, mProgressLineHeight;
- private int mProgressLineMargin;
-
- private boolean mScrollStarted;
- private float mTotalScrollDistance;
-
- private int mMiddleLineColor;
-
- public HorizontalProgressWheelView(Context context) {
- this(context, null);
- }
-
- public HorizontalProgressWheelView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public HorizontalProgressWheelView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init();
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public HorizontalProgressWheelView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- public void setScrollingListener(ScrollingListener scrollingListener) {
- mScrollingListener = scrollingListener;
- }
-
- public void setMiddleLineColor(@ColorInt int middleLineColor) {
- mMiddleLineColor = middleLineColor;
- invalidate();
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mLastTouchedPosition = event.getX();
- break;
- case MotionEvent.ACTION_UP:
- if (mScrollingListener != null) {
- mScrollStarted = false;
- mScrollingListener.onScrollEnd();
- }
- break;
- case MotionEvent.ACTION_MOVE:
- float distance = event.getX() - mLastTouchedPosition;
- if (distance != 0) {
- if (!mScrollStarted) {
- mScrollStarted = true;
- if (mScrollingListener != null) {
- mScrollingListener.onScrollStart();
- }
- }
- onScrollEvent(event, distance);
- }
- break;
- }
- return true;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- canvas.getClipBounds(mCanvasClipBounds);
-
- int linesCount = mCanvasClipBounds.width() / (mProgressLineWidth + mProgressLineMargin);
- float deltaX = (mTotalScrollDistance) % (float) (mProgressLineMargin + mProgressLineWidth);
-
- mProgressLinePaint.setColor(getResources().getColor(R.color.gallery_default_ucrop_color_progress_wheel_line));
- for (int i = 0; i < linesCount; i++) {
- if (i < (linesCount / 4)) {
- mProgressLinePaint.setAlpha((int) (255 * (i / (float) (linesCount / 4))));
- } else if (i > (linesCount * 3 / 4)) {
- mProgressLinePaint.setAlpha((int) (255 * ((linesCount - i) / (float) (linesCount / 4))));
- } else {
- mProgressLinePaint.setAlpha(255);
- }
- canvas.drawLine(
- -deltaX + mCanvasClipBounds.left + i * (mProgressLineWidth + mProgressLineMargin),
- mCanvasClipBounds.centerY() - mProgressLineHeight / 4.0f,
- -deltaX + mCanvasClipBounds.left + i * (mProgressLineWidth + mProgressLineMargin),
- mCanvasClipBounds.centerY() + mProgressLineHeight / 4.0f, mProgressLinePaint);
- }
-
- mProgressLinePaint.setColor(mMiddleLineColor);
- canvas.drawLine(mCanvasClipBounds.centerX(), mCanvasClipBounds.centerY() - mProgressLineHeight / 2.0f, mCanvasClipBounds.centerX(), mCanvasClipBounds.centerY() + mProgressLineHeight / 2.0f, mProgressLinePaint);
-
- }
-
- private void onScrollEvent(MotionEvent event, float distance) {
- mTotalScrollDistance -= distance;
- postInvalidate();
- mLastTouchedPosition = event.getX();
- if (mScrollingListener != null) {
- mScrollingListener.onScroll(-distance, mTotalScrollDistance);
- }
- }
-
- private void init() {
- mMiddleLineColor = ContextCompat.getColor(getContext(), R.color.gallery_default_ucrop_color_progress_wheel_line);
-
- mProgressLineWidth = getContext().getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_width_horizontal_wheel_progress_line);
- mProgressLineHeight = getContext().getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_height_horizontal_wheel_progress_line);
- mProgressLineMargin = getContext().getResources().getDimensionPixelSize(R.dimen.gallery_ucrop_margin_horizontal_wheel_progress_line);
-
- mProgressLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mProgressLinePaint.setStyle(Paint.Style.STROKE);
- mProgressLinePaint.setStrokeWidth(mProgressLineWidth);
-
- }
-
- public interface ScrollingListener {
-
- void onScrollStart();
-
- void onScroll(float delta, float totalDistance);
-
- void onScrollEnd();
- }
-
-}
diff --git a/library/src/main/java/uk/co/senab/photoview/Compat.java b/library/src/main/java/uk/co/senab/photoview/Compat.java
index 58c445ae..05f81d70 100755
--- a/library/src/main/java/uk/co/senab/photoview/Compat.java
+++ b/library/src/main/java/uk/co/senab/photoview/Compat.java
@@ -39,10 +39,7 @@ private static void postOnAnimationJellyBean(View view, Runnable runnable) {
}
public static int getPointerIndex(int action) {
- if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB)
- return getPointerIndexHoneyComb(action);
- else
- return getPointerIndexEclair(action);
+ return getPointerIndexHoneyComb(action);
}
@SuppressWarnings("deprecation")
diff --git a/library/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java b/library/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java
index 27a50e52..06c58be3 100755
--- a/library/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java
+++ b/library/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java
@@ -55,7 +55,7 @@ public boolean onSingleTapConfirmed(MotionEvent e) {
photoViewAttacher.getOnPhotoTapListener().onPhotoTap(imageView, xResult, yResult);
return true;
- }else{
+ } else {
photoViewAttacher.getOnPhotoTapListener().onOutsidePhotoTap();
}
}
diff --git a/library/src/main/java/uk/co/senab/photoview/IPhotoView.java b/library/src/main/java/uk/co/senab/photoview/IPhotoView.java
index 43b01dc2..fcf01518 100755
--- a/library/src/main/java/uk/co/senab/photoview/IPhotoView.java
+++ b/library/src/main/java/uk/co/senab/photoview/IPhotoView.java
@@ -79,12 +79,32 @@ public interface IPhotoView {
@Deprecated
float getMinScale();
+ /**
+ * Use {@link #setMinimumScale(float minimumScale)} instead, this will be removed in future
+ * release
+ *
+ * Sets the minimum scale level. What this value represents depends on the current {@link
+ * ImageView.ScaleType}.
+ *
+ * @param minScale minimum allowed scale
+ */
+ @Deprecated
+ void setMinScale(float minScale);
+
/**
* @return The current minimum scale level. What this value represents depends on the current
* {@link ImageView.ScaleType}.
*/
float getMinimumScale();
+ /**
+ * Sets the minimum scale level. What this value represents depends on the current {@link
+ * ImageView.ScaleType}.
+ *
+ * @param minimumScale minimum allowed scale
+ */
+ void setMinimumScale(float minimumScale);
+
/**
* Use {@link #getMediumScale()} instead, this will be removed in future release
*
@@ -94,6 +114,18 @@ public interface IPhotoView {
@Deprecated
float getMidScale();
+ /**
+ * Use {@link #setMediumScale(float mediumScale)} instead, this will be removed in future
+ * release
+ *
+ * Sets the middle scale level. What this value represents depends on the current {@link
+ * ImageView.ScaleType}.
+ *
+ * @param midScale medium scale preset
+ */
+ @Deprecated
+ void setMidScale(float midScale);
+
/**
* @return The current medium scale level. What this value represents depends on the current
* {@link ImageView.ScaleType}.
@@ -101,100 +133,84 @@ public interface IPhotoView {
float getMediumScale();
/**
- * Use {@link #getMaximumScale()} instead, this will be removed in future release
+ * Sets the medium scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
*
- * @return The current maximum scale level. What this value represents depends on the current
- * {@link ImageView.ScaleType}.
+ * @param mediumScale medium scale preset
*/
- @Deprecated
- float getMaxScale();
+ void setMediumScale(float mediumScale);
/**
+ * Use {@link #getMaximumScale()} instead, this will be removed in future release
+ *
* @return The current maximum scale level. What this value represents depends on the current
* {@link ImageView.ScaleType}.
*/
- float getMaximumScale();
-
- /**
- * Returns the current scale value
- *
- * @return float - current scale value
- */
- float getScale();
+ @Deprecated
+ float getMaxScale();
/**
- * Return the current scale type in use by the ImageView.
+ * Use {@link #setMaximumScale(float maximumScale)} instead, this will be removed in future
+ * release
+ *
+ * Sets the maximum scale level. What this value represents depends on the current {@link
+ * ImageView.ScaleType}.
*
- * @return current ImageView.ScaleType
+ * @param maxScale maximum allowed scale preset
*/
- ImageView.ScaleType getScaleType();
+ @Deprecated
+ void setMaxScale(float maxScale);
/**
- * Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll
- * to it's horizontal edge.
- *
- * @param allow whether to allow intercepting by parent element or not
+ * @return The current maximum scale level. What this value represents depends on the current
+ * {@link ImageView.ScaleType}.
*/
- void setAllowParentInterceptOnEdge(boolean allow);
+ float getMaximumScale();
/**
- * Use {@link #setMinimumScale(float minimumScale)} instead, this will be removed in future
- * release
- *
- * Sets the minimum scale level. What this value represents depends on the current {@link
+ * Sets the maximum scale level. What this value represents depends on the current {@link
* ImageView.ScaleType}.
*
- * @param minScale minimum allowed scale
+ * @param maximumScale maximum allowed scale preset
*/
- @Deprecated
- void setMinScale(float minScale);
+ void setMaximumScale(float maximumScale);
/**
- * Sets the minimum scale level. What this value represents depends on the current {@link
- * ImageView.ScaleType}.
+ * Returns the current scale value
*
- * @param minimumScale minimum allowed scale
+ * @return float - current scale value
*/
- void setMinimumScale(float minimumScale);
+ float getScale();
/**
- * Use {@link #setMediumScale(float mediumScale)} instead, this will be removed in future
- * release
- *
- * Sets the middle scale level. What this value represents depends on the current {@link
- * ImageView.ScaleType}.
+ * Changes the current scale to the specified value.
*
- * @param midScale medium scale preset
+ * @param scale - Value to scale to
*/
- @Deprecated
- void setMidScale(float midScale);
+ void setScale(float scale);
/**
- * Sets the medium scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
+ * Return the current scale type in use by the ImageView.
*
- * @param mediumScale medium scale preset
+ * @return current ImageView.ScaleType
*/
- void setMediumScale(float mediumScale);
+ ImageView.ScaleType getScaleType();
/**
- * Use {@link #setMaximumScale(float maximumScale)} instead, this will be removed in future
- * release
- *
- * Sets the maximum scale level. What this value represents depends on the current {@link
+ * Controls how the image should be resized or moved to match the size of the ImageView. Any
+ * scaling or panning will happen within the confines of this {@link
* ImageView.ScaleType}.
*
- * @param maxScale maximum allowed scale preset
+ * @param scaleType - The desired scaling mode.
*/
- @Deprecated
- void setMaxScale(float maxScale);
+ void setScaleType(ImageView.ScaleType scaleType);
/**
- * Sets the maximum scale level. What this value represents depends on the current {@link
- * ImageView.ScaleType}.
+ * Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll
+ * to it's horizontal edge.
*
- * @param maximumScale maximum allowed scale preset
+ * @param allow whether to allow intercepting by parent element or not
*/
- void setMaximumScale(float maximumScale);
+ void setAllowParentInterceptOnEdge(boolean allow);
/**
* Allows to set all three scale levels at once, so you don't run into problem with setting
@@ -221,14 +237,6 @@ public interface IPhotoView {
*/
void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener);
- /**
- * Register a callback to be invoked when the Photo displayed by this View is tapped with a
- * single tap.
- *
- * @param listener - Listener to be registered.
- */
- void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener);
-
/**
* PhotoViewAttacher.OnPhotoTapListener reference should be stored in a variable instead, this
* will be removed in future release.
@@ -242,11 +250,12 @@ public interface IPhotoView {
PhotoViewAttacher.OnPhotoTapListener getOnPhotoTapListener();
/**
- * Register a callback to be invoked when the View is tapped with a single tap.
+ * Register a callback to be invoked when the Photo displayed by this View is tapped with a
+ * single tap.
*
* @param listener - Listener to be registered.
*/
- void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener);
+ void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener);
/**
* Enables rotation via PhotoView internal functions.
@@ -274,11 +283,11 @@ public interface IPhotoView {
PhotoViewAttacher.OnViewTapListener getOnViewTapListener();
/**
- * Changes the current scale to the specified value.
+ * Register a callback to be invoked when the View is tapped with a single tap.
*
- * @param scale - Value to scale to
+ * @param listener - Listener to be registered.
*/
- void setScale(float scale);
+ void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener);
/**
* Changes the current scale to the specified value.
@@ -298,15 +307,6 @@ public interface IPhotoView {
*/
void setScale(float scale, float focalX, float focalY, boolean animate);
- /**
- * Controls how the image should be resized or moved to match the size of the ImageView. Any
- * scaling or panning will happen within the confines of this {@link
- * ImageView.ScaleType}.
- *
- * @param scaleType - The desired scaling mode.
- */
- void setScaleType(ImageView.ScaleType scaleType);
-
/**
* Allows you to enable/disable the zoom functionality on the ImageView. When disable the
* ImageView reverts to using the FIT_CENTER matrix.
diff --git a/library/src/main/java/uk/co/senab/photoview/PhotoView.java b/library/src/main/java/uk/co/senab/photoview/PhotoView.java
index e224ab80..bb05bc2c 100755
--- a/library/src/main/java/uk/co/senab/photoview/PhotoView.java
+++ b/library/src/main/java/uk/co/senab/photoview/PhotoView.java
@@ -109,11 +109,22 @@ public float getMinScale() {
return getMinimumScale();
}
+ @Override
+ @Deprecated
+ public void setMinScale(float minScale) {
+ setMinimumScale(minScale);
+ }
+
@Override
public float getMinimumScale() {
return mAttacher.getMinimumScale();
}
+ @Override
+ public void setMinimumScale(float minimumScale) {
+ mAttacher.setMinimumScale(minimumScale);
+ }
+
@Override
@Deprecated
public float getMidScale() {
@@ -121,67 +132,70 @@ public float getMidScale() {
}
@Override
- public float getMediumScale() {
- return mAttacher.getMediumScale();
+ @Deprecated
+ public void setMidScale(float midScale) {
+ setMediumScale(midScale);
}
@Override
- @Deprecated
- public float getMaxScale() {
- return getMaximumScale();
+ public float getMediumScale() {
+ return mAttacher.getMediumScale();
}
@Override
- public float getMaximumScale() {
- return mAttacher.getMaximumScale();
+ public void setMediumScale(float mediumScale) {
+ mAttacher.setMediumScale(mediumScale);
}
@Override
- public float getScale() {
- return mAttacher.getScale();
+ @Deprecated
+ public float getMaxScale() {
+ return getMaximumScale();
}
@Override
- public ScaleType getScaleType() {
- return mAttacher.getScaleType();
+ @Deprecated
+ public void setMaxScale(float maxScale) {
+ setMaximumScale(maxScale);
}
@Override
- public void setAllowParentInterceptOnEdge(boolean allow) {
- mAttacher.setAllowParentInterceptOnEdge(allow);
+ public float getMaximumScale() {
+ return mAttacher.getMaximumScale();
}
@Override
- @Deprecated
- public void setMinScale(float minScale) {
- setMinimumScale(minScale);
+ public void setMaximumScale(float maximumScale) {
+ mAttacher.setMaximumScale(maximumScale);
}
@Override
- public void setMinimumScale(float minimumScale) {
- mAttacher.setMinimumScale(minimumScale);
+ public float getScale() {
+ return mAttacher.getScale();
}
@Override
- @Deprecated
- public void setMidScale(float midScale) {
- setMediumScale(midScale);
+ public void setScale(float scale) {
+ mAttacher.setScale(scale);
}
@Override
- public void setMediumScale(float mediumScale) {
- mAttacher.setMediumScale(mediumScale);
+ public ScaleType getScaleType() {
+ return mAttacher.getScaleType();
}
@Override
- @Deprecated
- public void setMaxScale(float maxScale) {
- setMaximumScale(maxScale);
+ public void setScaleType(ScaleType scaleType) {
+ if (null != mAttacher) {
+ mAttacher.setScaleType(scaleType);
+ } else {
+ mPendingScaleType = scaleType;
+ }
}
@Override
- public void setMaximumScale(float maximumScale) {
- mAttacher.setMaximumScale(maximumScale);
+ public void setAllowParentInterceptOnEdge(boolean allow) {
+ mAttacher.setAllowParentInterceptOnEdge(allow);
}
@Override
@@ -224,11 +238,6 @@ public void setOnLongClickListener(OnLongClickListener l) {
mAttacher.setOnLongClickListener(l);
}
- @Override
- public void setOnPhotoTapListener(OnPhotoTapListener listener) {
- mAttacher.setOnPhotoTapListener(listener);
- }
-
@Override
@Deprecated
public OnPhotoTapListener getOnPhotoTapListener() {
@@ -236,8 +245,8 @@ public OnPhotoTapListener getOnPhotoTapListener() {
}
@Override
- public void setOnViewTapListener(OnViewTapListener listener) {
- mAttacher.setOnViewTapListener(listener);
+ public void setOnPhotoTapListener(OnPhotoTapListener listener) {
+ mAttacher.setOnPhotoTapListener(listener);
}
@Override
@@ -247,8 +256,8 @@ public OnViewTapListener getOnViewTapListener() {
}
@Override
- public void setScale(float scale) {
- mAttacher.setScale(scale);
+ public void setOnViewTapListener(OnViewTapListener listener) {
+ mAttacher.setOnViewTapListener(listener);
}
@Override
@@ -261,15 +270,6 @@ public void setScale(float scale, float focalX, float focalY, boolean animate) {
mAttacher.setScale(scale, focalX, focalY, animate);
}
- @Override
- public void setScaleType(ScaleType scaleType) {
- if (null != mAttacher) {
- mAttacher.setScaleType(scaleType);
- } else {
- mPendingScaleType = scaleType;
- }
- }
-
@Override
public void setZoomable(boolean zoomable) {
mAttacher.setZoomable(zoomable);
diff --git a/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java b/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java
index 48809821..f96bd6a2 100644
--- a/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java
+++ b/library/src/main/java/uk/co/senab/photoview/PhotoViewAttacher.java
@@ -22,7 +22,7 @@
import android.graphics.Matrix.ScaleToFit;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
-import android.support.v4.view.MotionEventCompat;
+import androidx.core.view.MotionEventCompat;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
@@ -50,93 +50,32 @@ public class PhotoViewAttacher implements IPhotoView, View.OnTouchListener,
OnGestureListener,
ViewTreeObserver.OnGlobalLayoutListener {
- private static final String LOG_TAG = "PhotoViewAttacher";
-
- // let debug flag be dynamic, but still Proguard can be used to remove from
- // release builds
- private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
-
- private Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
- int ZOOM_DURATION = DEFAULT_ZOOM_DURATION;
-
static final int EDGE_NONE = -1;
static final int EDGE_LEFT = 0;
static final int EDGE_RIGHT = 1;
static final int EDGE_BOTH = 2;
-
+ private static final String LOG_TAG = "PhotoViewAttacher";
+ // let debug flag be dynamic, but still Proguard can be used to remove from
+ // release builds
+ private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
static int SINGLE_TOUCH = 1;
-
+ // These are set so we don't keep allocating them on the heap
+ private final Matrix mBaseMatrix = new Matrix();
+ private final Matrix mDrawMatrix = new Matrix();
+ private final Matrix mSuppMatrix = new Matrix();
+ private final RectF mDisplayRect = new RectF();
+ private final float[] mMatrixValues = new float[9];
+ int ZOOM_DURATION = DEFAULT_ZOOM_DURATION;
+ private Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
private float mMinScale = DEFAULT_MIN_SCALE;
private float mMidScale = DEFAULT_MID_SCALE;
private float mMaxScale = DEFAULT_MAX_SCALE;
-
private boolean mAllowParentInterceptOnEdge = true;
private boolean mBlockParentIntercept = false;
-
- private static void checkZoomLevels(float minZoom, float midZoom,
- float maxZoom) {
- if (minZoom >= midZoom) {
- throw new IllegalArgumentException(
- "Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value");
- } else if (midZoom >= maxZoom) {
- throw new IllegalArgumentException(
- "Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value");
- }
- }
-
- /**
- * @return true if the ImageView exists, and it's Drawable exists
- */
- private static boolean hasDrawable(ImageView imageView) {
- return null != imageView && null != imageView.getDrawable();
- }
-
- /**
- * @return true if the ScaleType is supported.
- */
- private static boolean isSupportedScaleType(final ScaleType scaleType) {
- if (null == scaleType) {
- return false;
- }
-
- switch (scaleType) {
- case MATRIX:
- throw new IllegalArgumentException(scaleType.name()
- + " is not supported in PhotoView");
-
- default:
- return true;
- }
- }
-
- /**
- * Set's the ImageView's ScaleType to Matrix.
- */
- private static void setImageViewScaleTypeMatrix(ImageView imageView) {
- /**
- * PhotoView sets it's own ScaleType to Matrix, then diverts all calls
- * setScaleType to this.setScaleType automatically.
- */
- if (null != imageView && !(imageView instanceof IPhotoView)) {
- if (!ScaleType.MATRIX.equals(imageView.getScaleType())) {
- imageView.setScaleType(ScaleType.MATRIX);
- }
- }
- }
-
private WeakReference mImageView;
-
// Gesture Detectors
private GestureDetector mGestureDetector;
private uk.co.senab.photoview.gestures.GestureDetector mScaleDragDetector;
-
- // These are set so we don't keep allocating them on the heap
- private final Matrix mBaseMatrix = new Matrix();
- private final Matrix mDrawMatrix = new Matrix();
- private final Matrix mSuppMatrix = new Matrix();
- private final RectF mDisplayRect = new RectF();
- private final float[] mMatrixValues = new float[9];
-
// Listeners
private OnMatrixChangedListener mMatrixChangeListener;
private OnPhotoTapListener mPhotoTapListener;
@@ -144,12 +83,10 @@ private static void setImageViewScaleTypeMatrix(ImageView imageView) {
private OnLongClickListener mLongClickListener;
private OnScaleChangeListener mScaleChangeListener;
private OnSingleFlingListener mSingleFlingListener;
-
private int mIvTop, mIvRight, mIvBottom, mIvLeft;
private FlingRunnable mCurrentFlingRunnable;
private int mScrollEdge = EDGE_BOTH;
private float mBaseRotation;
-
private boolean mZoomEnabled;
private ScaleType mScaleType = ScaleType.FIT_CENTER;
@@ -214,6 +151,57 @@ public boolean onFling(MotionEvent e1, MotionEvent e2,
setZoomable(zoomable);
}
+ private static void checkZoomLevels(float minZoom, float midZoom,
+ float maxZoom) {
+ if (minZoom >= midZoom) {
+ throw new IllegalArgumentException(
+ "Minimum zoom has to be less than Medium zoom. Call setMinimumZoom() with a more appropriate value");
+ } else if (midZoom >= maxZoom) {
+ throw new IllegalArgumentException(
+ "Medium zoom has to be less than Maximum zoom. Call setMaximumZoom() with a more appropriate value");
+ }
+ }
+
+ /**
+ * @return true if the ImageView exists, and it's Drawable exists
+ */
+ private static boolean hasDrawable(ImageView imageView) {
+ return null != imageView && null != imageView.getDrawable();
+ }
+
+ /**
+ * @return true if the ScaleType is supported.
+ */
+ private static boolean isSupportedScaleType(final ScaleType scaleType) {
+ if (null == scaleType) {
+ return false;
+ }
+
+ switch (scaleType) {
+ case MATRIX:
+ throw new IllegalArgumentException(scaleType.name()
+ + " is not supported in PhotoView");
+
+ default:
+ return true;
+ }
+ }
+
+ /**
+ * Set's the ImageView's ScaleType to Matrix.
+ */
+ private static void setImageViewScaleTypeMatrix(ImageView imageView) {
+ /**
+ * PhotoView sets it's own ScaleType to Matrix, then diverts all calls
+ * setScaleType to this.setScaleType automatically.
+ */
+ if (null != imageView && !(imageView instanceof IPhotoView)) {
+ if (!ScaleType.MATRIX.equals(imageView.getScaleType())) {
+ imageView.setScaleType(ScaleType.MATRIX);
+ }
+ }
+ }
+
@Override
public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener) {
if (newOnDoubleTapListener != null) {
@@ -357,53 +345,100 @@ public float getMinScale() {
return getMinimumScale();
}
+ @Override
+ @Deprecated
+ public void setMinScale(float minScale) {
+ setMinimumScale(minScale);
+ }
+
@Override
public float getMinimumScale() {
return mMinScale;
}
+ @Override
+ public void setMinimumScale(float minimumScale) {
+ checkZoomLevels(minimumScale, mMidScale, mMaxScale);
+ mMinScale = minimumScale;
+ }
+
@Override
@Deprecated
public float getMidScale() {
return getMediumScale();
}
+ @Override
+ @Deprecated
+ public void setMidScale(float midScale) {
+ setMediumScale(midScale);
+ }
+
@Override
public float getMediumScale() {
return mMidScale;
}
+ @Override
+ public void setMediumScale(float mediumScale) {
+ checkZoomLevels(mMinScale, mediumScale, mMaxScale);
+ mMidScale = mediumScale;
+ }
+
@Override
@Deprecated
public float getMaxScale() {
return getMaximumScale();
}
+ @Override
+ @Deprecated
+ public void setMaxScale(float maxScale) {
+ setMaximumScale(maxScale);
+ }
+
@Override
public float getMaximumScale() {
return mMaxScale;
}
+ @Override
+ public void setMaximumScale(float maximumScale) {
+ checkZoomLevels(mMinScale, mMidScale, maximumScale);
+ mMaxScale = maximumScale;
+ }
+
@Override
public float getScale() {
return (float) Math.sqrt((float) Math.pow(getValue(mSuppMatrix, Matrix.MSCALE_X), 2) + (float) Math.pow(getValue(mSuppMatrix, Matrix.MSKEW_Y), 2));
}
+ @Override
+ public void setScale(float scale) {
+ setScale(scale, false);
+ }
+
@Override
public ScaleType getScaleType() {
return mScaleType;
}
+ @Override
+ public void setScaleType(ScaleType scaleType) {
+ if (isSupportedScaleType(scaleType) && scaleType != mScaleType) {
+ mScaleType = scaleType;
+
+ // Finally update
+ update();
+ }
+ }
+
@Override
public void onDrag(float dx, float dy) {
if (mScaleDragDetector.isScaling()) {
return; // Do not drag if we are already scaling
}
- if (DEBUG) {
- Logger.d(String.format("onDrag: dx: %.2f. dy: %.2f", dx, dy));
- }
-
ImageView imageView = getImageView();
mSuppMatrix.postTranslate(dx, dy);
checkAndDisplayMatrix();
@@ -436,10 +471,6 @@ public void onDrag(float dx, float dy) {
@Override
public void onFling(float startX, float startY, float velocityX,
float velocityY) {
- if (DEBUG) {
- Logger.d("onFling. sX: " + startX + " sY: " + startY + " Vx: "
- + velocityX + " Vy: " + velocityY);
- }
ImageView imageView = getImageView();
mCurrentFlingRunnable = new FlingRunnable(imageView.getContext());
mCurrentFlingRunnable.fling(getImageViewWidth(imageView),
@@ -484,11 +515,6 @@ public void onGlobalLayout() {
@Override
public void onScale(float scaleFactor, float focusX, float focusY) {
- if (DEBUG) {
- Logger.d(String.format("onScale: scale: %.2f. fX: %.2f. fY: %.2f",
- scaleFactor, focusX, focusY));
- }
-
if ((getScale() < mMaxScale || scaleFactor < 1f) && (getScale() > mMinScale || scaleFactor > 1f)) {
if (null != mScaleChangeListener) {
mScaleChangeListener.onScaleChange(scaleFactor, focusX, focusY);
@@ -563,42 +589,6 @@ public void setAllowParentInterceptOnEdge(boolean allow) {
mAllowParentInterceptOnEdge = allow;
}
- @Override
- @Deprecated
- public void setMinScale(float minScale) {
- setMinimumScale(minScale);
- }
-
- @Override
- public void setMinimumScale(float minimumScale) {
- checkZoomLevels(minimumScale, mMidScale, mMaxScale);
- mMinScale = minimumScale;
- }
-
- @Override
- @Deprecated
- public void setMidScale(float midScale) {
- setMediumScale(midScale);
- }
-
- @Override
- public void setMediumScale(float mediumScale) {
- checkZoomLevels(mMinScale, mediumScale, mMaxScale);
- mMidScale = mediumScale;
- }
-
- @Override
- @Deprecated
- public void setMaxScale(float maxScale) {
- setMaximumScale(maxScale);
- }
-
- @Override
- public void setMaximumScale(float maximumScale) {
- checkZoomLevels(mMinScale, mMidScale, maximumScale);
- mMaxScale = maximumScale;
- }
-
@Override
public void setScaleLevels(float minimumScale, float mediumScale, float maximumScale) {
checkZoomLevels(minimumScale, mediumScale, maximumScale);
@@ -617,11 +607,6 @@ public void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
mMatrixChangeListener = listener;
}
- @Override
- public void setOnPhotoTapListener(OnPhotoTapListener listener) {
- mPhotoTapListener = listener;
- }
-
@Override
@Deprecated
public OnPhotoTapListener getOnPhotoTapListener() {
@@ -629,8 +614,8 @@ public OnPhotoTapListener getOnPhotoTapListener() {
}
@Override
- public void setOnViewTapListener(OnViewTapListener listener) {
- mViewTapListener = listener;
+ public void setOnPhotoTapListener(OnPhotoTapListener listener) {
+ mPhotoTapListener = listener;
}
@Override
@@ -640,8 +625,8 @@ public OnViewTapListener getOnViewTapListener() {
}
@Override
- public void setScale(float scale) {
- setScale(scale, false);
+ public void setOnViewTapListener(OnViewTapListener listener) {
+ mViewTapListener = listener;
}
@Override
@@ -680,22 +665,13 @@ public void setScale(float scale, float focalX, float focalY,
/**
* Set the zoom interpolator
+ *
* @param interpolator the zoom interpolator
*/
public void setZoomInterpolator(Interpolator interpolator) {
mInterpolator = interpolator;
}
- @Override
- public void setScaleType(ScaleType scaleType) {
- if (isSupportedScaleType(scaleType) && scaleType != mScaleType) {
- mScaleType = scaleType;
-
- // Finally update
- update();
- }
- }
-
@Override
public void setZoomable(boolean zoomable) {
mZoomEnabled = zoomable;
@@ -730,6 +706,7 @@ public Matrix getDisplayMatrix() {
/**
* Like {@link #getDisplayMatrix()}, but allows the user to provide a matrix to copy the values into to reduce object allocation
+ *
* @param matrix target matrix to copy to
*/
@Override
@@ -781,7 +758,7 @@ private void checkImageViewScaleType() {
if (null != imageView && !(imageView instanceof IPhotoView)) {
if (!ScaleType.MATRIX.equals(imageView.getScaleType())) {
throw new IllegalStateException(
- "The ImageView's ScaleType has been changed since attaching a PhotoViewAttacher. You should call setScaleType on the PhotoViewAttacher instead of on the ImageView" );
+ "The ImageView's ScaleType has been changed since attaching a PhotoViewAttacher. You should call setScaleType on the PhotoViewAttacher instead of on the ImageView");
}
}
}
@@ -1062,7 +1039,7 @@ public interface OnPhotoTapListener {
/**
* A simple callback where out of photo happened;
- * */
+ */
void onOutsidePhotoTap();
}
@@ -1157,9 +1134,6 @@ public FlingRunnable(Context context) {
}
public void cancelFling() {
- if (DEBUG) {
- Logger.d("Cancel Fling");
- }
mScroller.forceFinished(true);
}
@@ -1191,11 +1165,6 @@ public void fling(int viewWidth, int viewHeight, int velocityX,
mCurrentX = startX;
mCurrentY = startY;
- if (DEBUG) {
- Logger.d("fling. StartX:" + startX + " StartY:" + startY
- + " MaxX:" + maxX + " MaxY:" + maxY);
- }
-
// If we actually can move, fling the scroller
if (startX != maxX || startY != maxY) {
mScroller.fling(startX, startY, velocityX, velocityY, minX,
@@ -1215,12 +1184,6 @@ public void run() {
final int newX = mScroller.getCurrX();
final int newY = mScroller.getCurrY();
- if (DEBUG) {
- Logger.d("fling run(). CurrentX:" + mCurrentX + " CurrentY:"
- + mCurrentY + " NewX:" + newX + " NewY:"
- + newY);
- }
-
mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);
setImageViewMatrix(getDrawMatrix());
diff --git a/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java b/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java
index b87c5b2e..a526bb77 100755
--- a/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java
+++ b/library/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java
@@ -24,17 +24,14 @@
public class CupcakeGestureDetector implements GestureDetector {
- protected OnGestureListener mListener;
private static final String LOG_TAG = "CupcakeGestureDetector";
- float mLastTouchX;
- float mLastTouchY;
final float mTouchSlop;
final float mMinimumVelocity;
-
- @Override
- public void setOnGestureListener(OnGestureListener listener) {
- this.mListener = listener;
- }
+ protected OnGestureListener mListener;
+ float mLastTouchX;
+ float mLastTouchY;
+ private VelocityTracker mVelocityTracker;
+ private boolean mIsDragging;
public CupcakeGestureDetector(Context context) {
final ViewConfiguration configuration = ViewConfiguration
@@ -43,8 +40,10 @@ public CupcakeGestureDetector(Context context) {
mTouchSlop = configuration.getScaledTouchSlop();
}
- private VelocityTracker mVelocityTracker;
- private boolean mIsDragging;
+ @Override
+ public void setOnGestureListener(OnGestureListener listener) {
+ this.mListener = listener;
+ }
float getActiveX(MotionEvent ev) {
return ev.getX();
diff --git a/library/src/main/jniLibs/arm64-v8a/libucrop.so b/library/src/main/jniLibs/arm64-v8a/libucrop.so
deleted file mode 100755
index e3911d6c..00000000
Binary files a/library/src/main/jniLibs/arm64-v8a/libucrop.so and /dev/null differ
diff --git a/library/src/main/jniLibs/armeabi-v7a/libucrop.so b/library/src/main/jniLibs/armeabi-v7a/libucrop.so
deleted file mode 100755
index b6172412..00000000
Binary files a/library/src/main/jniLibs/armeabi-v7a/libucrop.so and /dev/null differ
diff --git a/library/src/main/jniLibs/armeabi/libucrop.so b/library/src/main/jniLibs/armeabi/libucrop.so
deleted file mode 100755
index 6be5f557..00000000
Binary files a/library/src/main/jniLibs/armeabi/libucrop.so and /dev/null differ
diff --git a/library/src/main/jniLibs/x86/libucrop.so b/library/src/main/jniLibs/x86/libucrop.so
deleted file mode 100755
index 5de62c1e..00000000
Binary files a/library/src/main/jniLibs/x86/libucrop.so and /dev/null differ
diff --git a/library/src/main/jniLibs/x86_64/libucrop.so b/library/src/main/jniLibs/x86_64/libucrop.so
deleted file mode 100755
index 53bb591a..00000000
Binary files a/library/src/main/jniLibs/x86_64/libucrop.so and /dev/null differ
diff --git a/library/src/main/res/anim/gallery_ucrop_loader_circle_path.xml b/library/src/main/res/anim/gallery_ucrop_loader_circle_path.xml
deleted file mode 100755
index 0364d754..00000000
--- a/library/src/main/res/anim/gallery_ucrop_loader_circle_path.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/anim/gallery_ucrop_loader_circle_scale.xml b/library/src/main/res/anim/gallery_ucrop_loader_circle_scale.xml
deleted file mode 100755
index 60e7eef0..00000000
--- a/library/src/main/res/anim/gallery_ucrop_loader_circle_scale.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/color/gallery_text_color_selector.xml b/library/src/main/res/color/gallery_text_color_selector.xml
index 64e6f4fe..19cf9ac8 100644
--- a/library/src/main/res/color/gallery_text_color_selector.xml
+++ b/library/src/main/res/color/gallery_text_color_selector.xml
@@ -1,6 +1,6 @@
-
-
+
+
\ No newline at end of file
diff --git a/library/src/main/res/color/gallery_ucrop_scale_text_view_selector.xml b/library/src/main/res/color/gallery_ucrop_scale_text_view_selector.xml
deleted file mode 100755
index 689c3137..00000000
--- a/library/src/main/res/color/gallery_ucrop_scale_text_view_selector.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-hdpi/gallery_ic_cross.png
old mode 100755
new mode 100644
similarity index 100%
rename from library/src/main/res/drawable-hdpi/gallery_ucrop_ic_cross.png
rename to library/src/main/res/drawable-hdpi/gallery_ic_cross.png
diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_angle.png
deleted file mode 100755
index 218d5609..00000000
Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_angle.png and /dev/null differ
diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_crop.png
deleted file mode 100755
index a12fdfc7..00000000
Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_crop.png and /dev/null differ
diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_done.png
deleted file mode 100755
index 70472dd9..00000000
Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_done.png and /dev/null differ
diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_next.png
deleted file mode 100755
index d1b1cddb..00000000
Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_next.png and /dev/null differ
diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_reset.png
deleted file mode 100755
index 2b6692bb..00000000
Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_reset.png and /dev/null differ
diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_rotate.png
deleted file mode 100755
index ba20cf35..00000000
Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_rotate.png and /dev/null differ
diff --git a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_scale.png
deleted file mode 100755
index 0be967cd..00000000
Binary files a/library/src/main/res/drawable-hdpi/gallery_ucrop_ic_scale.png and /dev/null differ
diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-ldpi/gallery_ic_cross.png
old mode 100755
new mode 100644
similarity index 100%
rename from library/src/main/res/drawable-ldpi/gallery_ucrop_ic_cross.png
rename to library/src/main/res/drawable-ldpi/gallery_ic_cross.png
diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_angle.png
deleted file mode 100755
index 41af9796..00000000
Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_angle.png and /dev/null differ
diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_crop.png
deleted file mode 100755
index 19daec37..00000000
Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_crop.png and /dev/null differ
diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_done.png
deleted file mode 100755
index 9e48718a..00000000
Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_done.png and /dev/null differ
diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_next.png
deleted file mode 100755
index 732e9a78..00000000
Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_next.png and /dev/null differ
diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_reset.png
deleted file mode 100755
index dfdb5bc9..00000000
Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_reset.png and /dev/null differ
diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_rotate.png
deleted file mode 100755
index d812eada..00000000
Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_rotate.png and /dev/null differ
diff --git a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_scale.png
deleted file mode 100755
index 2522ac7d..00000000
Binary files a/library/src/main/res/drawable-ldpi/gallery_ucrop_ic_scale.png and /dev/null differ
diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-mdpi/gallery_ic_cross.png
old mode 100755
new mode 100644
similarity index 100%
rename from library/src/main/res/drawable-mdpi/gallery_ucrop_ic_cross.png
rename to library/src/main/res/drawable-mdpi/gallery_ic_cross.png
diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_angle.png
deleted file mode 100755
index 9945b062..00000000
Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_angle.png and /dev/null differ
diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_crop.png
deleted file mode 100755
index 36e4f362..00000000
Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_crop.png and /dev/null differ
diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_done.png
deleted file mode 100755
index ddf1cd96..00000000
Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_done.png and /dev/null differ
diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_next.png
deleted file mode 100755
index 8f972bb0..00000000
Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_next.png and /dev/null differ
diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_reset.png
deleted file mode 100755
index 5431cd34..00000000
Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_reset.png and /dev/null differ
diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_rotate.png
deleted file mode 100755
index f7890066..00000000
Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_rotate.png and /dev/null differ
diff --git a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_scale.png
deleted file mode 100755
index ac363b77..00000000
Binary files a/library/src/main/res/drawable-mdpi/gallery_ucrop_ic_scale.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-xhdpi/gallery_ic_cross.png
old mode 100755
new mode 100644
similarity index 100%
rename from library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_cross.png
rename to library/src/main/res/drawable-xhdpi/gallery_ic_cross.png
diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_angle.png
deleted file mode 100755
index 27d13187..00000000
Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_angle.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_crop.png
deleted file mode 100755
index f18a41c3..00000000
Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_crop.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_done.png
deleted file mode 100755
index e588817f..00000000
Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_done.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_next.png
deleted file mode 100755
index 6cd8e294..00000000
Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_next.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_reset.png
deleted file mode 100755
index 15f8a7b2..00000000
Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_reset.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_rotate.png
deleted file mode 100755
index d10f0c99..00000000
Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_rotate.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_scale.png
deleted file mode 100755
index cdb82257..00000000
Binary files a/library/src/main/res/drawable-xhdpi/gallery_ucrop_ic_scale.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-xxhdpi/gallery_ic_cross.png
old mode 100755
new mode 100644
similarity index 100%
rename from library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_cross.png
rename to library/src/main/res/drawable-xxhdpi/gallery_ic_cross.png
diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_angle.png
deleted file mode 100755
index 30d941d3..00000000
Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_angle.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_crop.png
deleted file mode 100755
index 7decf1a3..00000000
Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_crop.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_done.png
deleted file mode 100755
index 9e84e9ad..00000000
Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_done.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_next.png
deleted file mode 100755
index d6f68f37..00000000
Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_next.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_reset.png
deleted file mode 100755
index 52870ba0..00000000
Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_reset.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_rotate.png
deleted file mode 100755
index 91b1c8ed..00000000
Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_rotate.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_scale.png
deleted file mode 100755
index 158335cc..00000000
Binary files a/library/src/main/res/drawable-xxhdpi/gallery_ucrop_ic_scale.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ic_corner_selector.xml b/library/src/main/res/drawable-xxxhdpi/gallery_ic_corner_selector.xml
index ffe37819..a6497e2e 100644
--- a/library/src/main/res/drawable-xxxhdpi/gallery_ic_corner_selector.xml
+++ b/library/src/main/res/drawable-xxxhdpi/gallery_ic_corner_selector.xml
@@ -1,7 +1,7 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_cross.png b/library/src/main/res/drawable-xxxhdpi/gallery_ic_cross.png
old mode 100755
new mode 100644
similarity index 100%
rename from library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_cross.png
rename to library/src/main/res/drawable-xxxhdpi/gallery_ic_cross.png
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_angle.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_angle.png
deleted file mode 100755
index 68eb67e0..00000000
Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_angle.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_crop.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_crop.png
deleted file mode 100755
index 8dfce883..00000000
Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_crop.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_done.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_done.png
deleted file mode 100755
index fe6352d8..00000000
Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_done.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_next.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_next.png
deleted file mode 100755
index 9f645340..00000000
Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_next.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_reset.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_reset.png
deleted file mode 100755
index 75a92c0d..00000000
Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_reset.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_rotate.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_rotate.png
deleted file mode 100755
index 7525f926..00000000
Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_rotate.png and /dev/null differ
diff --git a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_scale.png b/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_scale.png
deleted file mode 100755
index 21fc505b..00000000
Binary files a/library/src/main/res/drawable-xxxhdpi/gallery_ucrop_ic_scale.png and /dev/null differ
diff --git a/library/src/main/res/drawable/gallery_bucket_item_selector.xml b/library/src/main/res/drawable/gallery_bucket_item_selector.xml
index ec5e626f..4a6ed0c9 100644
--- a/library/src/main/res/drawable/gallery_bucket_item_selector.xml
+++ b/library/src/main/res/drawable/gallery_bucket_item_selector.xml
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/library/src/main/res/drawable/gallery_button_selector.xml b/library/src/main/res/drawable/gallery_button_selector.xml
index 4952d945..fd509a3d 100644
--- a/library/src/main/res/drawable/gallery_button_selector.xml
+++ b/library/src/main/res/drawable/gallery_button_selector.xml
@@ -3,31 +3,21 @@
-
-
+
-
-
+
+
-
-
+
-
+
-
+
diff --git a/library/src/main/res/drawable/gallery_checkbox_selector.xml b/library/src/main/res/drawable/gallery_checkbox_selector.xml
deleted file mode 100644
index 2d864820..00000000
--- a/library/src/main/res/drawable/gallery_checkbox_selector.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/drawable/gallery_default_image.xml b/library/src/main/res/drawable/gallery_default_image.xml
index 24358d21..c0c889e4 100644
--- a/library/src/main/res/drawable/gallery_default_image.xml
+++ b/library/src/main/res/drawable/gallery_default_image.xml
@@ -1,4 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/library/src/main/res/drawable/gallery_ucrop_shadow_upside.xml b/library/src/main/res/drawable/gallery_ucrop_shadow_upside.xml
deleted file mode 100755
index 0be54272..00000000
--- a/library/src/main/res/drawable/gallery_ucrop_shadow_upside.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/drawable/gallery_ucrop_vector_ic_crop.xml b/library/src/main/res/drawable/gallery_ucrop_vector_ic_crop.xml
deleted file mode 100755
index 99b93e8d..00000000
--- a/library/src/main/res/drawable/gallery_ucrop_vector_ic_crop.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/library/src/main/res/drawable/gallery_ucrop_vector_loader.xml b/library/src/main/res/drawable/gallery_ucrop_vector_loader.xml
deleted file mode 100755
index 89cb7bcb..00000000
--- a/library/src/main/res/drawable/gallery_ucrop_vector_loader.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/drawable/gallery_ucrop_vector_loader_animated.xml b/library/src/main/res/drawable/gallery_ucrop_vector_loader_animated.xml
deleted file mode 100755
index 319dc43b..00000000
--- a/library/src/main/res/drawable/gallery_ucrop_vector_loader_animated.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_activity_media.xml b/library/src/main/res/layout/gallery_activity_media.xml
index 0e6f5cc2..5353d05a 100644
--- a/library/src/main/res/layout/gallery_activity_media.xml
+++ b/library/src/main/res/layout/gallery_activity_media.xml
@@ -4,7 +4,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
-
+ android:layout_gravity="center" />
-
+ android:layout_margin="8dp"
+ android:text="@string/gallery_over_button_text" />
+
+ android:layout_height="1dp" />
+ android:background="@drawable/gallery_bg_bucket"
+ android:scaleType="centerCrop" />
+ android:textColor="#2A2A2A"
+ android:textSize="16sp" />
-
+ android:visibility="gone" />
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_adapter_media_grid_item.xml b/library/src/main/res/layout/gallery_adapter_media_grid_item.xml
index dedb002b..c2e7d2bc 100644
--- a/library/src/main/res/layout/gallery_adapter_media_grid_item.xml
+++ b/library/src/main/res/layout/gallery_adapter_media_grid_item.xml
@@ -29,11 +29,11 @@
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
-
+ android:cacheColorHint="#00000000" />
+ android:clickable="true"
+ android:gravity="center_vertical">
+ android:gravity="center_vertical"
+ android:paddingBottom="12dp"
+ android:paddingLeft="15dp"
+ android:paddingTop="12dp"
+ android:text="@string/gallery_all_image"
+ android:textColor="@color/gallery_text_color_selector"
+ android:textSize="14sp" />
+ android:paddingTop="12dp"
+ android:text="@string/gallery_preview_title"
+ android:textColor="@color/gallery_text_color_selector"
+ android:textSize="14sp" />
+ android:layout_toLeftOf="@id/tv_preview"
+ android:background="#1F1F1F" />
@@ -68,15 +67,16 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/rl_bottom_bar"
- android:paddingTop="?actionBarSize"
android:background="@color/gallery_media_grid_block_color"
- android:visibility="gone"
- android:clickable="true">
-
+
+
+ android:background="@color/gallery_bucket_list_item_normal_color" />
+ android:orientation="vertical" />
-
+ android:textColor="#FFFFFF"
+ android:text="@string/gallery_image_selected" />
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_fragment_media_preview.xml b/library/src/main/res/layout/gallery_fragment_media_preview.xml
index 8022335c..4f1bd072 100644
--- a/library/src/main/res/layout/gallery_fragment_media_preview.xml
+++ b/library/src/main/res/layout/gallery_fragment_media_preview.xml
@@ -8,7 +8,7 @@
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"/>
+ android:orientation="vertical" />
-
+
+
diff --git a/library/src/main/res/layout/gallery_item_media_grid.xml b/library/src/main/res/layout/gallery_item_media_grid.xml
new file mode 100644
index 00000000..f2983d28
--- /dev/null
+++ b/library/src/main/res/layout/gallery_item_media_grid.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_item_media_grid_fresco.xml b/library/src/main/res/layout/gallery_item_media_grid_fresco.xml
new file mode 100644
index 00000000..20fcf973
--- /dev/null
+++ b/library/src/main/res/layout/gallery_item_media_grid_fresco.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_loading_view_final_footer_default.xml b/library/src/main/res/layout/gallery_loading_view_final_footer_default.xml
index 378d1b15..e08bc5e4 100644
--- a/library/src/main/res/layout/gallery_loading_view_final_footer_default.xml
+++ b/library/src/main/res/layout/gallery_loading_view_final_footer_default.xml
@@ -1,24 +1,24 @@
+ android:layout_height="wrap_content" />
+ android:textColor="#E2E2E2"
+ android:textSize="16sp" />
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_media_image_preview_item.xml b/library/src/main/res/layout/gallery_media_image_preview_item.xml
index e3b9f4e1..f3c093df 100644
--- a/library/src/main/res/layout/gallery_media_image_preview_item.xml
+++ b/library/src/main/res/layout/gallery_media_image_preview_item.xml
@@ -2,4 +2,4 @@
\ No newline at end of file
+ android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_ucrop_activity_photobox.xml b/library/src/main/res/layout/gallery_ucrop_activity_photobox.xml
deleted file mode 100755
index cc03a40e..00000000
--- a/library/src/main/res/layout/gallery_ucrop_activity_photobox.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/library/src/main/res/layout/gallery_ucrop_aspect_ratio.xml b/library/src/main/res/layout/gallery_ucrop_aspect_ratio.xml
deleted file mode 100755
index 5ccf9915..00000000
--- a/library/src/main/res/layout/gallery_ucrop_aspect_ratio.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_ucrop_controls.xml b/library/src/main/res/layout/gallery_ucrop_controls.xml
deleted file mode 100755
index c39ec964..00000000
--- a/library/src/main/res/layout/gallery_ucrop_controls.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/library/src/main/res/layout/gallery_ucrop_layout_rotate_wheel.xml b/library/src/main/res/layout/gallery_ucrop_layout_rotate_wheel.xml
deleted file mode 100755
index 32e4c7ea..00000000
--- a/library/src/main/res/layout/gallery_ucrop_layout_rotate_wheel.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_ucrop_layout_scale_wheel.xml b/library/src/main/res/layout/gallery_ucrop_layout_scale_wheel.xml
deleted file mode 100755
index 047203c3..00000000
--- a/library/src/main/res/layout/gallery_ucrop_layout_scale_wheel.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/layout/gallery_ucrop_view.xml b/library/src/main/res/layout/gallery_ucrop_view.xml
deleted file mode 100755
index 4884fd88..00000000
--- a/library/src/main/res/layout/gallery_ucrop_view.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/menu/gallery_ucrop_menu_activity.xml b/library/src/main/res/menu/gallery_ucrop_menu_activity.xml
deleted file mode 100755
index fd363d55..00000000
--- a/library/src/main/res/menu/gallery_ucrop_menu_activity.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
\ No newline at end of file
diff --git a/library/src/main/res/values-en/gallery_strings.xml b/library/src/main/res/values-en/gallery_strings.xml
new file mode 100644
index 00000000..399e37da
--- /dev/null
+++ b/library/src/main/res/values-en/gallery_strings.xml
@@ -0,0 +1,25 @@
+
+ Load more
+ No more
+ Loading…
+
+ Complete
+ Complete(%1$d/%2$d)
+ You can only choose %1$d photos
+ %1$d/%2$d
+ photos
+ video
+ App request to read your album
+ >App request to Camera
+ Absolutely empty
+ The device has no camera
+ Camera not available
+ preview
+ All pictures
+ All video
+ Photograph
+ Selected
+ pictures
+ cut
+ record video
+
diff --git a/library/src/main/res/values/gallery_attrs.xml b/library/src/main/res/values/gallery_attrs.xml
index 439d2edf..75e7f855 100644
--- a/library/src/main/res/values/gallery_attrs.xml
+++ b/library/src/main/res/values/gallery_attrs.xml
@@ -1,23 +1,23 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -56,64 +56,73 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
\ No newline at end of file
diff --git a/library/src/main/res/values/gallery_default_theme.xml b/library/src/main/res/values/gallery_default_theme.xml
index c024499f..fa759c10 100644
--- a/library/src/main/res/values/gallery_default_theme.xml
+++ b/library/src/main/res/values/gallery_default_theme.xml
@@ -1,14 +1,15 @@
-
-
+
#2A2A2F
- @dimen/abc_action_bar_default_height_material
- @drawable/gallery_ucrop_ic_cross
+ @dimen/abc_action_bar_default_height_material
+
+ @drawable/gallery_ic_cross
#ffffff
12sp
#ffffff
- @dimen/abc_text_size_title_material_toolbar
+ @dimen/abc_text_size_title_material_toolbar
+
0.3dp
1dp
#151515
@@ -21,7 +22,7 @@
#CC5833
#FF6E40
#151515
-
+ #282829
#F2F2F2
#D8D8D8
#D8D8D8
diff --git a/library/src/main/res/values/gallery_strings.xml b/library/src/main/res/values/gallery_strings.xml
index 92be0ade..d7cfe7b8 100644
--- a/library/src/main/res/values/gallery_strings.xml
+++ b/library/src/main/res/values/gallery_strings.xml
@@ -10,6 +10,7 @@
图片
视频
App请求读取你的相册
+ App请求拍照权限,否则无法拍照
空空如也
该设备无摄像头
相机不可用
@@ -17,4 +18,8 @@
所有图片
所有视频
拍摄照片
+ 选中
+ 张
+ 裁剪
+ 录制视频
diff --git a/library/src/main/res/values/gallery_styles.xml b/library/src/main/res/values/gallery_styles.xml
new file mode 100644
index 00000000..249fd4e6
--- /dev/null
+++ b/library/src/main/res/values/gallery_styles.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/library/src/main/res/values/gallery_ucrop_attrs.xml b/library/src/main/res/values/gallery_ucrop_attrs.xml
deleted file mode 100755
index bcaa4ab3..00000000
--- a/library/src/main/res/values/gallery_ucrop_attrs.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/values/gallery_ucrop_dimens.xml b/library/src/main/res/values/gallery_ucrop_dimens.xml
deleted file mode 100755
index b18a0386..00000000
--- a/library/src/main/res/values/gallery_ucrop_dimens.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- 16dp
- 8dp
- 20dp
- 2dp
- 10dp
- 64dp
- 72dp
- 3dp
- 13sp
- 10sp
- 50dp
- 40dp
- 30dp
-
-
- 1dp
- 1dp
- 30dp
- 100dp
- 10dp
-
-
diff --git a/library/src/main/res/values/gallery_ucrop_public.xml b/library/src/main/res/values/gallery_ucrop_public.xml
deleted file mode 100755
index b4ab285e..00000000
--- a/library/src/main/res/values/gallery_ucrop_public.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/values/gallery_ucrop_strings.xml b/library/src/main/res/values/gallery_ucrop_strings.xml
deleted file mode 100755
index 909f3e48..00000000
--- a/library/src/main/res/values/gallery_ucrop_strings.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- 原始比例
- 裁剪
-
- 裁剪
-
- Both input and output Uri must be specified
- Therefore, override color resource (ucrop_color_toolbar_widget) in your app to make it work on pre-L devices
-
diff --git a/library/src/main/res/values/gallery_ucrop_styles.xml b/library/src/main/res/values/gallery_ucrop_styles.xml
deleted file mode 100755
index 420aada2..00000000
--- a/library/src/main/res/values/gallery_ucrop_styles.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/library/src/main/res/values/gallery_ucrop_values.xml b/library/src/main/res/values/gallery_ucrop_values.xml
deleted file mode 100755
index 0d016b0e..00000000
--- a/library/src/main/res/values/gallery_ucrop_values.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- 1500
-
\ No newline at end of file
diff --git a/library/src/test/java/cn/finalteam/rxgalleryfinal/ExampleUnitTest.java b/library/src/test/java/cn/finalteam/rxgalleryfinal/ExampleUnitTest.java
deleted file mode 100644
index 323d5563..00000000
--- a/library/src/test/java/cn/finalteam/rxgalleryfinal/ExampleUnitTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package cn.finalteam.rxgalleryfinal;
-
-import org.junit.Test;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-/**
- * To work on unit tests, switch the Test Artifact in the Build Variants view.
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() throws Exception {
- SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
- System.out.println("====" + format.format(new Date()));
- }
-}
\ No newline at end of file
diff --git a/library/src/test/java/cn/finalteam/rxgalleryfinal/SimpleTest.java b/library/src/test/java/cn/finalteam/rxgalleryfinal/SimpleTest.java
deleted file mode 100644
index ed97fa88..00000000
--- a/library/src/test/java/cn/finalteam/rxgalleryfinal/SimpleTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package cn.finalteam.rxgalleryfinal;
-
-
-import android.text.format.DateFormat;
-
-import org.junit.Test;
-
-import java.util.Date;
-
-/**
- * Desction:
- * Author:pengjianbo
- * Date:16/6/3 上午10:30
- */
-public class SimpleTest {
-
- @Test
- public void testDateFormat(){
- System.out.println("====" + DateFormat.format("yyyyMMddHHmmss", new Date()));
- }
-
-}
diff --git a/rxgalleryfinal-sample.apk b/rxgalleryfinal-sample.apk
deleted file mode 100644
index e627ef92..00000000
Binary files a/rxgalleryfinal-sample.apk and /dev/null differ
diff --git a/sample/build.gradle b/sample/build.gradle
index cdcfdff9..a3f46b1a 100644
--- a/sample/build.gradle
+++ b/sample/build.gradle
@@ -1,15 +1,14 @@
apply plugin: 'com.android.application'
-apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'com.getkeepsafe.dexcount'
android {
- compileSdkVersion 24
- buildToolsVersion '24.0.1'
+ compileSdkVersion 30
+ buildToolsVersion '30.0.3'
defaultConfig {
applicationId "cn.finalteam.rxgalleryfinal.sample"
- minSdkVersion 14
- targetSdkVersion 24
+ minSdkVersion 16
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
}
@@ -24,23 +23,25 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
-
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
-
lintOptions {
abortOnError false
}
}
dependencies {
- compile fileTree(include: ['*.jar'], dir: 'libs')
- testCompile 'junit:junit:4.12'
- compile 'com.squareup.picasso:picasso:2.5.2'
- compile 'com.facebook.fresco:fresco:0.12.0'
- compile 'com.github.bumptech.glide:glide:3.7.0'
- compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
- compile project(':library')
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
+ testImplementation 'junit:junit:4.12'
+ implementation 'com.squareup.picasso:picasso:2.5.2'
+ implementation 'com.facebook.fresco:fresco:1.3.0'
+ implementation 'com.facebook.fresco:animated-gif:1.3.0'
+ implementation 'com.github.bumptech.glide:glide:3.7.0'
+ implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
+ debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.1'
+ releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+ testImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+ implementation project(':library')
}
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index cddba38e..e6792731 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -2,21 +2,24 @@
-
-
+
-
+
+
-
+ android:requestLegacyExternalStorage="true"
+ android:theme="@style/Theme_Light">
+
+
@@ -24,15 +27,15 @@
-
+ android:theme="@style/Theme_Light.Test" />
+ android:screenOrientation="fullSensor" />
+
\ No newline at end of file
diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/IApplication.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/IApplication.java
index 5455ffd7..48e9dc76 100644
--- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/IApplication.java
+++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/IApplication.java
@@ -2,9 +2,18 @@
import android.app.Application;
+import com.facebook.drawee.backends.pipeline.Fresco;
+import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
+import com.nostra13.universalimageloader.core.ImageLoader;
+import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
+import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
+import com.squareup.leakcanary.LeakCanary;
+
+import cn.finalteam.rxgalleryfinal.utils.ModelUtils;
+
/**
* Desction:
- * Author:pengjianbo
+ * Author:pengjianbo Dujinyang
* Date:16/5/16 上午9:17
*/
public class IApplication extends Application {
@@ -12,5 +21,20 @@ public class IApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
+ //打开日志
+ ModelUtils.setDebugModel(true);
+ Fresco.initialize(this);
+ ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(this);
+ config.threadPriority(Thread.NORM_PRIORITY - 2);
+ config.denyCacheImageMultipleSizesInMemory();
+ config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
+ config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
+ config.tasksProcessingOrder(QueueProcessingType.LIFO);
+ ImageLoader.getInstance().init(config.build());
+
+ if (LeakCanary.isInAnalyzerProcess(this)) {
+ return;
+ }
+ LeakCanary.install(this);
}
}
diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java
index e52aa1f2..93d26789 100644
--- a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java
+++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/MainActivity.java
@@ -1,86 +1,229 @@
package cn.finalteam.rxgalleryfinal.sample;
+import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.widget.Button;
+import android.view.View;
import android.widget.RadioButton;
import android.widget.Toast;
-import com.facebook.drawee.backends.pipeline.Fresco;
-import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
-import com.nostra13.universalimageloader.core.ImageLoader;
-import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
-import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.List;
import cn.finalteam.rxgalleryfinal.RxGalleryFinal;
+import cn.finalteam.rxgalleryfinal.bean.MediaBean;
import cn.finalteam.rxgalleryfinal.imageloader.ImageLoaderType;
-import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultSubscriber;
+import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultDisposable;
import cn.finalteam.rxgalleryfinal.rxbus.event.ImageMultipleResultEvent;
import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent;
+import cn.finalteam.rxgalleryfinal.sample.imageloader.ImageLoaderActivity;
+import cn.finalteam.rxgalleryfinal.ui.RxGalleryListener;
+import cn.finalteam.rxgalleryfinal.ui.activity.MediaActivity;
+import cn.finalteam.rxgalleryfinal.ui.base.IMultiImageCheckedListener;
+import cn.finalteam.rxgalleryfinal.ui.base.IRadioImageCheckedListener;
+import cn.finalteam.rxgalleryfinal.utils.Logger;
+import cn.finalteam.rxgalleryfinal.utils.PermissionCheckUtils;
+
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends AppCompatActivity implements View.OnClickListener {
- RadioButton mRbRadio,mRbMuti;
- Button mBtnOpen;
+ RadioButton mRbRadioIMG, mRbMutiIMG, mRbOpenC, mRbRadioVD, mRbMutiVD;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- initImageLoader();
- initFresco();
-
- mBtnOpen = (Button) findViewById(R.id.btn_open);
- mRbRadio = (RadioButton) findViewById(R.id.rb_radio);
- mRbMuti = (RadioButton) findViewById(R.id.rb_muti);
-
- mBtnOpen.setOnClickListener(view -> {
- if(mRbRadio.isChecked()) {
- RxGalleryFinal
- .with(MainActivity.this)
- .image()
- .radio()
- .crop()
- .imageLoader(ImageLoaderType.GLIDE)
- .subscribe(new RxBusResultSubscriber() {
+ findViewById(R.id.btn_image_loader).setOnClickListener(this);
+
+ findViewById(R.id.btn_open_img).setOnClickListener(this);
+ findViewById(R.id.btn_open_vd).setOnClickListener(this);
+
+ mRbRadioIMG = (RadioButton) findViewById(R.id.rb_radio_img);
+ mRbMutiIMG = (RadioButton) findViewById(R.id.rb_muti_img);
+ mRbRadioVD = (RadioButton) findViewById(R.id.rb_radio_vd);
+ mRbMutiVD = (RadioButton) findViewById(R.id.rb_muti_vd);
+ mRbOpenC = (RadioButton) findViewById(R.id.rb_openC);
+ //多选事件的回调
+ RxGalleryListener
+ .getInstance()
+ .setMultiImageCheckedListener(
+ new IMultiImageCheckedListener() {
@Override
- protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception {
- Toast.makeText(getBaseContext(), imageRadioResultEvent.getResult().getOriginalPath(), Toast.LENGTH_SHORT).show();
+ public void selectedImg(Object t, boolean isChecked) {
+ Toast.makeText(getBaseContext(), isChecked ? "选中" : "取消选中", Toast.LENGTH_SHORT).show();
}
- })
- .openGallery();
- } else {
- RxGalleryFinal
- .with(MainActivity.this)
- .image()
- .multiple()
- .maxSize(8)
- .imageLoader(ImageLoaderType.GLIDE)
- .subscribe(new RxBusResultSubscriber() {
+
@Override
- protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception {
- Toast.makeText(getBaseContext(), "已选择" + imageMultipleResultEvent.getResult().size() +"张图片", Toast.LENGTH_SHORT).show();
+ public void selectedImgMax(Object t, boolean isChecked, int maxSize) {
+ Toast.makeText(getBaseContext(), "你最多只能选择" + maxSize + "张图片", Toast.LENGTH_SHORT).show();
}
- })
- .openGallery();
- }
- });
+ });
+ //裁剪图片的回调
+ RxGalleryListener
+ .getInstance()
+ .setRadioImageCheckedListener(
+ new IRadioImageCheckedListener() {
+ @Override
+ public void cropAfter(Object t) {
+ Toast.makeText(getBaseContext(), t.toString(), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public boolean isActivityFinish() {
+
+ return true;
+ }
+ });
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.btn_image_loader:
+ Intent intent = new Intent(v.getContext(), ImageLoaderActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ break;
+
+ case R.id.btn_open_img:
+ openImageSelect();
+ break;
+ case R.id.btn_open_vd:
+ openVideoSelect();
+ break;
+
+ }
}
- private void initImageLoader() {
- ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(this);
- config.threadPriority(Thread.NORM_PRIORITY - 2);
- config.denyCacheImageMultipleSizesInMemory();
- config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
- config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
- config.tasksProcessingOrder(QueueProcessingType.LIFO);
- ImageLoader.getInstance().init(config.build());
+
+ /**
+ * 视频
+ * 单选 多选
+ */
+ private void openVideoSelect() {
+ if (mRbRadioVD.isChecked()) {
+ openVideoSelectRadioMethod();
+ } else if (mRbMutiVD.isChecked()) {
+ openVideoSelectMultiMethod(0);
+ }
}
- private void initFresco() {
- Fresco.initialize(this);
+ /**
+ * 图片
+ * 单选,多选, 直接打开相机
+ */
+ private void openImageSelect() {
+
+ if (mRbRadioIMG.isChecked()) {
+ RxGalleryFinal
+ .with(MainActivity.this)
+ .image()
+ .radio()
+ .crop()
+ .imageLoader(ImageLoaderType.GLIDE)
+ .subscribe(new RxBusResultDisposable() {
+ @Override
+ protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception {
+ Logger.i("只要选择图片就会触发");
+ }
+ })
+ .openGallery();
+ } else if (mRbMutiIMG.isChecked()) {
+ RxGalleryFinal
+ .with(MainActivity.this)
+ .image()
+ .multiple()
+ .maxSize(9)
+ .imageLoader(ImageLoaderType.GLIDE)
+ .subscribe(new RxBusResultDisposable() {
+ @Override
+ protected void onEvent(ImageMultipleResultEvent imageMultipleResultEvent) throws Exception {
+ Logger.i("多选图片的回调");
+ }
+ })
+ .openGallery();
+ } else {
+ //if (PermissionCheckUtils.checkCameraPermission(this, "", MediaActivity.REQUEST_CAMERA_ACCESS_PERMISSION)
+ // && PermissionCheckUtils.checkWriteExternalPermission(this, "", MediaActivity.REQUEST_STORAGE_WRITE_ACCESS_PERMISSION)
+ // && PermissionCheckUtils.checkReadExternalPermission(this, "", MediaActivity.REQUEST_STORAGE_READ_ACCESS_PERMISSION)) {
+ // RxGalleryFinalApi.openZKCamera(MainActivity.this);
+ // }
+ }
+ }
+
+ private List list = null;
+
+ /**
+ * 视频多选回调
+ */
+ private void openVideoSelectMultiMethod(int type) {
+ RxGalleryFinal
+ .with(MainActivity.this)
+ .video()
+ .radio()
+ .imageLoader(ImageLoaderType.GLIDE)
+ .subscribe(new RxBusResultDisposable() {
+ @Override
+ protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception {
+ Logger.i("只要选择图片就会触发");
+ }
+ })
+ .openGallery();
}
+ /**
+ * 视频单选回调
+ */
+ private void openVideoSelectRadioMethod() {
+ RxGalleryFinal
+ .with(MainActivity.this)
+ .video()
+ .radio()
+ .imageLoader(ImageLoaderType.GLIDE)
+ .subscribe(new RxBusResultDisposable() {
+ @Override
+ protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception {
+ Logger.i("只要选择图片就会触发");
+ }
+ })
+ .openGallery();
+ }
+
+ /**
+ * OPEN 图片多选实现方法
+ *
+ * 默认使用 第三个 ,如果运行sample,可自行改变Type,运行Demo查看效果
+ */
+ private void openImageSelectMultiMethod(int type) {
+ switch (type) {
+ case 0:
+
+ break;
+ case 1:
+ //使用自定义的参数
+
+ break;
+ case 2:
-}
+ break;
+ }
+
+ }
+
+ /**
+ * OPEN 图片单选实现方法
+ *
+ * 默认使用 第三个 ,如果运行sample,可自行改变Type,运行Demo查看效果
+ */
+ private void openImageSelectRadioMethod(int type) {
+
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ SimpleRxGalleryFinal.get().onActivityResult(requestCode, resultCode, data);
+ }
+}
\ No newline at end of file
diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/SimpleRxGalleryFinal.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/SimpleRxGalleryFinal.java
new file mode 100644
index 00000000..69775a50
--- /dev/null
+++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/SimpleRxGalleryFinal.java
@@ -0,0 +1,153 @@
+package cn.finalteam.rxgalleryfinal.sample;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.yalantis.ucrop.UCrop;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import cn.finalteam.rxgalleryfinal.utils.FileUtils;
+
+/**
+ * by y on 17/07/2017.
+ *
+ * 使用相机拍照并裁剪
+ */
+
+public class SimpleRxGalleryFinal {
+
+ private static final String IMAGE_TYPE = "image/jpeg";
+ private static final int TYPE_CAMERA = 1111;
+
+ private RxGalleryFinalCropListener listener = null;
+
+ private Uri imagePath;
+
+
+ private static final class SimpleRxGalleryFinalHolder {
+ private static final SimpleRxGalleryFinal SIMPLE_RX_GALLERY_FINAL = new SimpleRxGalleryFinal();
+ }
+
+ public static SimpleRxGalleryFinal get() {
+ return SimpleRxGalleryFinalHolder.SIMPLE_RX_GALLERY_FINAL;
+ }
+
+
+ public SimpleRxGalleryFinal init(RxGalleryFinalCropListener listener) {
+ this.listener = listener;
+ return this;
+ }
+
+
+ public void openCamera() {
+ Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ imagePath = FileUtils.fromFile(listener.getSimpleActivity(),getDiskCacheDir());
+ intent.putExtra(MediaStore.EXTRA_OUTPUT, imagePath);
+ listener
+ .getSimpleActivity()
+ .startActivityForResult(intent, TYPE_CAMERA);
+ }
+
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (resultCode) {
+ case Activity.RESULT_CANCELED:
+ if(listener!=null){
+ listener.onCropCancel();
+ }
+ break;
+ case UCrop.RESULT_ERROR:
+ if (data != null) {
+ Throwable cropError = UCrop.getError(data);
+ if (cropError != null) {
+ listener.onCropError(cropError.getMessage());
+ } else {
+ listener.onCropError("裁剪出现未知错误");
+ }
+ } else {
+ listener.onCropError("获取相册图片出现错误");
+ }
+ break;
+
+ case Activity.RESULT_OK:
+ switch (requestCode) {
+ case TYPE_CAMERA:
+ notifyImageToCamera(listener.getSimpleActivity(), imagePath);
+ UCrop of = UCrop.of(imagePath, Uri.fromFile(getDiskCacheDir()));
+
+ of.start(listener.getSimpleActivity());
+ break;
+ case UCrop.REQUEST_CROP:
+ listener.onCropSuccess(UCrop.getOutput(data));
+ break;
+ }
+ break;
+ }
+ }
+
+ private File getDiskCacheDir() {
+ String cachePath;
+ if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) {
+ File externalCacheDir = listener.getSimpleActivity().getExternalCacheDir();
+ if (externalCacheDir != null) {
+ cachePath = externalCacheDir.getPath();
+ } else {
+ cachePath = listener.getSimpleActivity().getCacheDir().getPath();
+ }
+ } else {
+ cachePath = listener.getSimpleActivity().getCacheDir().getPath();
+ }
+ return new File(cachePath, imageName());
+ }
+
+ private void notifyImageToCamera(Context context, Uri uri) {
+ try {
+ File file = new File(uri.getPath());
+ MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), null);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
+ }
+
+ private String imageName() {
+ return System.currentTimeMillis() + ".jpg";
+ }
+
+
+ public interface RxGalleryFinalCropListener {
+
+ @NonNull
+ AppCompatActivity getSimpleActivity();
+
+
+ /**
+ * 裁剪被取消
+ */
+ void onCropCancel();
+
+ /**
+ * 裁剪成功
+ *
+ * @param uri 裁剪的 Uri , 有可能会为Null
+ */
+ void onCropSuccess(@Nullable Uri uri);
+
+
+ /**
+ * 裁剪失败
+ *
+ * @param errorMessage 错误信息
+ */
+ void onCropError(@NonNull String errorMessage);
+
+ }
+}
diff --git a/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/imageloader/ImageLoaderActivity.java b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/imageloader/ImageLoaderActivity.java
new file mode 100644
index 00000000..472f0a68
--- /dev/null
+++ b/sample/src/main/java/cn/finalteam/rxgalleryfinal/sample/imageloader/ImageLoaderActivity.java
@@ -0,0 +1,86 @@
+package cn.finalteam.rxgalleryfinal.sample.imageloader;
+
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.AppCompatCheckBox;
+import android.view.View;
+import android.widget.Toast;
+
+import cn.finalteam.rxgalleryfinal.RxGalleryFinal;
+import cn.finalteam.rxgalleryfinal.imageloader.ImageLoaderType;
+import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultDisposable;
+import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent;
+import cn.finalteam.rxgalleryfinal.sample.R;
+import cn.finalteam.rxgalleryfinal.utils.Logger;
+
+/**
+ * by y on 2017/6/7.
+ */
+
+public class ImageLoaderActivity extends AppCompatActivity {
+
+ private AppCompatCheckBox appCompatCheckBox;
+ private RxGalleryFinal with;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_imageloader);
+ appCompatCheckBox = (AppCompatCheckBox) findViewById(R.id.cb_gif);
+ findViewById(R.id.btn_glide).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ start(ImageLoaderType.GLIDE);
+ }
+ });
+ findViewById(R.id.btn_picasso).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ start(ImageLoaderType.PICASSO);
+ }
+ });
+ findViewById(R.id.btn_fresco).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ start(ImageLoaderType.FRESCO);
+ }
+ });
+ findViewById(R.id.btn_universal).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ start(ImageLoaderType.UNIVERSAL);
+ }
+ });
+ }
+
+ private void start(ImageLoaderType imageLoaderType) {
+ switch (imageLoaderType) {
+ case PICASSO:
+ case UNIVERSAL:
+ Toast.makeText(getApplicationContext(), imageLoaderType + "不支持Gif", Toast.LENGTH_SHORT).show();
+ break;
+ }
+ if (with == null)
+ with = RxGalleryFinal.with(this);
+ with.image()
+ .radio()
+ .gif(appCompatCheckBox.isChecked())
+ .imageLoader(imageLoaderType)
+ .subscribe(new RxBusResultDisposable() {
+ @Override
+ protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception {
+ Toast.makeText(getBaseContext(), "选中了图片路径:" + imageRadioResultEvent.getResult().getOriginalPath(), Toast.LENGTH_SHORT).show();
+ }
+ }).openGallery();
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (with != null) {
+ Logger.i("RxGalleryFinal == null");
+ with = null;
+ }
+ super.onDestroy();
+ }
+}
diff --git a/sample/src/main/res/layout/activity_imageloader.xml b/sample/src/main/res/layout/activity_imageloader.xml
new file mode 100644
index 00000000..2910ec38
--- /dev/null
+++ b/sample/src/main/res/layout/activity_imageloader.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml
index c6c3804d..69faf21f 100644
--- a/sample/src/main/res/layout/activity_main.xml
+++ b/sample/src/main/res/layout/activity_main.xml
@@ -3,38 +3,122 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
- android:orientation="vertical"
tools:context="cn.finalteam.rxgalleryfinal.sample.MainActivity">
+
+
+
+
+
+ android:checked="true"
+ android:text="单选" />
+
+
+
+ android:text="打开摄像头" />
+
+ android:text="open 图片" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/src/main/res/values/gallery_strings.xml b/sample/src/main/res/values/gallery_strings.xml
new file mode 100644
index 00000000..399e37da
--- /dev/null
+++ b/sample/src/main/res/values/gallery_strings.xml
@@ -0,0 +1,25 @@
+
+ Load more
+ No more
+ Loading…
+
+ Complete
+ Complete(%1$d/%2$d)
+ You can only choose %1$d photos
+ %1$d/%2$d
+ photos
+ video
+ App request to read your album
+ >App request to Camera
+ Absolutely empty
+ The device has no camera
+ Camera not available
+ preview
+ All pictures
+ All video
+ Photograph
+ Selected
+ pictures
+ cut
+ record video
+
diff --git a/sample/src/main/res/values/styles.xml b/sample/src/main/res/values/styles.xml
index f11f7450..e4e1cba1 100644
--- a/sample/src/main/res/values/styles.xml
+++ b/sample/src/main/res/values/styles.xml
@@ -1,3 +1,6 @@
-
+
diff --git a/sample/src/main/res/values/themes.xml b/sample/src/main/res/values/themes.xml
index c5e38e35..2db56abb 100644
--- a/sample/src/main/res/values/themes.xml
+++ b/sample/src/main/res/values/themes.xml
@@ -5,7 +5,45 @@
-
+
+
+
+