I'm having a very frustrating problem with PopupWindow on Android.
I've implemented my own class that inherits PopupWindow and implements
OnClickListener.
After adding button backgrounds with custom selectors problems start.
This background keeps disappearing after clicking the button (starting new activity and dismissing the popup).
It doesn't disappear after "focus and click", only after "quick click".
Any idea/suggestion would be very appriciated!
public class TestPopup extends PopupWindow implements OnClickListener
protected LayoutInflater inflater;
protected Activity caller;
protected View popup;
protected View layout;
public TestPopup(Activity activity) {
super(activity);
popup = inflater.inflate(R.layout.popup, (ViewGroup) caller.findViewById(R.id.contentLayout));
layout = popup.findViewById(R.id.layout);
popup.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
Display display = caller.getWindowManager().getDefaultDisplay();
setHeight(display.getHeight());
setWidth(display.getWidth());
setFocusable(true);
setContentView(popup);
// fix to allow Popup to be clickable!
setBackgroundDrawable(new BitmapDrawable());
popup.setOnClickListener(this);
popup.findViewById(R.id.addButton).setOnClickListener(this);
popup.findViewById(R.id.deleteButton).setOnClickListener(this);
}
public void onClick(View v) {
Intent intent = null;
if (v.getId() == R.id.addButton) {
intent = new Intent(caller, AddActivity.class);
intent.putExtra(AddActivity.ACTION_ADD, true);
} else if (v.getId() == R.id.deleteButton) {
intent = new Intent(caller, AddActivity.class);
intent.putExtra(AddActivity.ACTION_DELETE, true);
}
if (intent != null) {
caller.startActivity(intent);
}
TestPopup.this.dismiss();
}
One solution is to call popup.invalidate(); before dismissing the popup.
Related
I'm new to android and I'm having a hard time finding solutions to my problem on my app.
My app is a wordsearch game that uses tapping on the tiles as an input. This is the code for the onClick() of the dynamic textviews on the tablelayout:
text.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
w.setVisibility(View.VISIBLE);
//change the color of tapped textview
text.setTextColor(Color.WHITE);
text.setBackgroundColor(Color.parseColor(mColors[randomNum]));
String b = text.getText().toString();
uTxt.setText(""+uTxt.getText().toString() + b);
//check if answer is in the word grid
if(checkAns(uTxt, list))
{
w.setVisibility(View.GONE);
wC.setText(String.valueOf(Integer.parseInt(wC.getText()+"")-1));
if(Integer.parseInt(wC.getText()+"") == 0){
int newM = minutes*60 + seconds;
dataHelper.insertData(pNameC.getText().toString(), newM, currentDateandTime, Category.leve);
t.cancel();
Context mContext = getApplicationContext();
Activity mActivity = GameScreen.this;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
// Inflate the custom layout/view
View customView = inflater.inflate(R.layout.gameover,null);
// Initialize a new instance of popup window
PopupWindow mPopupWindow = new PopupWindow(
customView,
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
);
Typeface font = Typeface.createFromAsset(getAssets(), "raw2.ttf");
TextView cattxt = (TextView)customView.findViewById(R.id.catTxt);
String ctg = ti.getText().toString();
cattxt.setTypeface(font);
cattxt.setText(ctg);
Button yesB = (Button) customView.findViewById(R.id.maglaro2);
yesB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(GameScreen.this, Category.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in, R.anim.slide_out);
GameScreen.this.finish();
}
});
Button noB = (Button) customView.findViewById(R.id.hindi);
noB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(GameScreen.this, MainActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in, R.anim.slide_out);
GameScreen.this.finish();
}
});
mPopupWindow.showAtLocation(table, Gravity.CENTER,0,0);
}
uTxt.setText("");
}
}
});
Now my problem is I want an UNDO Button that will delete the last character on the uTxt and will change back the color of the last touched textView
Does anyone have any ideas on how to do that?
If yes leave a comment, answer, or suggestion below. TIA!
Typical solution for this problem is the usage of the command pattern (excellent for undo redo functionality).
See https://en.wikipedia.org/wiki/Command_pattern
I want to close the popup window when I click a button, but it seems dismiss function doesn't work and the window is not closing. What did I wrong?
(I'm a beginner, so codes might be 'weird'. Please understand...)
public class AlarmPopup extends Activity {
private PopupWindow popup;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onShowPopup();
}
public void onShowPopup(){
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View view = inflater.inflate(R.layout.alarm_popup, null, false);
final PopupWindow popup = new PopupWindow(view, 400, 300, true);
setContentView(R.layout.alarm_popup);
view.findViewById(R.id.button).post(new Runnable() {
#Override
public void run() {
popup.showAtLocation(view, Gravity.CENTER, 0, 0);
}
});
findViewById(R.id.button).setOnClickListener(mClickListener);
}
Button.OnClickListener mClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) { // dismiss and stop the alarm function on other class
Intent i = new Intent(AlarmPopup.this, AlarmService.class);
stopService(i); // this function is working...
popup.dismiss();
}
};
}
You have declared popup as global and inside your onShowPopup you are creating new object for popup so that local popup will never be accessible from listener so make the changes as below:
public void onShowPopup(){
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View view = inflater.inflate(R.layout.alarm_popup, null, false);
popup = new PopupWindow(view, 400, 300, true);
setContentView(R.layout.alarm_popup);
view.findViewById(R.id.button).post(new Runnable() {
#Override
public void run() {
popup.showAtLocation(view, Gravity.CENTER, 0, 0);
}
});
view.findViewById(R.id.button).setOnClickListener(mClickListener);
}
Popup variable that you are using to dismiss your popup window has not been initialized in the code that you have posted. Your final variable that you have created inside method is local and will not be accessible outside that method.
So initialize your variable or use same variable inside method too.
Context
I'm working with popupwindows to allow a user to quickly rename a cardview in an activity.
I do this by using a ViewSwitcher to swap the TextView (original name) for an EditText(new name).
Problem
When the EditText and PopUpWindow to confirm are present an the user presses "RECENT APPS", you cannot for some reason get back into the app. ie. when you click it, it won't respond.
Diagnosis
I think it's an issue with Window Focus. I've tried EditText.clearFocus() from ET and dismissing all PopUps onPause, no luck.
Is there a way to use onFocusChangeListener to remove this issue?
Code (I've tried to remove as much superfluous items as possible)
TheHubActivity.java
public class TheHubActivity extends AppCompatActivity implements RecyclerViewAdapter.onCardClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
// KEYBOARD
imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
//... Set up recycle view
rvContent = new ArrayList<>();
}
#Override
public void onCardLongClick(Flow longClickedFlow, int cardPosition, View cardViewClicked) {
showLongClickPopUpMenu(longClickedFlow,cardPosition, cardViewClicked);
}
private void showLongClickPopUpMenu(final Flow longClickedFlow, final int cardPosition, final View cardViewClicked) {
LayoutInflater layoutInflater = (LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.popup_window_longclick, null);
LinearLayout viewGroup = (LinearLayout) layout.findViewById(R.id.popup_longclick);
// Creating the PopupWindow
final PopupWindow popup = new PopupWindow(layout, RecyclerView.LayoutParams.WRAP_CONTENT,
RecyclerView.LayoutParams.WRAP_CONTENT);
popup.setFocusable(true);
// Getting a reference to Close button, and close the popup when clicked.
ImageView delete = (ImageView) layout.findViewById(R.id.popup_delete_item);
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*.... Delete current Flow from internal file and UI */
popup.dismiss();
}
});
ImageView edit = (ImageView) layout.findViewById(R.id.popup_edit_item);
edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
popup.dismiss();
renameFlow(cardPosition, cardViewClicked);
}
});
// Displaying the popup at the specified location, + offsets.
popup.showAsDropDown(cardViewClicked, cardViewClicked.getMeasuredWidth(),popupDisplayHeight, Gravity.TOP);
longClickPopup = popup;
}
private void renameFlow(final int cardPosition, final View cardViewClicked) {
final ViewSwitcher switcher = (ViewSwitcher) cardViewClicked.findViewById(R.id.rename_switcher);
final EditText rename = (EditText) switcher.findViewById(R.id.item_flow_rename);
rename.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (rename.hasFocus()) {
showEditPopupWindow(rename, cardViewClicked, switcher, cardPosition);
} else {
imm.hideSoftInputFromWindow(rename.getWindowToken(), 0);
}
}
});
switcher.showNext();
rename.requestFocus();
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
/* Forces keyboard */
}
private void showEditPopupWindow(final EditText newName, View cardViewClicked, final ViewSwitcher switcher, final int cardPosition) {
LayoutInflater layoutInflater = (LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.popup_window_editing, null);
LinearLayout viewGroup = (LinearLayout) layout.findViewById(R.id.popup_editing);
// Creating the PopupWindow
final PopupWindow popup = new PopupWindow(layout, RecyclerView.LayoutParams.WRAP_CONTENT,
RecyclerView.LayoutParams.WRAP_CONTENT);
popup.setFocusable(false); // So that user can edit text
// Getting a reference to Close button, and close the popup when clicked.
ImageView confirmEdit = (ImageView) layout.findViewById(R.id.popup_confirm_item_changes);
confirmEdit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/* .. Changes name of cardview through edit text */
switcher.showNext();
popup.dismiss();
newName.clearFocus();
}
}
});
ImageView cancelEdit = (ImageView) layout.findViewById(R.id.popup_cancel_item_changes);
cancelEdit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switcher.showNext();
popup.dismiss();
}
});
popup.showAsDropDown(cardViewClicked, cardViewClicked.getMeasuredWidth(),popupDisplayHeight, Gravity.TOP);
editingPopup = popup;
}
#Override
protected void onPause() {
dismissPopups();
super.onPause();
}
private void dismissPopups() {
if (longClickPopup!=null && longClickPopup.isShowing()) {
longClickPopup.dismiss();
}
if (editingPopup!=null && editingPopup.isShowing()) {
editingPopup.dismiss();
}
}
}
For Visual People
I solved the issue... and it was surprisingly larger and completely unrelated to the Focus/PopUps (tunnel vision does that I guess).
In my Manifest I was using android:launchMode="singleTop" which was creating weird behaviour when TheHubActivity was sent to recent apps because this was my entrance activity. From the Developer Docs singleTop functions like so:
Similarly, a new instance of a "singleTop" activity may also be created to handle a new intent. However, if the target task already has an existing instance of the activity at the top of its stack, that instance will receive the new intent (in an onNewIntent() call); a new instance is not created. In other circumstances — for example, if an existing instance of the "singleTop" activity is in the target task, but not at the top of the stack, or if it's at the top of a stack, but not in the target task — a new instance would be created and pushed on the stack.
<activity
android:name=".TheHubActivity"
android:label="#string/app_name"
~~~~~~android:launchMode="singleTop"~~~~~~~~
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Hee guys,
So currently I'm using a PopupWindow to display an in app browser. However when pressing the back button it does nothing. I'm using the PopupWindow in another Fragment, then I use a statement to set the PopupWindow in my FragmentActivity and then when I press my back button it should check if the PopupWindow is set or not and dismiss it or not. However it doesn't even run through the onBackPressed.
PopupWindow in fragment:
--> is where I point out the line which makes sure the FragmentActivity gets the PopupWindow as well.
// Use webview for icons and website link.
public void inAppBrowser(String url){
mCursor.moveToFirst();
// Inflate View
LayoutInflater layoutInflater = (LayoutInflater) ((MainActivity) MainActivity.getContext()).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View inflatedView = layoutInflater.inflate(R.layout.browser_window, null, false);
// Control View Childs.
LinearLayout header = (LinearLayout) inflatedView.findViewById(R.id.filter_header);
header.setBackgroundColor(Color.parseColor(color));
Button cancel = (Button) inflatedView.findViewById(R.id.cancel);
Button done = (Button) inflatedView.findViewById(R.id.done);
// Set PopupWindow position.
Display display = ((MainActivity) MainActivity.getContext()).getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// Control PopupWindow.
final PopupWindow popWindow = new PopupWindow(inflatedView, size.x, size.y, true);
popWindow.setAnimationStyle(android.R.anim.fade_in);
popWindow.setFocusable(true);
popWindow.setOutsideTouchable(true);
popWindow.showAtLocation(v, Gravity.BOTTOM, 0, 150);
--> MainActivity.setPopupWindow(popWindow);
// Control WebView
WebView myWebView = (WebView) inflatedView.findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClientAdapter());
myWebView.clearCache(true);
myWebView.clearHistory();
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
MainActivity.setWebView(myWebView);
if (url != null) {
if (url.contains("http://") || url.contains("https://")) {
} else {
url = "http://" + url;
}
myWebView.loadUrl(url);
} else {
popWindow.dismiss();
MainActivity.setPopupWindow(null);
MainActivity.setWebView(null);
}
cancel.setVisibility(View.INVISIBLE);
done.setText("Close");
done.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
popWindow.dismiss();
}
});
}
My onBackPressed code :
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
//check if popupwindow is open
Log.e(TAG, "Check if it runs through this section");
if (popWindow != null) {
if (myWebView != null && myWebView.canGoBack()) {
myWebView.goBack();
} else {
popWindow.dismiss();
popWindow = null;
myWebView = null;
}
}
}
Ignore the WebView for now. That might be a question in the future, but I want the PopupWindow to close first. Any help is appreciated.
Make your PopupWindow not focusable:
final PopupWindow popWindow = new PopupWindow(inflatedView, size.x, size.y, false);
Also remove this line which was redundant:
popWindow.setFocusable(true);
I think you should define a static method removePopupWindow(view v) in MainActivity,
and call it inside onBackPressed() like MainActivity.removePopupWindow(popWindow);
Hope It will help you.
Ok, so this question was asked a long time ago, but I think I have a better solution. What I've done is add an OnDismissListener to my popup. In this listener I've added the code I wanted to execute when the popup got dismissed. This way Android still get's to manage the opening and closing of the popup and I just added a single line to make it work.
This is the way to add one:
yourAwesomePopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
// Your code on dismiss here
}
});
popup.showAtLocation(popupView, Gravity.CENTER,0,0);
popupshowing=true;// define this as a global
#Override
public void onBackPressed() {
if(popupshowing) {
popup.dismiss();
popupshowing=false;
}
else {
super.onBackPressed();
}
}
You can use this.
Dialog dialog = new Dialog(ActivityMain.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST); dialog.setContentView(R.layout.mydialog);
dialog.setCancelable(true);
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
try {
if (mScannerView!=null) {
mScannerView.stopCamera();
}
} catch(Exception e){
e.printStackTrace();
}
}
});
im trying to build share dialog.
in this share dialog I have facebook,whatsapp,mail and more.
im trying the make the background of every view change on touch to indicate the toch.
so far no problem.
the problem is that I also want to let the user move is finger into other option and when he do that the previous background return to his original color and the new view background changes.
i just cant get the hover event at all, and I couldn't trigger other onTouchEvent as long as the first one is still alive.
this is my code so far:
public class customDialogFragment1 extends DialogFragment {
public customDialogFragment1() {
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
postShareUrl=getActivity().getResources().getString(R.string.servicePostShareUrl);
id=getArguments().getString("body");
postTitle=getArguments().getString("subject");
Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
sendIntent.setType("text/plain");
Dialog dialog = new Dialog(getActivity(),android.R.style.Theme_Translucent_NoTitleBar);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),android.R.style.Theme_Translucent_NoTitleBar);
LayoutInflater inflater = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.share_title_layout, null);
// Set title divider color
TextView txtTitle= (TextView) v.findViewById(R.id.share_title);
Typeface tf = Typeface.createFromAsset(getActivity().getResources().getAssets(),
"fonts/OpenSansHebrew-Bold.ttf");
txtTitle.setTypeface(tf);
View layout=inflater.inflate(R.layout.custom_share_layout_inner,null);
builder.setView(layout);
ImageView facebook= (ImageView) layout.findViewById(R.id.imgFaceebook);
ImageView whatsapp= (ImageView) layout.findViewById(R.id.imgWhatsapp);
ImageView more= (ImageView) layout.findViewById(R.id.imgMore);
ImageView mail= (ImageView) layout.findViewById(R.id.imgMail);
facebook.setOnClickListener(imageClickListener);
whatsapp.setOnClickListener(imageClickListener);
more.setOnClickListener(imageClickListener);
mail.setOnClickListener(imageClickListener);
List activities = getActivity().getPackageManager().queryIntentActivities(sendIntent, 0);
Context context=(Activity)getActivity();
for(int i=0;i<activities.size();i++) {
ResolveInfo appPacageName = (ResolveInfo) activities.get(i);
Log.i("pacageName", appPacageName.toString());
if (appPacageName.toString().contains("com.facebook.composer")) {
shareCheckList[0] = appPacageName;
} else if (appPacageName.toString().contains("whatsapp")) {
shareCheckList[1] = appPacageName;
} else if (appPacageName.toString().contains("mail")) {
shareCheckList[2] = appPacageName;
}
}
dialog.setContentView(layout);
Window window = dialog.getWindow();
window.setLayout(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
window.setGravity(Gravity.CENTER);
window.setLayout(MainActivity.screenWidth-90,350);
return dialog;
}
and this is my ontouch listener :
private View.OnClickListener imageClickListener=new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT,getArguments().getString("subject"));
intent.putExtra(Intent.EXTRA_TEXT,getArguments().getString("body"));
switch (v.getId()){
case R.id.imgFaceebook:
if(!shareCheckList[0].toString().isEmpty()){
intent.setClassName(shareCheckList[0].activityInfo.packageName, shareCheckList[0].activityInfo.name);
((Activity)getActivity()).startActivity(intent);
break;
case R.id.imgWhatsapp:
intent.setClassName(shareCheckList[1].activityInfo.packageName, shareCheckList[1].activityInfo.name);
((Activity)getActivity()).startActivity(intent);
}
break;
case R.id.imgMail:
try{
intent.setClassName(shareCheckList[2].activityInfo.packageName, shareCheckList[2].activityInfo.name);
((Activity)getActivity()).startActivity(intent);
break;
case R.id.imgMore:
CustomDialogFragment2 cdf=new CustomDialogFragment2();
Bundle bundle = new Bundle();
bundle.putString("body",id);
bundle.putString("subject", postTitle);
cdf.setArguments(bundle);
cdf.show(getActivity().getFragmentManager(), "customDialogFragment2");
break;
}
}
};
If I understood right, you should use state list:
http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
Just create xml drawable file for every ImageView, and set for each state item with source you need.