Android Popupwindow Usage Resolution _android

Source: Internet
Author: User

Popupwindow use
Popupwindow This class is used to implement a pop-up box that uses a view of any layout as its content, and this pop-up is suspended above the current activity.

Popupwindow Use Demo
the use of this class, no longer too much explanation, directly on the code.
such as the layout of the pop-up box:

<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android=
"http://schemas.android.com/apk/" Res/android "
  android:layout_width=" match_parent "
  android:layout_height=" Wrap_content "
  android: Background= "#FFBBFFBB"
  android:orientation= "vertical" >

  <textview
    android:layout_width= "match _parent "
    android:layout_height=" wrap_content "
    android:padding=" 10DP "
    android:text=" Hello my Window "
    android:textsize=" 20sp "/>

  <button
    android:id=" @+id/button1 "
    android:layout_ Width= "Match_parent"
    android:layout_height= "wrap_content"
    android:padding= "10DP"
    android:text= " Button "
    android:textsize=" 20sp "/>

</LinearLayout>

There is only one button in the layout of the activity, and a pop-up box will be pressed, and the activity code is as follows:

Package Com.example.hellopopupwindow;
Import Android.os.Bundle;
Import android.app.Activity;
Import Android.content.Context;
Import Android.util.Log;
Import Android.view.LayoutInflater;
Import android.view.MotionEvent;
Import Android.view.View;
Import Android.view.View.OnClickListener;
Import Android.view.View.OnTouchListener;
Import Android.view.ViewGroup.LayoutParams;
Import Android.widget.Button;
Import Android.widget.PopupWindow;

Import Android.widget.Toast;

  public class Mainactivity extends activity {private context mcontext = null;
    @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);

    Setcontentview (R.layout.activity_main);

    Mcontext = this;
    Button button = (button) Findviewbyid (R.id.button); Button.setonclicklistener (New View.onclicklistener () {@Override public void OnClick (view view) {sh
      Owpopupwindow (view);
  }
    }); private void Showpopupwindow (view view) {//A custom layout, as shown content View Contentview = Layoutinflater.from (Mcontext). Inflate (R.layout.pop_window, NULL);
    Set Button click event Button button = (button) Contentview.findviewbyid (R.id.button1); Button.setonclicklistener (New Onclicklistener () {@Override public void OnClick (View v) {Toast.maket
      Ext (Mcontext, "button is pressed", Toast.length_short). Show ();

    }
    });  Final Popupwindow Popupwindow = new Popupwindow (Contentview, layoutparams.wrap_content, Layoutparams.wrap_content,

    true);

    Popupwindow.settouchable (TRUE); Popupwindow.settouchinterceptor (New Ontouchlistener () {@Override public boolean ontouch (View V, motionevent

        Event) {log.i ("Mengdd", "Ontouch:");
        return false;

    If this returns true, the touch event will be intercepted//intercepted after the Popupwindow ontouchevent is not invoked, so clicking the external area cannot dismiss}}); If you do not set the background of the Popupwindow, either click on the external area or the back button can not dismiss the frame//I think this is a bug in the API Popupwindow. Setbackgrounddrawable (Getresources (). getdrawable (R.drawable.selectmenu_bg_downward));

  Set the parameters, then show Popupwindow.showasdropdown (view);

 }

}

The layout of the pop-up box has a TextView and a Button,button Click to display toast, as shown in figure:

The first implementation of the time encountered a problem, that is, pop-up box will not be pressed back when the time to disappear, click the frame outside the box did not disappear normally, search for a moment, all said as long as the setting of the background is good.
Then I found a picture, and sure enough the frame can be normal dismiss (see note).

Popupwindow Source Analysis
to answer the above question, look at the source code (the latest API level 19,android 4.4.2).
1. Display method
The display provides two forms:
showatlocation () is displayed at the specified location with two method overloads:

public void Showatlocation (View parent, int gravity, int x, int y) public

void Showatlocation (IBinder token, int Gravi ty, int x, int y) 

Showasdropdown () is displayed around a reference view with three method overloads:

public void Showasdropdown (view anchor) public

void Showasdropdown (view anchor, int xoff, int yoff) public void

Showasdropdown (View anchor, int xoff, int yoff, int gravity) 

The last method with gravity parameters is introduced by API 19.
The pop-up method requires first preparepopup () , and finally Invokepopup () .
The Prepare method can be seen with no background:

  /** * <p>prepare the popup by embedding in into a new viewgroup if the * background drawable are NOT null. If embedding is required, the layout * parameters ' are mnodified to take into account the background ' s * paddi ng.</p> * * @param p The layout parameters of the popup ' s content view/private void Preparepopup (Windo Wmanager.layoutparams p) {if (Mcontentview = null | | | mcontext = NULL | | | mwindowmanager = = NULL) {throw new I Llegalstateexception ("You must specify a valid content view by" + "calling Setcontentview () before attempting t

    O Show the Popup. ");}
      if (mbackground!= null) {final Viewgroup.layoutparams layoutparams = Mcontentview.getlayoutparams ();
      int height = ViewGroup.LayoutParams.MATCH_PARENT;  if (layoutparams!= null && layoutparams.height = = ViewGroup.LayoutParams.WRAP_CONTENT) {height
      = ViewGroup.LayoutParams.WRAP_CONTENT; }//When a BAckground is available, we embed the content view//within another view that owns the background drawable Pop
      Upviewcontainer Popupviewcontainer = new Popupviewcontainer (mcontext); Popupviewcontainer.layoutparams listparams = new Popupviewcontainer.layoutparams (ViewGroup.LayoutParams.MATCH_P
      arent, height);
      Popupviewcontainer.setbackgrounddrawable (Mbackground);

      Popupviewcontainer.addview (Mcontentview, listparams);
    Mpopupview = Popupviewcontainer;
    else {mpopupview = Mcontentview; } mpopupviewinitiallayoutdirectioninherited = (mpopupview.getrawlayoutdirection () = = View.layout_direction_inh
    Erit);
    Mpopupwidth = P.width;
  Mpopupheight = P.height;

 }

2. Effect of NULL background on touch events
If you have a background, Will be outside the Contentview after a layer of popupviewcontainer as a mpopupview, if no background, then directly with Contentview as Mpopupview.
and this popupviewcontainer is an internal private class that inherits Framelayout, where it rewrites the distribution of key and touch events:  

 @Override public boolean dispatchkeyevent (KeyEvent event) {if (event.getkeycode () = = Keyevent.keycode_back) {
        if (getkeydispatcherstate () = null) {return super.dispatchkeyevent (event); } if (event.getaction () = = Keyevent.action_down && event.getrepeatcount () = = 0) {K
          Eyevent.dispatcherstate state = Getkeydispatcherstate ();
          if (state!= null) {state.starttracking (event, this);
        return true;
          else if (event.getaction () = = keyevent.action_up) {keyevent.dispatcherstate state = Getkeydispatcherstate ();
            if (state!= null && state.istracking (event) &&!event.iscanceled ()) {dismiss ();
          return true;
      } return Super.dispatchkeyevent (event);
      else {return super.dispatchkeyevent (event); @Override public boolean dispatchtouchevent (motioneventEV {if (mtouchinterceptor!= null && mtouchinterceptor.ontouch (this, Ev)) {return true;
    return super.dispatchtouchevent (EV);
      @Override public boolean ontouchevent (Motionevent event) {final int x = (int) event.getx ();
      
      Final int y = (int) event.gety (); if ((event.getaction () = = Motionevent.action_down) && ((x < 0) | | (x >= getwidth ()) | | (Y < 0) | | (Y >= getheight ()))
        {Dismiss ();
      return true;
        else if (event.getaction () = = Motionevent.action_outside) {dismiss ();
      return true;
      else {return super.ontouchevent (event);

 }
    }

Because the Popupview itself does not rewrite key and touch event processing, if there is no package for this outer container class, clicking the back key or the outer area does not cause the frame to disappear.

Supplementary case: The window does not disappear, but the event is passed down
Mentioned above:
Set the Popupwindow background, click the Back button or click on the outside area of the window, the window will be dismiss.
Conversely, if you do not set the Popupwindow background, then click the Back button and click on the outside area of the window, the window will not disappear.
So, if I want an effect, click on the external area, the window does not disappear, but the click event will be sent to the following activity, such as the following is a webview, I would like to click on the link inside.

Studied for a long time, said to be to the window to set a FLAG,WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
Look at the source code, the setting of this flag is controlled by a field called Mnottouchmodal, but the set method that sets the field is marked as @hide.
So you want to call through the method of reflection:

 /**
   * Set Whether this window are touch modal or if outside touches would be sent
   * to
   * Other windows behind it .
   * */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 ();
    }

  }

And then in the program:
Uiutils.setpopupwindowtouchmodal (Popupwindow, false);

Events outside the Popupwindow can be passed on to the following activity.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.