PopupWindow - Dismiss when clicked back but not outside - android

I want to clicked back button to dismiss PopupWindow.But I can also click outside to do another thing,the PopupWindow don't miss.
I try popupWindow.setFocusable(true);,but the PopupWindow will dismiss when I click outside.
I try to custom view.
public class OtherBrifeIntroView extends LinearLayout
{
#Override
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{
Toast.makeText(mContext, "test", Toast.LENGTH_SHORT).show();
return true;
}
return super.dispatchKeyEvent(event);
}
}
but it doesn't work.Can you help me?

I solve it.Set TouchModal false,but the setTouchModal is hide,so I use reflect.
public static void setPopupWindowTouchModal(PopupWindow popupWindow, boolean touchModal)
{
if (null == popupWindow)
{
return;
}
Method method;
try
{
method = PopupWindow.class.getDeclaredMethod("setTouchModal", boolean.class);
method.setAccessible(true);
method.invoke(popupWindow, touchModal);
}
catch (Exception e)
{
e.printStackTrace();
}
}
Finally.
setPopupWindowTouchModal(popupWindow, false);
popupWindow.setFocusable(true);

You can call popupWindow.dismiss() to manually dismiss the PopupWindow within your dispatchKeyEvent method. In order to stop it dismissing when you touch outside of the PopupWindow there are a number of things you can try.
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchable(true);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
Have a play about with the above values and see what the outcome is, I am not on my developer computer at the moment so can't test which one it is.

Related

How to make an app which will not listen to touch events

How to make an app which will not listen to touch events and back/home pressing but will listen only to the power button.
I've tried this but it wasn't successful.
#Override
public boolean onKeyDown(int keyCode, android.view.KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_POWER) {
return true;
}else if ((keyCode == KeyEvent.KEYCODE_HOME)|| (keyCode == KeyEvent.KEYCODE_BACK )){
return false;
}
return false;
}
You could wrap you class with a custom View of yours and override its OnClickListener and OnTouchListener methods. Override them with blank methods.
Also, keep your code to set how your app should work when the Power Button is clicked.
For instance, if you wrap your layout with a RelativeLayout or a general View, you could use something like
relativeLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
return false;
}
});
To block user touch event try this solution. And if you want to disable back and home try to override this method of Activity:
#Override
public void onAttachedToWindow() {
this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
super.onAttachedToWindow();
}
three weeks ago, i want also to catch the home button, but i faied. i do some research, i find the android system don't support to modify it.you can visit this
Overriding the Home button - how do I get rid of the choice?, about homebutton.
as for the touchEvent, i advice you can try this method ,override onTouchEvent (if you dont add onTouchListener, make it retrun fasle and do nothing, at the same time ,the activity also dont handle the onTounEvent or OnClick(whole layout).

Android Dialog OnKeyUp (KeyEvent)?

I have a dialog and on in this dialog I have a button. When pressed search is suppose to appear. And this works completely fine.
BUT I want to able to set up OnKeyUp event so if the user clicks on the actual search button on the phone (not on the screen), search view appears.
I was able to do this in an activity this way:
public override bool OnKeyUp(Keycode keyCode, KeyEvent e)
{
if (keyCode == Keycode.Search) {
// do something here
}
return base.OnKeyUp (keyCode, e);
}
But that's an override method. How do I call that for a Dialog?
This is how I've created the Dialog:
multiSelectDialog = new Dialog (context);
multiSelectDialog.RequestWindowFeature (1);
multiSelectDialog.SetContentView (dialogView);
multiSelectDialog.Show ();
Dialog has the OnKeyUp property.
multiSelectDialog.OnKeyUp(KeyCode.Search, KeyEvent e);
But I am not sure how to create a KeyEvent.
Thank you for your time.
onKeyUp() is a callback on Dialog, it will be called on a key-up event, you don't call it yourself.
Instead you have to extend Dialog and override onKeyUp(), for example:
multiSelectDialog = new Dialog(context) {
#Override
public boolean onKeyUp (int keyCode, KeyEvent event) {
// do something here
return true; // or false, depending on what you want to do
}
};
multiSelectDialog.requestWindowFeature(1);
multiSelectDialog.setContentView(dialogView);
multiSelectDialog.show();

Inside the settouch interceptor unable to call the functions in android?

In my application I am using a popup window. For dismissing the popup window when the user touches outside, I am using the ORDER LIST PW CODING coding below, the pop window dismiss function works perfectly but not able to call
Submenu_listtask = new Submenu_list();
Submenu_listtask.execute();
this function inside setTouchInterceptor its not working. Can any one know please help me.
ORDER LIST PW CODING
order_list_pw.setTouchInterceptor(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
//Unable to call this function
Submenu_listtask = new Submenu_list();
Submenu_listtask.execute();
order_list_pw.dismiss();
Log.v("Name", "Name");
return true;
}
return false;
}
});
Return true at the end of onTouch() as returning false only enables you to catch ACTION_DOWN event

PopUpWindow dismissal by back press key

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);

Android popup window dismissal

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();
}
});

Categories

Resources