[置顶] 利用photoView实现可点击放大到全屏显示的控件,效果类似于微信朋友圈点开看大图

此控件继承自ImageView,实现效果与微信朋友圈点开看大图相似,点击控件后进入沉浸模式全屏显示大图,全屏时双击或手指拉伸可放大图片,单击会退出全屏
老规矩,先上控件实现代码:
/**  * 可点击放大全屏显示的imageView  * Created by Administrator on 2016/11/16 0016.  */ public class MyPopupView extends ImageView implements View.OnClickListener {
    private int photoViewId = -1;
    private int popupId = -1;
    private OnClickListener mListener;
    private List<Integer> ids;

    public MyPopupView(Context context) {
        this(context, null);
    }

    public MyPopupView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyPopupView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOnClickListener(this);
    }

    /**  * 设置popupWindow的布局文件及其子控件点击事件  *  * @param popupId popupWindow的布局ID  * @param photoViewId popupWindow中的photoViewID  * @param mListener 点击事件监听 mListener的实现中需要根据子控件id匹配处理  * @param ids popupWindow中除photoView以外的其他需要设置点击事件监听的子控件的ID  */  public MyPopupView(Context context, int popupId, int photoViewId, OnClickListener mListener, int... ids) {
        this(context);
        this.popupId = popupId;
        this.photoViewId = photoViewId;
        this.mListener = mListener;
//    mListener.onClick()方法的实现范例:
//    public void onClick(View v) {
//        switch (ids) {
//            case ids[0]:    do something            break;
//            case ids[1]:    do something            break;
//                ...
//            case ids[ids.length]:    do something            break;
//        }
//    }
        this.ids = new ArrayList<>();
        for (int id : ids
                ) {
            this.ids.add(id);
        }
    }

    /**  * 无需设置其他子控件点击事件  *  * @param popupId popupWindow的布局ID  * @param photoViewId popupWindow中的photoViewID  */  public MyPopupView(Context context, int popupId, int photoViewId) {
        this(context);
        this.popupId = popupId;
        this.photoViewId = photoViewId;
    }


    @Override
    public void setOnClickListener(OnClickListener l) {
        //内部为此控件添加点击事件监听
        //使外部设置的点击事件监听无效
        super.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        View popupView;
        PhotoView photoView;
        if (popupId == -1 || photoViewId == -1) {
            //如果没有自定义popupWindow布局则加载默认布局文件
            popupView = View.inflate(getContext(), R.layout.popup_default, null);
            photoView = (PhotoView) popupView.findViewById(R.id.photoView);
        } else {
            popupView = View.inflate(getContext(), popupId, null);
            photoView = (PhotoView) popupView.findViewById(photoViewId);
        }
        //设置popupView中除photoView以外的子控件的点击事件
        if (mListener != null && ids != null) {
            for (int id : ids) {
                View child = popupView.findViewById(id);
                if (child != null) {
                    child.setOnClickListener(mListener);
                }
            }
        }
        //从MyPopupView获取bitmap设置给photoView,如果MyPopupView未设置src则给photoView设置安卓机器人图片
        //可修改为从uri加载原缩略图的大图,有需要的同学可以自己实现
        Bitmap mBitmap = ((BitmapDrawable) getDrawable()).getBitmap();
        if (mBitmap == null) {
            photoView.setImageResource(R.mipmap.ic_launcher);
        } else {
            photoView.setImageBitmap(mBitmap);
        }
        PopupWindow mPopupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);
        PhotoViewAttacher mAttacher = new PhotoViewAttacher(photoView);
        //设置photoView单击、双击监听
        mAttacher.setOnDoubleTapListener(new MyOnDoubleTapListener(mAttacher, getContext(), mPopupWindow));
        //设置popupWindow背景色
        mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.BLACK));
        //沉浸式全屏
        DRAppUtil.getInstance().hideSystemUI(mPopupWindow.getContentView());
        //设置popupWindow出现与消失的动画
        mPopupWindow.setAnimationStyle(R.style.popup_anim_style);
        //全屏显示
        mPopupWindow.showAtLocation(((Activity) getContext()).getWindow().getDecorView(), Gravity.CENTER, 0, 0);
    }
}
上面用到了第三方控件photoView,上github一搜就能看到,导入方式:
compile 'com.github.chrisbanes.photoview:library:1.2.4' 

photoView的动作监听器:
/**  * photoView的单击、双击监听  * Created by Dovar on 2016/10/10 0010.  */ public class MyOnDoubleTapListener extends DefaultOnDoubleTapListener {
    private PopupWindow mPopupWindow;
    private Context mContext;

    /**  * Default constructor  *  * @param photoViewAttacher PhotoViewAttacher to bind to  */  public MyOnDoubleTapListener(PhotoViewAttacher photoViewAttacher, Context mContext, PopupWindow mPopupWindow) {
        super(photoViewAttacher);
        this.mContext = mContext;
        this.mPopupWindow = mPopupWindow;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        Log.d("test", "onSingleTapConfirmed: ");
        DRAppUtil.getInstance().showSystemUI(mPopupWindow.getContentView());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException mE) {
                    mE.printStackTrace();
                }
                ((Activity) mContext).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mPopupWindow.dismiss();
                    }
                });
            }
        }).start();

        return super.onSingleTapConfirmed(e);
    }
}
我只是重写了单击的监听方法,实现单击关闭popupWindow,之所以要开个工作线程短暂延迟是因为showSystemUI()方法是耗时操作
 
 
开启、退出沉浸模式的方法我前面的博客中有,这里贴个简单的,只处理了标题栏:
/**  * 进入沉浸模式  */ @TargetApi(Build.VERSION_CODES.KITKAT)
public void hideSystemUI(View view) {
    //setSystemUiVisibility()是耗时任务
    view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE  | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN  | View.SYSTEM_UI_FLAG_FULLSCREEN  | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}

/**  * 退出沉浸模式  */ public void showSystemUI(View view) {
    view.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE  | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

全屏时弹出的popupWindow可以自定义布局,给布局中的子控件添加监听的方法需要注意一下:
mListener.onClick()方法的实现范例:
public void onClick(View v) {
    switch (v.getId()) {
        case ids[0]:    do something            break;
        case ids[1]:    do something            break;
            ...
        case ids[ids.length]:    do something            break;
    }
}
因为是在构造方法中使用可变参数传入子控件id,所以设置监听的时候是按照点击的ID来响应的。
Demo地址:点击打开链接

你可能感兴趣的:(photoview,点击放大图片)