修改图片详情页面的实现方式,适配大图/长图

This commit is contained in:
kehaoyuan
2020-01-04 18:06:50 +08:00
parent 6c2d489940
commit 9f4c9431b9
9 changed files with 192 additions and 477 deletions

View File

@ -1,11 +1,12 @@
package com.gh.gamecenter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
@ -18,40 +19,39 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.facebook.binaryresource.BinaryResource;
import com.facebook.cache.common.CacheKey;
import com.facebook.common.executors.CallerThreadExecutor;
import com.facebook.common.references.CloseableReference;
import com.facebook.datasource.DataSource;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.gh.base.BaseActivity;
import com.gh.common.Base64ImageHolder;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.MD5Utils;
import com.gh.common.util.MessageShareUtils;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PermissionHelper;
import com.gh.common.view.EmptyDrawable;
import com.gh.common.util.SimpleImageLoader;
import com.gh.common.view.Gh_RelativeLayout;
import com.gh.common.view.Gh_RelativeLayout.OnSingleTapListener;
import com.gh.common.view.Gh_ViewPager;
import com.gh.common.view.ZoomSimpleDraweeView;
import com.gh.gamecenter.entity.ImageInfoEntity;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.github.piasy.biv.view.BigImageView;
import com.github.piasy.biv.view.FrescoImageViewFactory;
import com.lightgame.utils.Utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
@ -59,11 +59,6 @@ import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
import butterknife.BindView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@ -90,14 +85,13 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
private ViewImageAdapter adapter;
private ImagePipeline mImagePipeline;
private boolean mShowBase64Image = false;
private static final String KEY_BASE64 = "base64";
private static final String KEY_URLS = "urls";
private static final String KEY_CURRENT = "current";
private static final String KEY_SCALETYPE = "ScaleType";
private ArrayList<String> urls;
private HashSet<Integer> mViewedSet; // 让调用者知道该图片是否被看过了
@ -106,7 +100,7 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
private int mLimitWidth;
private boolean isOrientation;
public static Intent getBase64ViewImageIntent(Context context, boolean showSingleBase64Image) {
Intent checkIntent = new Intent(context, ViewImageActivity.class);
checkIntent.putExtra(KEY_BASE64, showSingleBase64Image);
@ -131,7 +125,6 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
super.onCreate(savedInstanceState);
mViewedSet = new HashSet<>();
mImageInfoMap = new HashMap<>();
// init data
int current = 0;
Bundle extras = getIntent().getExtras();
@ -183,31 +176,29 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
if (object != null) {
mProgressHint.setWidth(mProgressHint.getWidth());
RelativeLayout view = (RelativeLayout) object;
final ZoomSimpleDraweeView draweeView = view.findViewById(R.id.viewimage_iv_show);
draweeView.getHierarchy().setProgressBarImage(new EmptyDrawable(progress -> {
if (position == mViewPager.getCurrentItem()) { // 防止下载过程中切换图片
int percent = progress / 100;
if (percent < 100) {
mProgressHint.setText((percent + "%"));
} else {
mProgressHint.setText("已完成");
mBaseHandler.postDelayed(() -> {
if (position == mViewPager.getCurrentItem()) { // 防止等待过程中切换图片
mProgressHint.setVisibility(View.GONE);
}
}, 500);
final BigImageView imageView = view.findViewById(R.id.viewimage_iv_show);
String url = urls.get(position);
imageView.showImage(Uri.parse(url));
imageView.setImageLoaderCallback(new SimpleImageLoader() {
@Override
public void onProgress(int progress) {
if (position == mViewPager.getCurrentItem()) { // 防止下载过程中切换图片
if (progress < 100) {
mProgressHint.setText((progress + "%"));
} else {
mProgressHint.setText("已完成");
mBaseHandler.postDelayed(() -> {
if (position == mViewPager.getCurrentItem()) { // 防止等待过程中切换图片
mProgressHint.setVisibility(View.GONE);
}
}, 500);
}
}
}
}));
draweeView.setController(Fresco.newDraweeControllerBuilder()
// 高清图片
.setImageRequest(ImageRequest.fromUri(urls.get(position)))
// 低分辨率图片
.setLowResImageRequest(ImageRequest.fromUri(ImageUtils.addLimitWidth(urls.get(position), mLimitWidth)))
.build());
});
}
});
DisplayUtils.transparentStatusAndNavigation(this);
}
@ -263,8 +254,10 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
return;
}
ZoomSimpleDraweeView zoomDraweeView = ghRelativeLayout.findViewById(R.id.viewimage_iv_show);
zoomDraweeView.reset(); // 重置矩阵,还原图片
BigImageView imageView = ghRelativeLayout.findViewById(R.id.viewimage_iv_show);
SubsamplingScaleImageView ssiv = imageView.getSSIV();
if (ssiv != null) ssiv.resetScaleAndCenter();
}
}
mIndicatorTv.setText(String.format("%d/%d", position + 1, urls.size()));
@ -295,16 +288,10 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
});
}
private void loadImage(String url, final ZoomSimpleDraweeView imageView) {
if (url.contains(".gif")) {
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(url)
.setAutoPlayAnimations(true)
.build();
imageView.setController(controller);
} else {
imageView.setImageURI(url); // 加载原图
}
private void loadImage(String url, final BigImageView imageView) {
// 添加GIF支持
imageView.setImageViewFactory(new FrescoImageViewFactory());
imageView.showImage(Uri.parse(url));
}
private class ViewImageAdapter extends PagerAdapter implements OnSingleTapListener {
@ -317,6 +304,7 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
return urls.size();
}
@SuppressLint("MissingPermission")
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
@ -324,28 +312,45 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
ImageRequest imageRequest = ImageRequest.fromUri(url);
boolean isInMemoryCache = mImagePipeline.isInBitmapMemoryCache(imageRequest);
boolean isInDiskCache = imageRequest != null && mImagePipeline.isInDiskCacheSync(imageRequest);
Gh_RelativeLayout view = (Gh_RelativeLayout) View.inflate(container.getContext(), R.layout.viewimage_normal_item, null);
ZoomSimpleDraweeView imageView = view.findViewById(R.id.viewimage_iv_show);
if (isInMemoryCache
|| isInDiskCache
|| NetworkUtils.isWifiOr4GConnected(ViewImageActivity.this)
|| url.contains(".gif")) {
loadImage(url, imageView);
} else {
ImageUtils.addLimitWidthAndLoad(imageView, url, mLimitWidth, imageInfo -> {
if (imageInfo != null && mImageInfoMap.get(url) == null) {
loadImageInfo(position, imageInfo.getWidth()); // 加载图片参数,目的是用户显示原文按钮
}
});
Gh_RelativeLayout view = (Gh_RelativeLayout) View.inflate(container.getContext(), R.layout.viewimage_normal_item, null);
BigImageView imageView = view.findViewById(R.id.viewimage_iv_show);
if (!isInMemoryCache
&& !isInDiskCache
&& !NetworkUtils.isWifiOr4GConnected(ViewImageActivity.this)
&& !url.contains(".gif")) {
url = ImageUtils.getTransformLimitUrl(url, mLimitWidth, getApplicationContext());
}
//单点退出
imageView.setOnSingleClickListener(ViewImageActivity.this::finish);
String finalUrl = url;
imageView.setImageLoaderCallback(new SimpleImageLoader() {
@Override
public void onSuccess(File image) {
if (!finalUrl.equals(urls.get(position))) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(image.getPath()).getAbsolutePath(), options);
loadImageInfo(position, options.outWidth); // 加载图片参数,目的是用户显示原文按钮
}
SubsamplingScaleImageView ssiv = imageView.getSSIV();
if (ssiv != null) {
ssiv.setMaxScale(10f); // 这个缩放倍数最好很具宽高自动调节
ssiv.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() {
@Override
public void onReady() {
ssiv.resetScaleAndCenter();
}
});
ssiv.setOnClickListener(v -> finish());
}
}
});
loadImage(url, imageView);
//长按
imageView.setOnLongClickListener(() -> {
imageView.setOnLongClickListener(v -> {
final Dialog dialog = new Dialog(ViewImageActivity.this);
LinearLayout container1 = new LinearLayout(ViewImageActivity.this);
@ -353,8 +358,11 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
container1.setBackgroundColor(Color.WHITE);
final TextView reportTv = new TextView(ViewImageActivity.this);
reportTv.setPadding(DisplayUtils.dip2px(ViewImageActivity.this, 20), DisplayUtils.dip2px(ViewImageActivity.this, 12),
0, DisplayUtils.dip2px(ViewImageActivity.this, 12));
reportTv.setPadding(
DisplayUtils.dip2px(ViewImageActivity.this, 20),
DisplayUtils.dip2px(ViewImageActivity.this, 12),
0,
DisplayUtils.dip2px(ViewImageActivity.this, 12));
reportTv.setText(R.string.save_pic);
reportTv.setTextSize(17);
reportTv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.title));
@ -371,13 +379,15 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
dialog.show();
}
reportTv.setOnClickListener(v -> {
reportTv.setOnClickListener(v1 -> {
PermissionHelper.checkStoragePermissionBeforeAction(ViewImageActivity.this, () -> {
findImageBM();
saveImageToFile(imageView.getCurrentImageFile(), finalUrl);
dialog.cancel();
});
dialog.cancel();
});
return false;
});
view.setTag(position);
@ -385,100 +395,51 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
return view;
}
private void findImageBM() {
String url = urls.get(mViewPager.getCurrentItem());
String limitUrl = ImageUtils.addLimitWidth(urls.get(mViewPager.getCurrentItem()), mLimitWidth);
String targetUrl;
if (mImagePipeline.isInBitmapMemoryCache(ImageRequest.fromUri(url))) {
targetUrl = url;
} else if (mImagePipeline.isInBitmapMemoryCache(ImageRequest.fromUri(limitUrl))) {
targetUrl = limitUrl;
} else {
targetUrl = url;
}
ImageRequest imageRequest = ImageRequestBuilder
.newBuilderWithSource(Uri.parse(targetUrl))
.setProgressiveRenderingEnabled(true)
.build();
DataSource<CloseableReference<CloseableImage>>
dataSource = mImagePipeline.fetchDecodedImage(imageRequest, ViewImageActivity.this);
final String finalCurUrl = targetUrl;
dataSource.subscribe(new BaseBitmapDataSubscriber() {
@Override
protected void onNewResultImpl(Bitmap bitmap) {
if (bitmap != null) { // gif bitmap is null
saveImage(bitmap, finalCurUrl);
} else {
ImageRequest imageRequest = ImageRequest.fromUri(Uri.parse(finalCurUrl));
CacheKey encodedCacheKey = mImagePipeline.getCacheKeyFactory().getEncodedCacheKey(imageRequest, null);
BinaryResource resource = Fresco.getImagePipelineFactory().getMainFileCache().getResource(encodedCacheKey);
try {
String fileName = finalCurUrl.substring(finalCurUrl.lastIndexOf("/"));
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
File targetFile = new File(savePath, fileName);
OutputStream outStream = new FileOutputStream(targetFile);
outStream.write(resource.read());
Utils.toast(ViewImageActivity.this, "图片已保存到/Pictures/ghzhushou/");
MessageShareUtils.refreshImage(ViewImageActivity.this, targetFile);
} catch (Exception e) {
Utils.log("图片保存失败:" + e.toString());
e.printStackTrace();
}
}
}
@Override
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
}
}, CallerThreadExecutor.getInstance());
}
private void saveImage(Bitmap bitmap, String curUrl) {
String fileName = "";
if (mShowBase64Image) {
fileName = MD5Utils.getUrlMD5(curUrl.substring(0, 50)) + ".png";
} else {
fileName = curUrl.substring(curUrl.lastIndexOf("/"));
}
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
private void saveImageToFile(File src, String curUrl) {
InputStream in = null;
OutputStream out = null;
try {
String fileName;
if (mShowBase64Image) {
fileName = MD5Utils.getUrlMD5(curUrl.substring(0, 50)) + ".png";
} else {
fileName = curUrl.substring(curUrl.lastIndexOf("/"));
}
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
File file = new File(savePath);
if (!file.exists()) {
file.mkdirs();
}
File f = new File(savePath, fileName);
if (f.exists()) {
f.delete();
File dst = new File(savePath, fileName);
if (dst.exists()) {
dst.delete();
}
in = new FileInputStream(src);
out = new FileOutputStream(dst);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
FileOutputStream out = new FileOutputStream(f);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
Utils.log("图片保存成功");
Utils.toast(ViewImageActivity.this, "图片已保存到/Pictures/ghzhushou/");
MessageShareUtils.refreshImage(ViewImageActivity.this, f);
} catch (IOException e) {
} catch (Exception e) {
Utils.log("图片保存失败:" + e.toString());
e.printStackTrace();
} finally {
try {
if (out != null) out.close();
if (in != null) in.close();
} catch (Exception ignore) {
}
}
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
object = null;
}
@Override