此控件继承自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地址:点击打开链接