1. 程式人生 > >利用photoView實現可點選放大到全屏顯示的控制元件,效果類似於微信朋友圈點開看大圖

利用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地址:點選開啟連結