我将使用基于三星SPen的AirView功能的PopupWindow显示预览
但问题是没有创建SurfaceView,也没有调用SurfaceHolder.Callback方法.
显示弹出窗口时,表面区域变为透明,因为根本不创建表面.
SurfaceView未创建且透明:
HoverPreview:
public class HoverPreview extends LinearLayout implements View.OnHoverListener,SurfaceHolder.Callback {
private static final String TAG = "HoverPreview";
private SurfaceHolder mHolder = null;
View mAnchorView = null;
String videoPath;
int position;
private boolean IsMediaPlayerReady = false;
private MediaPlayer mMediaPlayer;
private SurfaceView mSurfaceView;
Context context;
public HoverPreview(Context context,String videoPath,int position) {
super(context);
this.videoPath = videoPath;
this.position = position;
setupLayout(context);
}
public HoverPreview(Context context,AttributeSet attrs) {
super(context,attrs);
setupLayout(context);
}
public HoverPreview(Context context,AttributeSet attrs,int defStyle) {
super(context,attrs,defStyle);
setupLayout(context);
}
private void setupLayout(Context context) {
this.context = context;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.media_browser_hover,this);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG,"HoverSurface created");
final Surface surface = surfaceHolder.getSurface();
if (surface == null) return;
if (!surface.isValid()) return;
mHolder = surfaceHolder;
mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setDataSource(videoPath);
} catch (IOException e) {
e.printStackTrace();
}
mMediaPlayer.setDisplay(mHolder);
mAnchorView.setTag(mMediaPlayer);
mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mediaPlayer,int i,int i2) {
mHolder.setFixedSize(i,i2);
}
});
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d(TAG,"MediaPlayer preview is prepared");
IsMediaPlayerReady = true;
if (mMediaPlayer != null && IsMediaPlayerReady) {
if (position > 0)
mMediaPlayer.seekTo(position);
mMediaPlayer.start();
}
}
});
Log.d(TAG,"MediaPlayer is created");
try {
mMediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder,int i2,int i3) {
Log.d(TAG,"HoverSurface changed");
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG,"HoverSurface destroyed");
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
//thumbnailImageView.setTag(null);
}
}
public void setAnchorView(View view) {
mAnchorView = view;
}
@Override
public boolean onHover(View view,MotionEvent motionEvent) {
try {
if (motionEvent.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
Log.d(TAG,"ACTION_HOVER_ENTER");
mSurfaceView = (SurfaceView) findViewById(R.id.media_browser_hoverSurfaceView);
mHolder = mSurfaceView.getHolder();
if (mHolder != null) {
mHolder.addCallback(this);
}
} else if (motionEvent.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
Log.d(TAG,"ACTION_HOVER_EXIT");
if (mAnchorView.getTag() != null) {
MediaPlayer mMediaPlayer = (MediaPlayer) mAnchorView.getTag();
mMediaPlayer.stop();
mMediaPlayer.release();
mAnchorView.setTag(null);
}
}
} catch (Exception e) {
Log.e(TAG,e.getMessage() + Utils.toString(e.getStackTrace()));
}
return false;
}
}
final PopupWindow popupWindow = new PopupWindow(context);
final HoverPreview hoverPreview = new HoverPreview(context,videoPath,0);
hoverPreview.setAnchorView(thumbnailImageView);
thumbnailImageView.setOnHoverListener(new View.OnHoverListener() {
@Override
public boolean onHover(View view,MotionEvent motionEvent) {
hoverPreview.onHover(view,motionEvent);
if (motionEvent.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
popupWindow.setContentView(hoverPreview);
popupWindow.setWidth(600);
popupWindow.setHeight(400);
popupWindow.showAtLocation(thumbnailImageView,ToolHoverPopup.Gravity.NO_GRAVITY,10,10);
Log.d(TAG,"Manual Hover Enter");
} else if (motionEvent.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
Log.d(TAG,"Manual Hover Exit");
if (popupWindow != null)
popupWindow.dismiss();
}
return true;
});
最佳答案
这是我完整的工作解决方案:
原文链接:https://www.f2er.com/android/430970.html我从SPen库中借用了ToolHoverPopup类中的一些代码,我也为这个特殊的弹出窗口进行了自定义,以便在实际悬停发生之前不会创建或膨胀任何内容,这样我们就不会消耗资源来在列表中启用这样的预览.
我们需要将预览附加到Window上,因此我们必须管理通常由PopupWindow完成的所有底层定位工作,所以我完全删除了对PopupWindow的依赖,现在我的HoverPreview类完全正常工作和管理所有作业,它还能够以毫秒为单位确定悬停检测延迟.
截图(SurfaceView已创建)
用法:(由于布局包含SurfaceView并且是资源密集型的,我手动触发onHover事件,以便仅在执行真实悬停时才执行真实表面创建.同样,在此之前,我不会在需要之前创建任何HoverPreview对象)
thumbnailImageView.setOnHoverListener(new View.OnHoverListener() {
@Override
public boolean onHover(View view,MotionEvent motionEvent) {
HoverPreview hoverPreview;
if (thumbnailImageView.getTag() == null) {
hoverPreview = new HoverPreview(context,getActivity().getWindow(),0);
hoverPreview.setHoverDetectTime(1000);
thumbnailImageView.setTag(hoverPreview);
} else
hoverPreview = (HoverPreview) thumbnailImageView.getTag();
hoverPreview.onHover(null,motionEvent);
if (motionEvent.getAction() == MotionEvent.ACTION_HOVER_EXIT)
thumbnailImageView.setTag(null);
return true;
}
});
HoverPreview:
public class HoverPreview extends LinearLayout implements View.OnHoverListener,SurfaceHolder.Callback {
private static final int MSG_SHOW_POPUP = 1;
private static final int MSG_DISMISS_POPUP = 2;
private static final int HOVER_DETECT_TIME_MS = 300;
private static final int POPUP_TIMEOUT_MS = 60 * 1000;
protected int mHoverDetectTimeMS;
private static final String TAG = "HoverPreview";
private SurfaceHolder mHolder = null;
String videoPath;
int position;
private boolean IsMediaPlayerReady = false;
private MediaPlayer mMediaPlayer;
private SurfaceView mSurfaceView;
Context context;
private HoverPopupHandler mHandler;
Window window;
public HoverPreview(Context context,Window window,int position) {
super(context);
this.mHoverDetectTimeMS = HOVER_DETECT_TIME_MS;
this.videoPath = videoPath;
this.position = position;
this.window = window;
setupLayout(context);
}
private void setupLayout(Context context) {
this.context = context;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rootView = inflater.inflate(R.layout.media_browser_hover,this);
mSurfaceView = (SurfaceView) findViewById(R.id.media_browser_hoverSurfaceView);
}
View rootView;
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG,"HoverSurface created");
final Surface surface = surfaceHolder.getSurface();
if (surface == null) return;
if (!surface.isValid()) return;
mHolder = surfaceHolder;
mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setDataSource(videoPath);
} catch (IOException e) {
e.printStackTrace();
return;
}
mMediaPlayer.setDisplay(mHolder);
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d(TAG,"MediaPlayer preview is prepared");
IsMediaPlayerReady = true;
int videoWidth = mMediaPlayer.getVideoWidth();
int videoHeight = mMediaPlayer.getVideoHeight();
Point size = new Point();
int screenHeight = 0;
int screenWidth = 0;
Display display = getDisplay();
display.getSize(size);
screenWidth = size.x - (350 + 30); // margin + padding
screenHeight = size.y;
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mSurfaceView.getLayoutParams();
lp.width = screenWidth;
lp.height = (int) (((float) videoHeight / (float) videoWidth) * (float) screenWidth);
mSurfaceView.setLayoutParams(lp);
if (mMediaPlayer != null && IsMediaPlayerReady) {
if (position > 0)
mMediaPlayer.seekTo(position);
mMediaPlayer.start();
findViewById(R.id.media_browser_hoverRootFrameLayout).setVisibility(VISIBLE);
}
}
});
Log.d(TAG,"HoverSurface destroyed");
try {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
}
} catch (Exception e) {
}
}
@Override
public boolean onHover(View view,"ACTION_HOVER_ENTER");
show(); // checks the timing
} else if (motionEvent.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
Log.d(TAG,"ACTION_HOVER_EXIT");
dismiss();
}
} catch (Exception e) {
Log.e(TAG,e.getMessage() + Utils.toString(e.getStackTrace()));
}
return false;
}
/**
* Sets the time that detecting hovering.
*
* @param ms The time,milliseconds
*/
public void setHoverDetectTime(int ms) {
mHoverDetectTimeMS = ms;
}
public void dismiss() {
dismissPopup();
}
private void dismissPopup() {
// remove pending message and dismiss popup
getMyHandler().removeMessages(MSG_SHOW_POPUP);
getMyHandler().removeMessages(MSG_DISMISS_POPUP);
try {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
}
} catch (Exception e) {
}
if (getParent() != null)
((ViewGroup) getParent()).removeView(this);
}
private Handler getMyHandler() {
if (mHandler == null)
mHandler = new HoverPopupHandler();
return mHandler;
}
public void show() {
// send message to show.
if (getMyHandler().hasMessages(MSG_SHOW_POPUP)) {
return;
// getHandler().removeMessages(MSG_SHOW_POPUP);
}
getMyHandler().sendEmptyMessageDelayed(MSG_SHOW_POPUP,mHoverDetectTimeMS);
}
private void showPopup() {
if (getParent() == null) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);
params.gravity = Gravity.CENTER_VERTICAL;
params.x = 350;
window.addContentView(this,params);
}
mHolder = mSurfaceView.getHolder();
if (mHolder != null) {
mHolder.addCallback(this);
}
}
;
private class HoverPopupHandler extends Handler {
@Override
public void handleMessage(Message msg) {
// if (DEBUG)
// android.util.Log.e(TAG,"handleMessage : " + ((msg.what == MSG_SHOW_POPUP) ? "SHOW" : "DISMISS"));
switch (msg.what) {
case MSG_SHOW_POPUP:
showPopup();
sendEmptyMessageDelayed(MSG_DISMISS_POPUP,POPUP_TIMEOUT_MS);
break;
case MSG_DISMISS_POPUP:
dismissPopup();
break;
}
}
}
}