PhotoView 与九宫格和ViewPager

photoView的九宫格全屏展示、结合ViewPager的使用(填坑)

photoView(‘com.github.chrisbanes.photoview:library:1.2.4’)作为github高分的手势操作的ImgView,开发中经常会用到该控件,这里记录一下开发类似好友动态的列表图片展示所遇到的关于photoView的坑;

1,结合九宫格布局全屏展示效果

跳转九宫格布局github点这里
九宫格布局效果还是很不错的,网上大神教学的文章也很完善,因此不多赘述。
这里的九宫格布局只是单纯的九宫格展示,不带有点击放大全屏展示的操作,因此,有大神在九宫格布局之上二次封装了可点击的九宫格控件

compile 'com.lzy.widget:ninegridview:0.2.0'

效果很好很强大,简单的看了一下源码,其实这个九宫格封装只是在原来的九宫格NineGridImageViewAdapter上的onItemImageClick()方法里加了个点击事件,跳转到了作者自己定义好的一个Activity中,用于全屏展示,是个功能比较完善的项目,但是我自己开发用的项目需要一点自己风格的东西,于是,根据这个原理,我也自己写了一个PhotoView+ViewPager的Activity,封装自己的一些需求,但是却遇到一个加一个的坑,再次记录填坑之路。

2,PhotoView+ViewPager

  private void initView() {
        for (int i = 0; i < mDataList.size(); i++) {
            PhotoView view = new PhotoView(this);
            view.setScaleType(ImageView.ScaleType.FIT_CENTER);
            Glide.with(this).load(GlideUtils.glideUrl(mDataList.get(i))).placeholder(R.drawable.ic_empty).into(view);
            mViewList.add(view);
        }
        initViewPage();
    }

    private void initViewPage() {
        PagerAdapter adapter = new PagerAdapter() {
            @Override
            public int getCount() {
                return mViewList.size();
            }

            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == object;
            }

            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView((View) object);
            }

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                activityPhotoPageViewpager.addView(mViewList.get(position));
                return mViewList.get(position);
            }
        };
        activityPhotoPageViewpager.setAdapter(adapter);
        if (mPosition >= 0 && mPosition < mViewList.size()) {
            activityPhotoPageViewpager.setCurrentItem(mPosition);
        }
    }

这是一开始的思路,点击进入全屏时,初始化一个ViewPager,然后根据Data的数量,初始化一定个数的PhotoView加载一下图片展示下就可以了,但是问题来了,这个代码运行起来会发现一个小问题,点击进入全屏时没问题了,但是在此点击退出全屏这个,这个需要自己手写,然而发现一个问题,PhotoView 的OnclickListener是不能用的,set之后依旧没效果,而且,测试过在PhotoView外部套一个container布局,使用container布局的点击事件,依旧是没有效果的,后来检索了下源码,发现PhotoView给出了另一个方法用来处理,setOnPhotoTapListener();
只要简单的

//这里用了简单的Lambda表达式,应该都能看懂吧...
 view.setOnPhotoTapListener((view1, x, y) -> finish());

实现效果。
如果只是单纯的实现点击退出全屏这个没问题,但是结合ViewPager使用时,就会出现问题了,

如果来回滚动ViewPage,就会出现这个问题,然后,就会发现点击事件又不能用了

I/PhotoViewAttacher: ImageView no longer exists. You should not use this PhotoViewAttacher any more.

查了一下源码,发现是photoView是类似MVC结构,作者将所有的操作抛给了PhotoViewAttacher这个类来处理,这个异常就是在这个类中抛出的:

public ImageView getImageView() {
        ImageView imageView = null;

        if (null != mImageView) {
            imageView = mImageView.get();
        }

        // If we don't have an ImageView, call cleanup()
        if (null == imageView) {
            cleanup();
            LogManager.getLogger().i(LOG_TAG,
                    "ImageView no longer exists. You should not use this PhotoViewAttacher any more.");
        }

        return imageView;
    }

然而发现,只有在这个cleanUp()方法中,才会置空mImageView,同时这个方法还进行了一些操作,置空了监听器,所以监听失效了


    /**
     * Clean-up the resources attached to this object. This needs to be called when the ImageView is
     * no longer used. A good example is from {@link android.view.View#onDetachedFromWindow()} or
     * from {@link android.app.Activity#onDestroy()}. This is automatically called if you are using
     * {@link uk.co.senab.photoview.PhotoView}.
     */
    @SuppressWarnings("deprecation")
    public void cleanup() {
        if (null == mImageView) {
            return; // cleanup already done
        }

        final ImageView imageView = mImageView.get();

        if (null != imageView) {
            // Remove this as a global layout listener
            ViewTreeObserver observer = imageView.getViewTreeObserver();
            if (null != observer && observer.isAlive()) {
                observer.removeGlobalOnLayoutListener(this);
            }

            // Remove the ImageView's reference to this
            imageView.setOnTouchListener(null);

            // make sure a pending fling runnable won't be run
            cancelFling();
        }

        if (null != mGestureDetector) {
            mGestureDetector.setOnDoubleTapListener(null);
        }

        // Clear listeners too
        mMatrixChangeListener = null;
        mPhotoTapListener = null;
        mViewTapListener = null;

        // Finally, clear ImageView
        mImageView = null;
    }

而这个方法是在PhotoView中是这么用的

 @Override
    protected void onDetachedFromWindow() {
        mAttacher.cleanup();
        super.onDetachedFromWindow();
    }

那么问题就很明朗了
因为我没有设置缓存setOffscreenPageLimit()控制,导致我的PhotoView会在

 @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView((View) object);
            }

这里被干掉,设置上之后,一切解决。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值