Android控件

使用XPopup实现多张大图浏览

2019-07-25  本文已影响71人  Small_Cake

由于XPopup内置的大图浏览只支持目标文件为ImageView,但我使用的是一个第三方的Banner,也想实现大图浏览。所以就需要我们自定义一下大图浏览了。仿照XPopupImageViewerPopupView

1.首先创建一个自定义的PopupView

public class BigPicsPopupView extends BasePopupView implements OnDragChangeListener, View.OnClickListener {
    protected PhotoViewContainer photoViewContainer;
    protected BlankView placeholderView;
    protected TextView tv_pager_indicator, tv_save;
    protected HackyViewPager pager;
    protected ArgbEvaluator argbEvaluator = new ArgbEvaluator();
    private List<String> urls = new ArrayList<>();
    private XPopupImageLoader imageLoader;
    private OnSrcViewUpdateListener srcViewUpdateListener;
    private int position;
    protected Rect rect = null;
    protected View srcView;
    boolean isShowPlaceholder = true;
    int placeholderColor = -1; //占位View的颜色
    int placeholderStrokeColor = -1; // 占位View的边框色
    int placeholderRadius = -1; // 占位View的圆角
    boolean isShowSaveBtn = true; //是否显示保存按钮

    public BigPicsPopupView(@NonNull Context context) {
        super(context);
    }

    @Override
    protected int getPopupLayoutId() {
        return R.layout._xpopup_image_viewer_popup_view;
    }

    @Override
    protected void initPopupContent() {
        super.initPopupContent();
        tv_pager_indicator = findViewById(R.id.tv_pager_indicator);
        tv_save = findViewById(R.id.tv_save);
        placeholderView = findViewById(R.id.placeholderView);
        photoViewContainer = findViewById(R.id.photoViewContainer);
        photoViewContainer.setOnDragChangeListener(this);
        pager = findViewById(R.id.pager);
        pager.setAdapter(new BigPicsPopupView.PhotoViewAdapter());
        pager.setOffscreenPageLimit(urls.size());
        pager.setCurrentItem(position);
        pager.setVisibility(INVISIBLE);
        addOrUpdateSnapshot(urls.get(position));

        pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int i) {
                position = i;
                showPagerIndicator();
                //更新srcView
                if (srcViewUpdateListener != null) {
                    srcViewUpdateListener.onSrcViewUpdate(BigPicsPopupView.this , i);
                }
            }
        });
        if(isShowSaveBtn)tv_save.setOnClickListener(this);
    }

    public interface OnSrcViewUpdateListener {
        void onSrcViewUpdate(@NonNull BigPicsPopupView popupView, int position);
    }

    private void setupPlaceholder(){
        placeholderView.setVisibility(isShowPlaceholder ? VISIBLE : INVISIBLE);
        if(isShowPlaceholder){
            if(placeholderColor!=-1){
                placeholderView.color = placeholderColor;
            }
            if(placeholderRadius!=-1) {
                placeholderView.radius = placeholderRadius;
            }
            if(placeholderStrokeColor!=-1) {
                placeholderView.strokeColor = placeholderStrokeColor;
            }
            XPopupUtils.setWidthHeight(placeholderView, rect.width(), rect.height());
            placeholderView.setTranslationX(rect.left);
            placeholderView.setTranslationY(rect.top);
            placeholderView.invalidate();
        }
    }

    private void showPagerIndicator() {
        if (urls.size() > 1) {
            tv_pager_indicator.setVisibility(VISIBLE);
            tv_pager_indicator.setText((position + 1) + "/" + urls.size());
        }
        if(isShowSaveBtn)tv_save.setVisibility(VISIBLE);
    }

    ImageView snapshotView;

    private void addOrUpdateSnapshot(String url) {
        if (snapshotView == null) {
            snapshotView = new PhotoView(getContext());
            photoViewContainer.addView(snapshotView);
            snapshotView.setTranslationX(rect.left);
            snapshotView.setTranslationY(rect.top);
            XPopupUtils.setWidthHeight(snapshotView, rect.width(), rect.height());
        }
        setupPlaceholder();
        Glide.with(getContext()).load(url).into(snapshotView);

    }

    @Override
    protected void doAfterShow() {
        //do nothing self.
    }

    @Override
    public void doShowAnimation() {
        photoViewContainer.isReleaseing = true;
        snapshotView.setVisibility(VISIBLE);
        snapshotView.post(new Runnable() {
            @Override
            public void run() {
                TransitionManager.beginDelayedTransition((ViewGroup) snapshotView.getParent(), new TransitionSet()
                        .setDuration(XPopup.getAnimationDuration())
                        .addTransition(new ChangeBounds())
                        .addTransition(new ChangeTransform())
                        .addTransition(new ChangeImageTransform())
                        .setInterpolator(new FastOutSlowInInterpolator())
                        .addListener(new TransitionListenerAdapter() {
                            @Override
                            public void onTransitionEnd(@NonNull Transition transition) {
                                pager.setVisibility(VISIBLE);
                                snapshotView.setVisibility(INVISIBLE);
                                showPagerIndicator();
                                photoViewContainer.isReleaseing = false;
                                BigPicsPopupView.super.doAfterShow();
                            }
                        }));
                snapshotView.setTranslationY(0);
                snapshotView.setTranslationX(0);
                snapshotView.setScaleType(ImageView.ScaleType.FIT_CENTER);
                XPopupUtils.setWidthHeight(snapshotView, photoViewContainer.getWidth(), photoViewContainer.getHeight());

                // do _xpopup_shadow anim.
                animateShadowBg(photoViewContainer.blackColor);
            }
        });

    }

    private void animateShadowBg(final int endColor) {
        final int start = ((ColorDrawable) photoViewContainer.getBackground()).getColor();
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1f);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                photoViewContainer.setBackgroundColor((Integer) argbEvaluator.evaluate(animation.getAnimatedFraction(),
                        start, endColor));
            }
        });
        animator.setDuration(XPopup.getAnimationDuration())
                .setInterpolator(new LinearInterpolator());
        animator.start();
    }

    @Override
    public void doDismissAnimation() {
        tv_pager_indicator.setVisibility(INVISIBLE);
        tv_save.setVisibility(INVISIBLE);
        pager.setVisibility(INVISIBLE);
        snapshotView.setVisibility(VISIBLE);
        photoViewContainer.isReleaseing = true;
        TransitionManager.beginDelayedTransition((ViewGroup) snapshotView.getParent(), new TransitionSet()
                .setDuration(XPopup.getAnimationDuration())
                .addTransition(new ChangeBounds())
                .addTransition(new ChangeTransform())
                .addTransition(new ChangeImageTransform())
                .setInterpolator(new FastOutSlowInInterpolator())
                .addListener(new TransitionListenerAdapter() {
                    @Override
                    public void onTransitionEnd(@NonNull Transition transition) {
                        doAfterDismiss();
                        pager.setVisibility(INVISIBLE);
                        snapshotView.setVisibility(VISIBLE);
                        pager.setScaleX(1f);
                        pager.setScaleY(1f);
                        snapshotView.setScaleX(1f);
                        snapshotView.setScaleY(1f);
                        placeholderView.setVisibility(INVISIBLE);
                    }
                }));

        snapshotView.setTranslationY(rect.top);
        snapshotView.setTranslationX(rect.left);
        snapshotView.setScaleX(1f);
        snapshotView.setScaleY(1f);
        XPopupUtils.setWidthHeight(snapshotView, rect.width(), rect.height());

        // do _xpopup_shadow anim.
        animateShadowBg(Color.TRANSPARENT);
    }

    @Override
    public int getAnimationDuration() {
        return 0;
    }

    @Override
    public void dismiss() {
        if (popupStatus != PopupStatus.Show) return;
        popupStatus = PopupStatus.Dismissing;
        doDismissAnimation();
    }

    public BigPicsPopupView setImageUrls(List<String> urls) {
        this.urls = urls;
        return this;
    }

    public BigPicsPopupView setSrcViewUpdateListener(OnSrcViewUpdateListener srcViewUpdateListener) {
        this.srcViewUpdateListener = srcViewUpdateListener;
        return this;
    }

    public BigPicsPopupView setXPopupImageLoader(XPopupImageLoader imageLoader) {
        this.imageLoader = imageLoader;
        return this;
    }

    public BigPicsPopupView isShowPlaceholder(boolean isShow) {
        this.isShowPlaceholder = isShow;
        return this;
    }

    public BigPicsPopupView isShowSaveButton(boolean isShowSaveBtn) {
        this.isShowSaveBtn = isShowSaveBtn;
        return this;
    }

    public BigPicsPopupView setPlaceholderColor(int color){
        this.placeholderColor = color;
        return this;
    }
    public BigPicsPopupView setPlaceholderRadius(int radius){
        this.placeholderRadius = radius;
        return this;
    }
    public BigPicsPopupView setPlaceholderStrokeColor(int strokeColor){
        this.placeholderStrokeColor = strokeColor;
        return this;
    }

    /**
     * 设置单个使用的源View。单个使用的情况下,无需设置url集合和SrcViewUpdateListener
     *
     * @param srcView
     * @return
     */
    public BigPicsPopupView setSingleSrcView(ImageView srcView, String url) {
        if (this.urls == null) {
            urls = new ArrayList<>();
        }
        urls.clear();
        urls.add(url);
        setSrcView(srcView, 0);
        return this;
    }

    public BigPicsPopupView setSrcView(View srcView, int position) {
        this.srcView = srcView;
        this.position = position;
        int[] locations = new int[2];
        this.srcView.getLocationInWindow(locations);
        rect = new Rect(locations[0], locations[1], locations[0] + srcView.getWidth(), locations[1] + srcView.getHeight());
        return this;
    }

    public void updateSrcView(View srcView,String url) {
        setSrcView(srcView, position);
        addOrUpdateSnapshot(url);
    }

    @Override
    public void onRelease() {
        dismiss();
    }

    @Override
    public void onDragChange(int dy, float scale, float fraction) {
        tv_pager_indicator.setAlpha(1 - fraction);
        if(isShowSaveBtn)tv_save.setAlpha(1 - fraction);
    }

    @Override
    protected void onDismiss() {
        super.onDismiss();
        srcView = null;
    }

    @Override
    public void onClick(View v) {
        if(v==tv_save){
            //check permission
            AndPermission.with(getContext())
                    .runtime()
                    .permission(Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE)
                    .onGranted(new Action<List<String>>() {
                        @Override
                        public void onAction(List<String> data) {
                            XPopupUtils.saveBmpToAlbum(getContext(), imageLoader, urls.get(position));

                        }
                    })
                    .onDenied(new Action<List<String>>() {
                        @Override
                        public void onAction(List<String> data) {
                            Toast.makeText(getContext(), "没有保存权限,保存功能无法使用!", Toast.LENGTH_SHORT).show();
                        }
                    }).start();
        }
    }

    public class PhotoViewAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return urls.size();
        }

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

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            final PhotoView photoView = new PhotoView(container.getContext());
            // call LoadImageListener
            if (imageLoader != null) {
                imageLoader.loadImage(position, urls.get(position), photoView);
            }
            container.addView(photoView);
            photoView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (photoView.getScale() == 1.0f) {
                        dismiss();
                    }
                }
            });
            return photoView;
        }

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


}

2.配置参数和显示

    private void showBigPics(int position, List<String> images) {
        BigPicsPopupView bigPicsPopupView = new BigPicsPopupView(getContext());
        bigPicsPopupView.setImageUrls(images);
        bigPicsPopupView.setSrcView(mBinding.banner, position);
        bigPicsPopupView.setXPopupImageLoader(new BigPicPopImageLoader());
        bigPicsPopupView.setSrcViewUpdateListener((popupView, index) ->
                bigPicsPopupView.updateSrcView(mBinding.banner, images.get(index))
        );
        new XPopup.Builder(getContext())
                .asCustom(bigPicsPopupView)
                .show();
    }

3.使用

    private void initBanner() {
        List<String> images = goodsInfo.getItemPicList();
        if (images == null || images.size() == 0) images = Arrays.asList(goodsInfo.getItemPic());
        List<String> finalImages = images;
        if (images.size()>1){
            mBinding.banner.setOnBannerListener(position -> showBigPics(position, finalImages));
        }else {
            mBinding.banner.setOnClickListener(v -> showBigPics(0, finalImages));
        }
        mBinding.banner.setImageLoader(new BannerImgLoader())
                .setDelayTime(5000)
                .setImages(images)
                .start();
    }

注意:这里需要先设置轮播图点击事件,再开启轮播,不然会出现首次进入点击第一张图片无反应的情况。
我使用的是 banner来加载轮播图片,最后的效果如下:

大图浏览
上一篇下一篇

猜你喜欢

热点阅读