I want to dismiss the pop up window when back button is pressed. I tried with this code:
popwindow.setBackgroundDrawable(new BitmapDrawable()); and it works. But in my app, pop should remain, even after touching outside of the pop up window. It should be dismissed only when back button is pressed. So I tried this: popwindow.setFocusable(false);
Now its not dismissing when touched outside the pop up. But its not dismissing on back press too. I do not want to overide `onBackPressed(). Is there any other way, through which i can achieve this. Thanks in advance..
popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
new ScaleInAnimation(popupView).animate();
popupWindow.getContentView().setFocusableInTouchMode(true);
popupWindow.getContentView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
popupWindow.dismiss();
return true;
}
return false;
}
});
To disable pop up dismiss when click outside of popwindow
set
popwindow.setCanceledOnTouchOutside(false);
and for dismiss it on back button
set
popwindow.setCancelable(true);
Set like this..
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchable(true);
popupWindow.setBackgroundDrawable(new BitmapDrawable()); popupWindow.setTouchInterceptor(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
if (AppContext.isDebugMode())
Log.d("POPUP_WINDOW", "v: "+v.getTag() + " | event: "+event.getAction());
popupWindow.dismiss(); return true;
}
});
Aside from the setOutsideTouchable(true) and setFocusable(true) I had to add
popUpView.setBackgroundDrawable(new BitmapDrawable())
to make it work. This did not change the UI of my popup, but for some magical reason, enabled the back button functionality.
The code below may be helpfull:
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.showAsDropDown(mParent);
And,the show of the popupWindow (popupWindow.showAsDropDown or popupWindow.showAtLocation )must be called in the end.
Set Popup property as..
popup.setOutsideTouchable(false);
popup.setCancelable(true);
Related
I'm creating a custom soft keyboard, and created a PopupWindow to show when a key is long pressed, like when you long press E and it shows E, É, È for you to choose one. The popup has a key to close him, but I want to remove this key and make him shows just while the user is touching, then the user long press, drag to the key that he want and release.
I'm using android API 8.
The popup is created in a KeyboardView class in the onLongPress method.
final View custom = LayoutInflater.from(context)
.inflate(R.layout.popup_layout, new FrameLayout(context));
final PopupWindow popup = new PopupWindow(context);
popup.setContentView(custom);
popup.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
popup.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
popup.showAtLocation(this, Gravity.NO_GRAVITY, popupKey.x, popupKey.y-50);
The button for close the popup:
buttonCancel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
popup.dismiss();
}
});
I think can use something with the onTouch method, but how to identify the event of releasing? And where use it? On the keyboardView, or maybe on the popup window?
I managed to do this with:
#Override
public boolean onTouchEvent(MotionEvent me){
if(popup != null && me.getAction() == MotionEvent.ACTION_UP){
popup.dismiss();
}
}
I first created a method to show on logcat the code of every touch event, then I got the code that appeared when I release the touch and compared with the documentation, and it it the code for MotionEvent.ADCTION_UP.
With this, it's just put a dismiss on the popup.
I saw that there is a private function called KeyboardView.dismissPopupKeyboard().
This is ugly, but because I am using the default PopupWindow (I didn't overrided OnLongPress()) and I saw thata KeyboardView.onClick() calls dismissPopupKeyboard() and that's it, what I did was:
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP){
getOnKeyboardActionListener().onKey('1', null);
dismissPopupKeyboard();
}
return true; // Required for recieving subsequent events (ACTION_MOVE, ACTION_UP)
}
I want to know how to close a pop_up window once the user clicks outside it, I had a look at PopupWindow - Dismiss when clicked outside but without any luck, and I tried that code:
pw.setBackgroundDrawable(null);
pw.setOutsideTouchable(true);
pw.setTouchInterceptor(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE)
{
pw.dismiss();
return true;
}
return false;
}
});
Try this out.Hope it works :)
solution 1:
popupWindow.setFocusable(true);
popupWindow.update();
If this dont work.Then you can try this out.
solution 2:
You can use dialog.setCanceledOnTouchOutside(true); which will close the dialog if you touch outside of the dialog.
Something like,
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
Or if your Dialog in non-model then,
1 - Set the flag-FLAG_NOT_TOUCH_MODAL for your dialog's window attribute
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 - Add another flag to windows properties,, FLAG_WATCH_OUTSIDE_TOUCH - this one is for dialog to receive touch event outside its visible region.
3 - Override onTouchEvent() of dialog and check for action type. if the action type is 'MotionEvent.ACTION_OUTSIDE' means, user is interacting outside the dialog region. So in this case, you can dimiss your dialog or decide what you wanted to perform. view plainprint?
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog ******************** ");
this.dismiss();
}
return false;
}
Ok so fixed in the end.
First made the main layout which the popup sits on a relative layout. Then placed a full screen blank layout on top which I made invisible and transparent.
Then show when the popup is shown, set the full screen panel visible with setVisibility(View.VISIBLE); and hide when popup is hidden with setVisibility(View.GONE);
Also need to return true from an on touch listener for the layout with (To stop touch events passing back to the main layout):
blocker.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
And give the popup window the properties:
setTouchable(true);
setOutsideTouchable(false);
Cheers
you should'nt set the BackgroundDrawable to null, because that kills the OnTouchListener ;
you should replace pw.setBackgroundDrawable(null); by pw.setBackgroundDrawable(new BitmapDrawable())
Better use a dialog Fragment for the same. It is made for the popup functionality and closes by default on pressing outside the dialog Fragment or using the hard back button.
I have created a popUpwindow which contains this properties:
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(false);
After mentioning this also there is a dismissal of popUpwindow when clicked outside the popUpWindow. Can anybody tell me what can be done to avoid this.
And also i have a music getting played in popUpwindow but when it plays i am not able to increase or decrease volume for the same.
I am not able to access media volume controls when there is popUpwindow in focus. I have read that if there is overidden method onKeydown / up then setVolumeControlsStream(AudioManager.Stream_Music) will not work. But i have used keyDown method to handle backpress rest i am returning return super.onKeyDown(keyCode, event);
Please suggest method to overcome this.
Try this
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
return false;
}else{
return super.dispatchTouchEvent(ev);
}
}
May this help you. i used this to avoid dismissal of Dialog when clicked outside the Dialog.
Try this-
put below line end of your class
#Override
public void onBackPressed() {
if (popupWindow != null)
popupWindow.dismiss();
else
super.onBackPressed();
finish();
}
Set focusable to false for popup window. It will avoid dismissal of popUpwindow when clicked outside the popUpWindow.
popupWindow.setFocusable(false);
I have use Popupwindow for auto-suggestion popup in a dialogFragment. On portrait, that popup doesn't reach soft keyboard (popup look small), it seem like its size is limited by dialog windown size. I want the popup reach soft keyboard (look bigger). How to make popupwindow exceed dialog window?
Note : I have try to setClippingEnable to fasle, but popup is growth exceed keyboard and screen.
Set this boolean for your popup window object and the pop up size will exceed the dialog size.
popupWindow.setClippingEnabled(false);
Here are my code
popUp = new PopupWindow(view, w, h);
popUp.setBackgroundDrawable(new BitmapDrawable());
popUp.setOutsideTouchable(true);
popUp.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
popUp.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
popUp.setTouchInterceptor(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
popUp.dismiss();
return true;
}
return false;
}
});
private void updatePopUp(EditText input) {
popUp.setWidth(input.getWidth());
popUp.showAsDropDown(input);
popUp.update();
}
I think this code don't have problem because I have use it in other class, but the problem is when I implement it in dialog Fragment.
try this
PopupWindow mPop=new PopupWindow("View for popup","hgt(int)","width(int)","focusable(boolean)");
I have a popup window displaying when I click an item in my list activity. The problem is that the back key doesn't close it. I tried catching the back key in my list activity but it doesn't register it...then I tried registering a onkeylistener to the view I'm passing to my popup window. Like this:
pop.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
boolean res=false;
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
// do something on back.
Log.e("keydown","back");
if (pw.isShowing()) {
Log.e("keydown","pw showing");
pw.dismiss();
res = true;
}
} else {
res = false;
}
return res;
}
});
which is passed to a popup like this:
pw = new PopupWindow(
pop,
240,
70,
true);
But that listener doesn't fire neither. Can you help me? I'm out of ideas :)
This is because the popup window does not respond to onTouch or onKey events unless it has a background that != null. Check out some code I wrote to help with this. In the basic case you can to call PopupWindow#setBackgroundDrawable(new BitmapDrawable()) to force it to act the way you expect. You won't need your own onKey listener. You might also need to call PopupWindow#setOutsideTouchable(true) if you want it to go away when the user clicks outside of the window boundaries.
Extended esoteric answer:
The reason the background cannot be null is because of what happens in PopupWindow#preparePopup. If it detects background != null it creates an instance of PopupViewContainer and calls setBackgroundDrawable on that and puts your content view in it. PopupViewContainer is basically a FrameLayout that listens for touch events and the KeyEvent.KEYCODE_BACK event to dismiss the window. If background == null, it doesn't do any of that and just uses your content view. You can, as an alternative to depending on PopupWindow to handle that, extend your root ViewGroup to behave the way you want.
Do as per following it works fine:
PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT, true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setOutsideTouchable(true);
pw.showAsDropDown(btnSelectWeight);
For new projects it's better to use
popupWindow.setBackgroundDrawable(new ColorDrawable());
instead of
popupWindow.setBackgroundDrawable(new BitmapDrawable());
as BitmapDrawable is deprecated. Also, it's better than ShapeDrawable in this case. I noticed that when PopupWindow is a rectangle with rounded corners, ShapeDrawable fills corners with black.
A really simple solution is to write pw.setFocusable(true), but probably you don't want to do this because then the MapActivity won't handle touch events.
A better solution is to override the back key, e.g like this:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Override back button
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (pw.isShowing()) {
pw.dismiss();
return false;
}
}
return super.onKeyDown(keyCode, event);
}
Good luck!
For the new searchers, as creating a new BitmapDrawable is not allowed now(The constructor BitmapDrawable() is deprecated) , so that you have to change it to a new ShapeDrawable(), so that you will change :
pw.setBackgroundDrawable(new BitmapDrawable());
To :
pw.setBackgroundDrawable(new ShapeDrawable());
And the whole work will be like :
PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new ShapeDrawable());
pw.setTouchInterceptor(new OnTouchListener() { // or whatever you want
#Override
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE) // here I want to close the pw when clicking outside it but at all this is just an example of how it works and you can implement the onTouch() or the onKey() you want
{
pw.dismiss();
return true;
}
return false;
}
});
pw.showAtLocation(layout, Gravity.CENTER, 0, 0);
just use this
mPopupWindow.setBackgroundDrawable(new BitmapDrawable(null,""));
which is not deprecated. i'd avoid new ShapeDrawable() as its going to render slowly as it tries to draw a shape when the screen needs to be redrawn.
I hope this will be help for you
pw.setTouchInterceptor(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN) {
pw.dismiss();
}
return true;
}
});
you need add setBackgroundDrawable(new BitmapDrawable()) for your PopupWindow.
private void initPopupWindow() {
// TODO Auto-generated method stub
View view = getLayoutInflater().inflate(R.layout.main_choice, null);
ListView main_menu_listview = (ListView) view.findViewById(R.id.main_menu_listview);
ShowMainChoice madapter = new ShowMainChoice(context);
main_menu_listview.setAdapter(madapter);
int width = (int)getWindowManager().getDefaultDisplay().getWidth()/2;
popupWindow = new PopupWindow(view, width,WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(new BitmapDrawable());//this is important,如果缺少这句将导致其他任何控件及监听都得不到响应
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
main_menu_listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
// TODO Auto-generated method stub
Log.e("++++++>", arg2+"");
}
});
}
This problem is popupwindow底层的消息机制决定的,因为它是阻塞式的。Good luck
pw.setBackgroundDrawable(new ColorDrawable());
must wrote it before setContentView
This works for me.
Are you looking for the combination of the popupwindow dismiss and a good working of the BACK button, then you may consider the below solution.
Solution principle: all button clicks near your popup window will be intercepted, but any BACK button will not be intercepted. So, if you have anything in you popupwindow that takes action, then set an indication just before your call to dismiss(). In your setOnDismissListener() perform an extra action (like getActivity().popupBackStack()).
The advantage of this solution is that you can create your own CustomPopupWindow and implement this strategy. You can hide this implementation in your custom popup window.
Step 1: add near to your instantiation of your Popup Window:
boolean isClickHandled = false;
popupWindow.setOutsideTouchable(true);
popupWindow.setBackgroundDrawable(new ShapeDrawable());
popupWindow.setTouchInterceptor(new View.OnTouchListener() { // or whatever you want
#Override
public boolean onTouch(View v, MotionEvent event) {
isClickHandled = true;
return false;
}
});
If you have buttons inside your popupWindow, have the setOnClickListener.onClick set the isClickHandled = true and dismiss().
In your onDismissListener do something like:
popupWindow.setOnDismissListener(() -> {
popupWindow.dismiss();
if ( !isClickHandled) {
MainActivity.mainActivity.getSupportFragmentManager().popBackStack();
}
});