How to achieve this in android.https://www.google.com/design/spec/motion/choreography.html#choreography-creation This menu appears from the touch point, tying the element to the point of touch.
Error message in edittext comes in the bottom of the view
You can use PopupWindow and then use popupWindow.showAsDropDown(theView).
Edit:
Here is an example from my code:
LayoutInflater inflater = (LayoutInflater) TimeCheckActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.timecheck_popup,
(ViewGroup) findViewById(R.id.popup_element));
popupWindow = new PopupWindow(layout, 320, 160, true);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setOutsideTouchable(true);
radioButton[1].setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(times.size()>1) {
popupText.setText(times.get(1).toString());
popupWindow.showAsDropDown((View) radioButton[1]);
}
return true;
}
});
I also have xml layout which has Textview ("popupText").
Related
I am using popup window in my app. I want to dismiss the window when user touch outside the window. I have written the below code for the same and its working. But the issue is I have a scrollview inside my window when I tried to scroll it window itself is canceling. How can i prevent that?
mInflater = (LayoutInflater) getActivity()
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View layout = mInflater.inflate(R.layout.help_popup,
null);
mHelpPopup = new PopupWindow(layout, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, true);
mHelpPopup.setOutsideTouchable(true);
mHelpPopup.setTouchable(true);
mHelpPopup.setBackgroundDrawable(new BitmapDrawable());
mHelpPopup.setTouchInterceptor(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Logger.get().d("POPUP_WINDOW", "v: " + v.getTag() + " | event: " + event.getAction());
mHelpPopup.dismiss();
return true;
}
});
mHelpPopup.showAtLocation(layout, Gravity.CLIP_VERTICAL, (int) helpTxtView.getX(), (int) helpTxtView.getY());
I could find out the answer. It was because of touchinterceptor. when i removed that listener it is working fine.
I know how to make android menu using Java or XML and how to use or call but now I am facing a new situation i.e. I want to open menu in a specific place like when I click on image than menu pop-up on that image place.
How can I do it?
Following code will help you to open popup at dynamic place:
public void showMenuPopUp(final View view, final Context mCtx ) {
LayoutInflater layoutInflater = (LayoutInflater) mCtx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.menu_popup, null);
popupWindow = new PopupWindow(popupView, LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT, true);
popupWindow.setFocusable(true);
popupWindow.update();
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchInterceptor(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
popupWindow.dismiss();
return true;
}
return false;
}
});
Button btn1= (Button) popupView.findViewById(R.id.btn1);
Button (new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// button click event
popupWindow.dismiss();
}
});
popupWindow.showAsDropDown(view, 0, 0);
}
Where view is your view on which you have to open popup
To open this popup on Image click write onClickLsitener of your Image like this:
ImageView img = (ImageView) findViewById(R.id.myImageId);
img.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// your code here
showMenuPopUp(v,Activity.this);
}
});
I have answered similar question here , I used PopUpWindow in that example, you can also use DialogFragment but slightly minimum option,both supports custom layout which looks like menu. you can perform similar option on Button you clicked in your screen or the Actionbar button
You have two option two do this using popupwindow, on click of a button you can do 1)showAsDropDown(findViewbyId(R.id.menuitem),0,0) for popupwindow which is good cause it looks like it popped down from the button you clicked or
2)showAtLocation() which takes gravity property like X and Y positions, in which you can mention which place on the screen you want the menu to appear
This is my popupwindow. but it is handling any touch events..
popup = new PopupWindow(popupView, 300, 300, true);
popup.showAsDropDown(v, -30, 0);
popup.setBackgroundDrawable(getResources().getDrawable(R.drawable.background));
popup.setOutsideTouchable(true);
popup.setTouchable(true);
popup.setFocusable(true);
popup.setTouchInterceptor(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TAG", "Touched in the window");
return false;
}
});
Please tell me the problem with this code..
For the sake helping whoever stumbles upon this thread...
Instead of setTouchInterceptor(), I have been using setOnClickListener() or setOnTouchListener(), which are not members of PopupWindow, true, but I simply call a LayoutInflater to get meeself the popup (View) and then set it as the PopupWindow layout. Proceed to do MAGIC with the View member functions as it better suits you.
Code sample:
LinearLayout viewGroup = (LinearLayout) context.findViewById(R.id.my_popup_layout_id);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.popup_layout, viewGroup);
popup = new PopupWindow(context);
popup.setContentView(layout);
popup.setWidth(popupWidth);
popup.setHeight(popupHeight);
//popup.setFocusable(true);
popup.setOutsideTouchable(false);
popup.showAsDropDown(anchorViewOfYourChoice, OFFSET_X, OFFSET_Y);
I have a listview and when the user presses a button I want to gather the coordinates of the button and place an edittext that I inflate right over top of it on the screen. When the user clicks anywhere else on the screen the edittext will disappear and it will fire a method that uses the data the user entered into the box. How would I go about doing something like this? I would like something similar to QuickActions, but not quite as intrusive. Could someone point me in the direction of at least how to go about getting the button coordinates?
Ok, so here is how i've been able to achieve what i'm looking to do. Is it possible to dynamically place a PopupWindow without having to mess with adjusting margins etc.
public void showPopup(View view, View parentView, final int getId, String getLbs){
int pWidth = 100;
int pHeight = 80;
int vHeight = parentView.getHeight(); //The listview rows height.
int[] location = new int[2];
view.getLocationOnScreen(location);
final View pView = inflater.inflate(R.layout.list_popup, null, false);
final PopupWindow pw = new PopupWindow(pView, pWidth, pHeight, false);
pw.setTouchable(true);
pw.setFocusable(true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.showAtLocation(view, Gravity.NO_GRAVITY, location[0]-(pWidth/4), location[1]+vHeight);
final EditText input = (EditText)pView.findViewById(R.id.Input);
input.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
Log.i("Focus", "Focus Changed");
if (hasFocus) {
//Shows the keyboard when the EditText is focused.
InputMethodManager inputMgr = (InputMethodManager)RecipeGrainActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
inputMgr.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT);
}
}
});
input.setText("");
input.requestFocus();
Log.i("Input Has Focus", "" + input.hasFocus());
pw.setOnDismissListener(new OnDismissListener(){
#Override
public void onDismiss() {
changeWeight(getId, Double.parseDouble(input.getText().toString()));
Log.i("View Dismiss", "View Dismissed");
}
});
pw.setTouchInterceptor(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
Log.i("Background", "Back Touched");
pw.dismiss();
return true;
}
return false;
}
});
}
The pWidth and pHeight are the size of the PopupWindow I chose and the vHeight is the height of the main parent view that I collected from the onCreate context. Keep in mind this is not polished code. I still need to add a few things like animate in and out as well as a nice little arrow or something to show what the window is being associated with. The setBackgroundDrawable is very important and if you don't use it you won't be able to click outside the box to close it.
Right now, its weird. I have to click twice outside the box to close the window. The first click just seems to highlight my textbox and the second click actually closes it out. Anyone have any idea why that might be happening?
Messy, depending on your View hierarchy. The getLeft() method (along with getRight, getTop and getBottom) are all relative to the control's View parent. Take a look at getLocationOnScreen and see if it does what you want.
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();
}
});