While my app is running, I get this error:
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
My code is:
LayoutInflater layoutInflater = (LayoutInflater)getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.nextround_popup, parent, false);
final PopupWindow popupWindow = new PopupWindow(popupView,(int) (width * .6), (int) (height * .8));
Button btnDismiss = (Button)popupView.findViewById(R.id.dismiss);
popupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.black_gradient));
new Handler().postDelayed(new Runnable(){
public void run() {
popupWindow.showAtLocation(parent, Gravity.CENTER, 0, 0);
}
}, 100L);
I found some helpful solutions on SO, but I didn't manage to get it solved.
the reason for this error is PopupWindow showing need a token, but the view would not have the token until the Activity render complete. even if you make it delayed. as well as 100ms is short, but if make it longer, it seems stupid.
you can show PopupWindow in the method onWindowFocusChanged, when Activity render complete, this method will be called. like follows:
class MyActivity extends Activity{
//...
#Override
public void onWindowFocusChanged(boolean hasFocus){
if(hasFocus){
//show your PopupWindow
popupWindow.showAtLocation(parent, Gravity.CENTER, 0, 0);
}
}
//...
}
Related
I've spent a while trying to get this to work, looked for similar solutions online, but none seem to work. I need my PopupWindow to only be dismissed on the click of the generate button, not by clicking outside the window. Anyone encountered this issue before?
private void LoadRAMSPopup() {
mainLayout.getForeground().setAlpha(150);
LayoutInflater layoutInflater = (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
final View ramsView = layoutInflater.inflate(R.layout.popup_rams, null);
final PopupWindow popupRAMS = new PopupWindow(
ramsView,
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
if (Build.VERSION.SDK_INT >= 21) {
popupRAMS.setElevation(5.0f);
}
findViewById(R.id.mainLayout).post(new Runnable() {
#Override
public void run() {
popupRAMS.showAtLocation(findViewById(R.id.mainLayout), Gravity.CENTER, 0, 0);
popupRAMS.setOutsideTouchable(false);
popupRAMS.setFocusable(true);
popupRAMS.update();
Button btnGenerate = (Button) ramsView.findViewById(R.id.btnGenerate);
btnGenerate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), CreateRAMSActivity.class);
startActivity(intent);
popupRAMS.dismiss();
mainLayout.getForeground().setAlpha(0);
}
});
}
});
}
Setting up popupRAMS.setFocusable(false). removes unnecessary touch required to make popup window disappear. So please replace
popupRAMS.setFocusable(true);
with
popupRAMS.setFocusable(false);
Also try to add
popupRAMS.setOutsideTouchable(false);
Hope it will help you out.
Try this one
popupRAMS.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(context, android.R.color.transparent)));
popupRAMS.setOutsideTouchable(false);
I tried every other solution and the one that worked forme was setting "false" on the constructor
mDiscountPopUp = new PopupWindow(discountPopUpView, WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT, false); // Creation of popup
i have created a button in android and when clicking it would show the popup window..but the code doesnot work like that..it has no errors but not showing popup window...please helpme..here is my code
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RelativeLayout objrl = (RelativeLayout) findViewById(R.id.myrl);
final Button objButton = (Button) findViewById(R.id.mybutton);
objButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
PopupWindow objPopupWindow = new PopupWindow(objrl, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);
objPopupWindow.setAnimationStyle(R.drawable.background2);
objPopupWindow.showAtLocation(objButton, Gravity.CENTER_HORIZONTAL, 10, 10);
}
});
}
have you tried this : objPopupWindow.showAsDropDown(popupButton, 0, 0);
or try this http://rajeshandroiddeveloper.blogspot.in/2013/07/android-popupwindow-example-in-listview.html
PopupWindow popupWindowDogs = popupWindowDogs();
called below function where they want ::-
public PopupWindow popupWindowDogs() {
// initialize a pop up window type
PopupWindow popupWindow = new PopupWindow(this);
// the drop down list is a list view
ListView listViewDogs = new ListView(this);
// set our adapter and pass our pop up window contents
listViewDogs.setAdapter(dogsAdapter(popUpContents));
// set the item click listener
listViewDogs.setOnItemClickListener(new DogsDropdownOnItemClickListener());
// some other visual settings
popupWindow.setFocusable(true);
popupWindow.setWidth(250);
popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
// set the list view as pop up window content
popupWindow.setContentView(listViewDogs);
return popupWindow;
}
I've found some strange stuff in your codes
You've specified WRAP_CONTENT but haven't specified its content at all
Pass a drawable as animation style to the setAnimationStyle method.
In my opinion if you specify a valid animation style and a content view, It should appear.
I think you missed this code inside the OnClickListener
objPopupWindow.setContentView(objrl);
I have been hunting for the answer to this but most seem to point to getApplicationContext() issues but I am not using getApplicationContext().
Basically I am trying to have a popup window open on start up of a activity but when the activity starts it force closes with the above error.
The code im have writen is:
protected void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
setContentView(R.layout.installguides_menu);
setTitleFromActivityLabel(R.id.title_text);
btn_Back = (Button) findViewById(R.id.btn_Back);
btn_Back.setOnClickListener (btn_Back_onClick);
btn_Ubuntu10Guide = (Button) findViewById(R.id.btn_Ubuntu10Guide);
btn_Ubuntu12Guide = (Button) findViewById(R.id.btn_Ubuntu12Guide);
btn_BacktrackGuide = (Button) findViewById(R.id.btn_BacktrackGuide);
btn_DebianGuide = (Button) findViewById(R.id.btn_DebianGuide);
btn_Ubuntu10Guide .setOnClickListener (btn_Ubuntu10Guide_onClick);
btn_Ubuntu12Guide .setOnClickListener (btn_Ubuntu12Guide_onClick);
btn_BacktrackGuide .setOnClickListener (btn_BacktrackGuide_onClick);
btn_DebianGuide .setOnClickListener (btn_DebianGuide_onClick);
LayoutInflater layoutInflater = (LayoutInflater)getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.donation_popup, null);
final PopupWindow popupWindow = new PopupWindow(
popupView,
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
Button btnDismiss = (Button)popupView.findViewById(R.id.dismiss);
btnDismiss.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
popupWindow.dismiss();
}});
popupWindow.showAsDropDown(btn_Ubuntu10Guide, 50, -30);
}
Hope you guys can help, been hunting for the answer for hours so your my last hope!
My first guess is that you are not allowed to show a pop-up inside onCreate. It is for initializing your application and constructing your layout, but you are forcing it to display a pop-up instead.
onStart() is a more suitable place to show it. Override this function and show your pop-up there. If you prefer to do it in onResume(), note that the user will see it not only when they launch the application but also when they come back to it after navigating away to another activity.
EDIT 2: Try this for creating the pop-up in onStart or onCreate:
LayoutInflater inflater = (LayoutInflater)
this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
PopupWindow pw = new PopupWindow(
inflater.inflate(findViewById(R.id.popup_layout), null, false),
100,
100,
true);
// delaying popup until after all application initialization is done
findViewById(R.id.main_page_layout).post(new Runnable() {
public void run() {
pw.showAtLocation(findViewById(R.id.main_page_layout), Gravity.CENTER, 0, 0);
}
});
Add id's to your activity and pop-up layouts using
android:id="#+id/main_page_layout"
and
android:id="#+id/popup_layout"
respectively so that they match the id's you will use in the code above.
I have a popup menu implemented , which shows up on click of a button. This is my onclick method.
public void showOverflow(View view) {
boolean click = true;
Button action = (Button) findViewById(R.id.btbAction);
LayoutInflater inflater = (LayoutInflater) main.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View popupView = inflater.inflate(R.layout.overflow_layout, null);
final PopupWindow pw = new PopupWindow(popupView,
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
pw.setOutsideTouchable(true);
if (click) {
pw.showAsDropDown(action, 0, 0);
click = false;
} else {
pw.dismiss();
click = true;
}
}
The popup window shows up when the button is clicked. Now, the problem is that the window is not dismissed when i touch outside the popup window.
I tried setting this property to the popup window
pw.setOutsideTouchable(true);
Things remain the same. Please help me fix this
You should change the setOutsideTouchable call's parameter to true:
pw.setOutsideTouchable(false);
Controls whether the pop-up will be informed of touch events outside
of its window. This only makes sense for pop-ups that are touchable
but not focusable, which means touches outside of the window will be
delivered to the window behind. The default is false.
If the popup is showing, calling this method will take effect only the
next time the popup is shown or through a manual call to one of the
update() methods.
Parameters: touchable true if the popup should receive outside touch
events, false otherwise
On the other hand, what is the click local variable supposed to do? It is set to true, so it will always force the pw to pop up, whenever the showOverflow method is called, and for no reason it is set to false later, because it's life cycle ends as you leave that method.
Your code should look something like this:
private LayoutInflater inflater;
private Button action;
private PopupWindow pw;
private View popupView;
/*
* (non-Javadoc)
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
popupView = inflater.inflate(R.layout.overflow_layout, null, false);
action = (Button) findViewById(R.id.action);
action.setOnClickListener(this);
}
public void showOverflow()
{
pw = new PopupWindow(getApplicationContext());
pw.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
pw.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
pw.setOutsideTouchable(true);
pw.setContentView(popupView);
pw.showAsDropDown(action, 0, 0);
}
The getApplicationContext() shoud be used in case you are inside an Activity class. Otherwise you should get the Context as a parameter.
change pw.setOutsideTouchable(true); to pw.setOutsideTouchable(false);
I know this is an old question but this is what I have done to fix it
The problem is:
You are creating a new instance of popupwindow everytime you call showOverFlow() thats why after you close the popupwindow another popup window will show
What will you do is initialize popupview in OnCreate
Then call popupwindow.showAsDropDown(view) in showOverFlow() method
And lastly you can check whether is it showing below code
Put this code in your button onclick
if(popupwindow.isShowing()){
popup.dismiss() }
else{
ShowOverflow()}
I want to make toast click able or a UI element which will have clickable button but behaves like toast.
It should not run on UI thread like toast.
It should not halt or overlay current user activity, message should come like toast with clickable button and vanish but as toast user should be able to access background ongoing UI item.
If any one has any idea about how to achieve this pls share with me.
Little trick. Tested working Android 4.4
toast = new Toast(context);
try {
Class<?> clazz = Class.forName("android.widget.Toast");
Method method = clazz.getDeclaredMethod("getWindowParams");
WindowManager.LayoutParams param = (WindowManager.LayoutParams) method.invoke(toast);
param.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
} catch (Exception e) {
e.printStackTrace();
}
The Gmail undo bar is the best suitable for you, its just like a toast with a button.
Here is a code implementation for it.
http://code.google.com/p/romannurik-code/source/browse/misc/undobar/src/com/example/android/undobar/UndoBarController.java
I had a similar requirement that I solved using a PopupWindow. Basically, I had an about window with a clickable link that I wanted displayed like a toast. The popup window can accomplish this as follows:
In the parent class, I use the following flag:
private boolean durationExpired = false;
Then, when I invoke what would have been the toast, I do the following instead:
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.about_hiittimer,
(ViewGroup) findViewById(R.id.about_hiittimer));
TextView url = (TextView) layout.findViewById(R.id.url);
url.setMovementMethod(LinkMovementMethod.getInstance());
final PopupWindow popupWindow = new PopupWindow(layout, 280, 160, false);
popupWindow.showAtLocation(layout, 17, 0, 0);
popupWindow.setTouchable(true);
popupWindow.setOutsideTouchable(true);
final Handler popupHandler = new Handler();
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!durationExpired) {
durationExpired = true;
popupHandler.postDelayed(this, 2000);
} else {
popupWindow.dismiss();
popupHandler.removeCallbacks(this);
durationExpired = false;
}
}
});
Put your main layout inside a FrameLayout. Write a layout for your toast, with the button and all, insert it into the FrameLayout (below your main layout) and set its visibility to GONE.
When you show it (setting visibility to VISIBLE) start a new thread that counts down the seconds till its dismissed. Set it back to invisible from the thread via a Handler (cause all UI elements can only be managed from the main thread).
cheers!