利用photoView實現可點選放大到全屏顯示的控制元件,效果類似於微信朋友圈點開看大圖
阿新 • • 發佈:2018-11-10
此控制元件繼承自ImageView,實現效果與微信朋友圈點開看大圖相似,點選控制元件後進入沉浸模式全屏顯示大圖,全屏時雙擊或手指拉伸可放大圖片,單擊會退出全屏
老規矩,先上控制元件實現程式碼:
/** * 可點選放大全屏顯示的imageView * Created by Administrator on 2016/11/16 0016. */ public class MyPopupView extends ImageView implements View.OnClickListener { private int photoViewId = -1; private intpopupId = -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地址:點選開啟連結