iielse / imageviewer Goto Github PK
View Code? Open in Web Editor NEWA simple and customizable Android full-screen image viewer 一个简单且可自定义的Android全屏图像浏览器
License: MIT License
A simple and customizable Android full-screen image viewer 一个简单且可自定义的Android全屏图像浏览器
License: MIT License
MessagePicturesLayout显示图片的时候,第一次能出现图片,第二次以后基本绘制不出图片。
9宫格里面图片展示,是不支持gif嘛?,为什么我放入了一个gif,显示错乱
因为写死了ImageView,所以不支持gif图查看。
列表里面下拉刷新有时候图片会不显示,在不同机型上刷新有的会不显示,有的会显示三张比较高的图(非正方形)
在ViewPager中点击图片发生错误
public void show(ImageView i, List<ImageView> imageGroupList, final List<Uri> urlList) {
之前设计的是 第二个imageGroupList和第三个参数urlList是对应关系,且顺序也需要对应,且点击触发show的imageView必须是 imageGroupList中的元素
限制太多
public void show(ImageView i, SparseArray<ImageView> imageGroupList, final List<Uri> urlList) {
思考后发现,把第二个入参改成了 SparseArray
类型,imageGroupList的key(position) 映射 urlList中的url地址要灵活很多, 点击触发show的imageView依旧需要在imageGroupList中,来确认初始位置。 这样设计更适合聊天界面来查看图片列表。
要改变的地方 3处
/**
* @param i 被点击的ImageView
* @param imageGroupList
* @param urlList 被加载的图片url列表,数量必须大于等于 imageGroupList.size。 且顺序应当和imageGroupList保持一致
*/
public void show(ImageView i, SparseArray<ImageView> imageGroupList, final List<Uri> urlList) {
if (i == null || imageGroupList == null || urlList == null || imageGroupList.size() < 1 ||
urlList.size() < imageGroupList.size()) {
String info = "i[" + i + "]";
info += "#imageGroupList " + (imageGroupList == null ? "null" : "size : " + imageGroupList.size());
info += "#urlList " + (urlList == null ? "null" : "size :" + urlList.size());
throw new IllegalArgumentException("error params \n" + info);
}
initPosition = -1;
for (int x = 0; x < imageGroupList.size(); x++) {
if (imageGroupList.get(imageGroupList.keyAt(x)) == i) {
initPosition = imageGroupList.keyAt(x);
break;
}
}
if (initPosition < 0) {
throw new IllegalArgumentException("param ImageView i must be a member of the List <ImageView> imageGroupList!");
}
...
}
private boolean setDefaultDisplayConfigs(final ImageView imageView, final int pos, boolean hasPlayBeginAnimation) {
boolean isFindEnterImagePicture = false;
ViewState.write(imageView, ViewState.STATE_ORIGIN).alpha(0).scaleXBy(1.5f).scaleYBy(1.5f);
if (mImageGroupList.get(pos) != null) { // 这里
ImageView originRef = mImageGroupList.get(pos);
if (pos == initPosition && !hasPlayBeginAnimation) {
@Override
public void onPageSelected(int position) {
iSource = adapter.mImageSparseArray.get(position);
if (iOrigin != null) {
iOrigin.setVisibility(View.VISIBLE);
}
if (mImageGroupList.get(position) != null) { // 这里
iOrigin = mImageGroupList.get(position);
if (iOrigin.getDrawable() != null) iOrigin.setVisibility(View.INVISIBLE);
}
调用
conversationAdapter1 = ConversationAdapter1().apply {
cb = object : ConversationAdapter1.Callback {
override fun onPictureClick(view: ImageView, uri: Uri, uriList: List<Uri>, position: Int) {
// view 被点击的imageView
// uri 被点击的imageView对应展示的图片地址信息
// uriList 一整个要展示的图片列表
vImageWatcher.show(view, SparseArray<ImageView>().apply {
put(uriList.indexOf(uri), view)
}, uriList)
}
}
}
不知道为什么,第一个图片,两边总是显示不全,被遮住了。缩小也不行。搞了了好久,浪费了3个多小时,唉换框架!
我自己将 Glide.with(context).load(url).asBitmap().into(new Target() {改成了这种方式,就这一点不同,同时说明一下,我支持的24.0.0不知道是不是这样远远导致的
有个问题是fresco我们用的是自定义的imageview集成自SimpleDraweeView,不像glide可以直接load到imageview
如果不设置值
eg: demo中注释// lPictures.set(mData.getPictureThumbList(), mData.getPictureList());
Process: ch.ielse.demo.p02, PID: 378
java.lang.IllegalArgumentException: dataList.size != thumbDataList.size
at ch.ielse.demo.p02.MessagePicturesLayout.notifyDataChanged(MessagePicturesLayout.java:76)
at ch.ielse.demo.p02.MessagePicturesLayout.onSizeChanged(MessagePicturesLayout.java:146)
at android.view.View.sizeChange(View.java:17638)
at android.view.View.setFrame(View.java:17600)
at android.view.View.layout(View.java:17517)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.support.v7.widget.RecyclerView$LayoutManager.layoutDecoratedWithMargins(RecyclerView.java:8659)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1583)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3767)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:724)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2342)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2069)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6301)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
at android.view.Choreographer.doCallbacks(Choreographer.java:683)
at android.view.Choreographer.doFrame(Choreographer.java:619)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
猜猜我是谁
P02,点击小图进入大图后,两指不断扩张放大图片,然后单指滑动图片到屏幕边缘,这时候继续放大图片,图片的位置会自动回到屏幕中心。
你好,请问WebView中的图片能否实现类似的效果吗
没有按照预期的方式显示,点击之后仅仅按列表里的大小显示,并且位置水平靠左垂直居中的。
效果图如下:
http://upload-images.jianshu.io/upload_images/2018741-f22add5f1676a879.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
` new ImageWatcher.IndexProvider() {
private View view;
@Override
public View initialView(Context context) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
MyUtils.dip2px(context, 40));//
lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
view = LayoutInflater.from(context).inflate(R.layout.image_index, null);
view.setLayoutParams(lp);
return view;
}
@Override
public void onPageChanged(final ImageWatcher imageWatcher, int position, List<Uri> list) {
TextView textIndex = view.findViewById(R.id.tv_index);
TextView tvShare = view.findViewById(R.id.tv_share);
textIndex.setText(String.format("%s/%s", position + 1, list.size()));
tvShare.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ToastUtils.show("分享");
}
};`
您好,我在项目使用了 glide , 它的版本是 4.0 的, 如果我想使用您这个框架,我该怎么做?
横向超长图片双击无法看清楚的问题
比如:http://image.xcar.com.cn/attachments/a/day_20141126/2014112609_68d9843ed0c3e1d05735CObUWVqIy3rr.jpg
这个长图,双击根本看不清楚
修复代码:
ImageWatcher.java->handleDoubleTapTouchResult()
if (vsCurrent.scaleY <= vsDefault.scaleY && vsCurrent.scaleX <= vsDefault.scaleX) {
final String imageOrientation = (String) iSource.getTag(R.id.image_orientation);
float expectedScale = (MAX_SCALE - vsDefault.scaleX) * 0.4f + vsDefault.scaleX;
if (imageOrientation.equals("horizontal")) {
ViewState viewState = ViewState.read(iSource, ViewState.STATE_DEFAULT);
//图片在双击的时候放大的倍数,如果图片过长看不放大根本看不见
final float scale = viewState.width / viewState.height;
float maxScale = MAX_SCALE;
if (scale > 2.0f) {
maxScale = MAX_SCALE * scale / 2;
}
expectedScale = (maxScale - vsDefault.scaleX) * 0.4f + vsDefault.scaleX;
}
animSourceViewStateTransform(iSource, ViewState.write(iSource, ViewState.STATE_TEMP).scaleX(expectedScale).scaleY(expectedScale));
} else {
animSourceViewStateTransform(iSource, vsDefault);
}
希望可以请求合并
显示出来的时候onSizeChanged方法走两次,不显示的时候走一次
很好很强大
此处打开图片浏览器,消失不需要回到指定imageview处,请问怎么处理呢
如果能支持视频预览就更好了
e神,发现个问题.在4.4的机器上,比如说夜神模拟器,获取的content解析不了
W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (6000x4000, max=4096x4096)
相册图片显示特别小
华为系统相册返回Uri不能直接使用 uri.getPath 。不然使用BitmapFactory.decodeFile会返回空
解析方案参考 https://github.com/Yalantis/uCrop 源码
private static Bitmap obtainBmpSource(@NonNull Context context, @NonNull Uri uri, int requiredWidth, int requiredHeight) throws Exception {
final ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(uri, "r");
final FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
options.inSampleSize = calculateInSampleSize(options, requiredWidth, requiredHeight);
options.inJustDecodeBounds = false;
Bitmap decodeSampledBitmap = null;
boolean success = false;
while (!success) {
try {
decodeSampledBitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
success = true;
} catch (OutOfMemoryError error) {
Log.e("ImageCropper", "decodeSampledBitmap: BitmapFactory.decodeFileDescriptor: ", error);
options.inSampleSize++;
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
close(parcelFileDescriptor);
}
int exifOrientation = getExifOrientation(context, uri);
int exifDegrees = exifToDegrees(exifOrientation);
int exifTranslation = exifToTranslation(exifOrientation);
Matrix matrix = new Matrix();
if (exifDegrees != 0) {
matrix.preRotate(exifDegrees);
}
if (exifTranslation != 1) {
matrix.postScale(exifTranslation, 1);
}
if (!matrix.isIdentity()) {
decodeSampledBitmap = transformBitmap(decodeSampledBitmap, matrix);
}
return decodeSampledBitmap;
}
修改核心代码
RxImagePickerFragment
替换方法入参
private void onQueryOrTakeSuccess(@NonNull String type, @NonNull List<String> pictures) {
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
private void onQueryOrTakeSuccess(@NonNull String type, @NonNull List<Uri> pictures) {
九宫格布局 界面
您的debug-apk运行崩溃,重新编译也崩溃。
1.单选图片确定后崩溃
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
at ch.ielse.view.imagecropper.ImageCropper.cropInternal(ImageCropper.java:101)
at ch.ielse.view.imagecropper.ImageCropper.access$000(ImageCropper.java:25)
at ch.ielse.view.imagecropper.ImageCropper$1.run(ImageCropper.java:139)
2.选择拍照后崩溃
io.reactivex.exceptions.OnErrorNotImplementedException: file:///storage/emulated/0/Android/data/ch.ielse.demo.p01/cache/rxPicker/TEMP1595091369.jpg exposed beyond app through ClipData.Item.getUri()
at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704)
at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701)
at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:74)
at io.reactivex.observers.SerializedObserver.onError(SerializedObserver.java:155)
at io.reactivex.internal.operators.observable.ObservableTakeUntil$TakeUntilObserver.onError(ObservableTakeUntil.java:73)
at io.reactivex.subjects.PublishSubject.subscribeActual(PublishSubject.java:95)
at io.reactivex.Observable.subscribe(Observable.java:10842)
at io.reactivex.internal.operators.observable.ObservableTakeUntil.subscribeActual(ObservableTakeUntil.java:41)
at io.reactivex.Observable.subscribe(Observable.java:10842)
at io.reactivex.Observable.subscribe(Observable.java:10828)
at io.reactivex.Observable.subscribe(Observable.java:10731)
at ch.ielse.demo.p01.MainActivity.takeCamera(MainActivity.java:107)
at ch.ielse.demo.p01.MainActivity.access$000(MainActivity.java:26)
at ch.ielse.demo.p01.MainActivity$1$1.accept(MainActivity.java:78)
at ch.ielse.demo.p01.MainActivity$1$1.accept(MainActivity.java:75)
at io.reactivex.internal.observers.ConsumerSingleObserver.onSuccess(ConsumerSingleObserver.java:61)
at io.reactivex.internal.operators.single.SingleTakeUntil$TakeUntilMainObserver.onSuccess(SingleTakeUntil.java:92)
at io.reactivex.internal.operators.observable.ObservableAllSingle$AllObserver.onComplete(ObservableAllSingle.java:99)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.drainLoop(ObservableFlatMap.java:367)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.drain(ObservableFlatMap.java:323)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onComplete(ObservableFlatMap.java:300)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.drainLoop(ObservableFlatMap.java:367)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.drain(ObservableFlatMap.java:323)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onComplete(ObservableFlatMap.java:300)
at io.reactivex.internal.operators.observable.ObservableFromArray$FromArrayDisposable.run(ObservableFromArray.java:110)
at io.reactivex.internal.operators.observable.ObservableFromArray.subscribeActual(ObservableFromArray.java:36)
at io.reactivex.Observable.subscribe(Observable.java:10842)
at io.reactivex.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:55)
at io.reactivex.Observable.subscribe(Observable.java:10842)
at io.reactivex.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:55)
at io.reactivex.Observable.subscribe(Observable.java:10842)
at io.reactivex.internal.operators.observable.ObservableAllSingle.subscribeActual(ObservableAllSingle.java:34)
at io.reactivex.Single.subscribe(Single.java:2703)
at io.reactivex.internal.operators.single.SingleTakeUntil.subscribeActual(SingleTakeUntil.java:51)
at io.reactivex.Single.subscribe(Single.java:2703)
at io.reactivex.Single.subscribe(Single.java:2689)
at io.reactivex.Single.subscribe(Single.java:2660)
at ch.ielse.demo.p01.MainActivity.requestPermissions(MainActivity.java:155)
at ch.ielse.demo.p01.MainActivity$1.onClick(MainActivity.java:74)
at ch.ielse.demo.p01.SheetDialog$Builder$1.onClick(SheetDialog.java:142)
at android.view.View.performClick(View.java:5730)
at android.view.View$PerformClick.run(View.java:22806)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6519)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1113)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:974)
Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/ch.ielse.demo.p01/cache/rxPicker/TEMP1595091369.jpg exposed beyond app through ClipData.Item.getUri()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:1847)
at android.net.Uri.checkFileUriExposed(Uri.java:2346)
at android.content.ClipData.prepareToLeaveProcess(ClipData.java:833)
at android.content.Intent.prepareToLeaveProcess(Intent.java:8976)
at android.content.Intent.prepareToLeaveProcess(Intent.java:8961)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1647)
at android.app.Activity.startActivityForResult(Activity.java:4888)
at android.app.Activity.startActivityFromFragment(Activity.java:4874)
at android.app.Activity$HostCallbacks.onStartActivityFromFragment(Activity.java:7176)
at android.app.Fragment.startActivityForResult(Fragment.java:1150)
at android.app.Fragment.startActivityForResult(Fragment.java:1139)
at ch.ielse.view.imagecropper.RxImagePickerFragment.takeCamera(RxImagePickerFragment.java:170)
at ch.ielse.view.imagecropper.RxImagePicker.takeCamera(RxImagePicker.java:59)
at ch.ielse.demo.p01.MainActivity.takeCamera(MainActivity.java:104)
... 37 more
我写图片查看时也遇到过4096问题,且有时候的需求就是需要显示原始尺寸,不能压缩,所以寻求了这个轮子进行大图的区块加载:subsampling-scale-image-view,你可以参考参考
不好集成啊~E神,继续优化...
fragment之间hide和show,两个fragment都有MessagePicturesLayout是后一个首次显示是图片绘制不出来
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.