27

I can't find a way to obtain a reference the Window containing an arbitrary View v. I found getWindowToken, but I can't figure out how to use it? Does anyone know how?

Also, does anyone know why it returns an IBinder rather than a Window?

Casebash
  • 114,675
  • 90
  • 247
  • 350

2 Answers2

19

Well... since all views have a reference of the activity that created them (Context), you can use that Context to get a reference of the window. Let me show you this example I wrote some minutes ago:

// main activity
import android.app.Activity;
import android.os.Bundle;
public class GetWindow extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyView view = new MyView(this);
        view.changeSomethingInWindow(); // keep an eye on this method
        setContentView(view);
    }
}

Then, inside your view you can do this:

// your view :D
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class MyView extends View{
    public MyView(Context context) {
        super(context);
    }

    @Nullable
    private Activity getActivity() {
        if (context == null) return null;
        if (context instanceof Activity) return (Activity) context;
        if (context instanceof ContextWrapper) return getActivity(((ContextWrapper)context).getBaseContext());
        return null;
    }
 
    public void changeSomethingInWindow(){
        // get a reference of the activity
        Activity parent = getActivity();
        if(parent == null) return;
        // using the activity, get Window reference
        Window window = parent.getWindow();
        // using the reference of the window, do whatever you want :D
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
}

In this case, I change the mode the Window is displayed to Fullscreen. Hope this help you. Tell me if you get in trouble with this.

Community
  • 1
  • 1
Cristian
  • 198,401
  • 62
  • 356
  • 264
  • 2
    Thank you for your answer. Using getWindow and casting to an activity was a good idea. I don't suppose you know why an `IBinder` is returned rather than a `Window`? – Casebash May 12 '10 at 06:45
  • 1
    Hello Casidiablo, there is a problem with your Code. This is only possible for views you create in your own code in a way that the context you use in your custom constructor is an activity. I tried the getContext Method of an Item from a ListAdapter and in this case I get a Context not an Activity. Activity is a subclass from Context this means you can get a Context object that could not be casted into an Activity. My test code ended in a ClassCastException. – Janusz May 12 '10 at 08:01
  • 98
    Misleading answer. Not all views are used in Activity! Some views are in PopupMenu, or Dialog, or AppWidgetProvider. You'd get cast exception, or wrong Window. Dialog has its own window. Revise your answer. – Pointer Null Mar 15 '12 at 14:44
  • Yes. Activity parent = (Activity)getContext(); code can occur exception like below. java.lang.ClassCastException: android.app.Application cannot be cast to android.app.Activity – theWook Feb 11 '14 at 05:56
  • So how would one go about fixing this? I'm in the same situation here. ClassCastException\ – JP Wile Mar 15 '14 at 03:01
  • @PointerNull Do you know how to get dialog window? – zeeali Mar 08 '17 at 16:00
  • @zeeali: simply Dialog.getWindow() – Pointer Null Mar 10 '17 at 18:15
  • @PointerNull I need to get it in the same method in the answer above just like `parent.getWindow();` – zeeali Mar 11 '17 at 07:15
  • but can an activity can have several window ? – zeus May 30 '17 at 07:11
  • I submitted an edit, check it out when it gets approved. – Dragos Rachieru Mar 25 '21 at 08:26
0

I know this is an old question but when searched Google still redirects to here, and since the above answer is not completely valid, here is what I've done to change window flags inside the view. (The above code basically does the exact thing anyway, but it assumes all views are attached to an Activity.)

It doesn't get the actual Window instance, but it returns the attributes instead, which allows to update the flags, or anything a window has to offer at this point.

The decor view, or the top view that is attached the window should have an instance of WindowManager.LayoutParams and there, you should be able to set the required flags, because the params have a WindowManager.LayoutParams.flags integer value. Here is how to get the window params.

private WindowManager.LayoutParams tryGetWindowParams()
{
    View view = this;
    if (view.getLayoutParams() instanceof WindowManager.LayoutParams)
        return (WindowManager.LayoutParams) view.getLayoutParams();
    while (view.getParent() instanceof View)
    {
        view = (View) view.getParent();
        if (view.getLayoutParams() instanceof WindowManager.LayoutParams)
            return (WindowManager.LayoutParams) view.getLayoutParams();
    }
    return null;
}

After that, you should be able to just do this (the example will be the FLAG_NOT_TOUCHABLE flag, but you can use any other window flag as required.)

private boolean setWindowNotTouchable()
{
    WindowManager.LayoutParams windowParams = tryGetWindowParams();
    if (windowParams != null)
    {
        if ((windowParams.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) == 0)
        {
            windowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
            requestLayout();
        }
        return true;
    }
    return false;
}

private boolean setWindowTouchable()
{
    WindowManager.LayoutParams windowParams = tryGetWindowParams();
    if (windowParams != null)
    {
        if ((windowParams.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
        {
            windowParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
            requestLayout();
        }
        return true;
    }
    return false;
}

Don't forget to call View.requestLayout() as the window params need to get updated.

Furkan Yurdakul
  • 2,801
  • 1
  • 15
  • 37