Android系统服务---WindowManager概念-实战-深入理解

74 阅读3分钟

#简介

  • Android提供的一个系统服务——WindowManager(窗口管理服务), 是显示View最底层!
  • WindowManagerAndroid为我们提供的用于与窗口管理器进行交互的一个API;

- 我们知道**`App的界面`都是 由`Acitivty`组成, 而`Activity`又由`View`组成, 当我们想显示一个`界面`的时候, 可能首先想到`Activity`,又或者是`Dialog`和`Toast`。** - 但是有些情况下, `Activity、Dialog、Toast`可能`满足不了`我们的`需求`, 比如, 仅要做一个`简单的显示`的话 用`Activity`显得有点`多余`了, 而`Dialog`又需要`Context`对象, `Toast`又不可以点击; - **对于以上情况, 我们便可以用`WindowManager`来`添加View`到`屏幕上`, 或者从屏幕上`移除View`! 它就是`管理Android窗口机制`的一个`接口`, `显示View`的`最底层`!**
  • Toast,Activity,Dialog的底层都用到了WindowManager

  • WindowManager全局的!

  • 该类的核心

    • 调用addViewremoveViewupdateViewLayout等方法 来显示View
    • 通过WindowManager.LayoutParams这个API来 设置相关的属性




#使用 ①获得WindowManager对象:

WindowManager wManager = getApplicationContext().getSystemService(Context. WINDOW_ SERVICE);

②获得WindowManager.LayoutParams对象,为后续操作做准备

WindowManager.LayoutParams wmParams=new WindowManager.LayoutParams();

###使用实例: #####实例1:获取屏幕宽高 在Android 4.2前,用下述方法获得屏幕宽高:

public static int[] getScreenHW(Context context) {
    WindowManager manager = (WindowManager)context
    .getSystemService(Context.WINDOW_SERVICE);
    Display display = manager.getDefaultDisplay();
    int width = display.getWidth();
    int height = display.getHeight();
    int[] HW = new int[] { width, height };
    return HW;
}

而上述的方法在Android 4.2以后就过时了,之后该用另一种方法获得屏幕宽高:

public static int[] getScreenHW2(Context context) {
    WindowManager manager = (WindowManager) context.
    getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics dm = new DisplayMetrics();
    manager.getDefaultDisplay().getMetrics(dm);
    int width = dm.widthPixels;
    int height = dm.heightPixels;
    int[] HW = new int[] { width, height };
    return HW;
}

然后可以再另外写两个获取宽以及高的方法, 这里以第二种获得屏幕宽高为例:

public static int getScreenW(Context context) {
    return getScreenHW2(context)[0];
}

public static int getScreenH(Context context) {
    return getScreenHW2(context)[1];
}

开始时候可以将以上代码封装成工具类;

或者直接直接获取:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WindowManager wManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

        DisplayMetrics dm = new DisplayMetrics();

        wManager.getDefaultDisplay().getMetrics(dm);
        Toast.makeText(MainActivity.this, "当前手机的屏幕宽高:" + dm.widthPixels + "*" +
                dm.heightPixels, Toast.LENGTH_SHORT).show();
    }
}
public class MainActivity extends AppCompatActivity {

    private TextView tv_test;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv_test = findViewById(R.id.tv_test);

        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024 / 1024);

        DisplayMetrics outMetrics = new DisplayMetrics();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            getWindowManager().getDefaultDisplay().getRealMetrics(outMetrics);
        }

        int widthPixel = outMetrics.widthPixels;
        int heightPixel = outMetrics.heightPixels;

        String text = "最大运行内存是 " + maxMemory + "M" + "\n";
        text += "屏宽 = " + widthPixel + "像素, 屏高 = " + heightPixel + "像素";

        tv_test.setText(text);


    }
}

####实例2:设置窗口全屏显示

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
getSupportActionBar().hide();

#####实例3:保持屏幕常亮

public void setKeepScreenOn(Activity activity,boolean keepScreenOn)  
{  
    if(keepScreenOn)  
    {  
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);  
    }else{  
        activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);  
    }  
} 




#Window与WindowManager

  • Window表示一个窗口的概念, 在日常开发中直接接触Window的机会并不多, 但是在某些特殊时候 需要在桌面上显示一个类似悬浮窗的东西, 这种效果就需要用Window实现。

  • Window是一个抽象类,它的具体实现PhoneWindow

  • 创建一个Window是很简单的事, 只需要通过WindowManager即可完成。

  • WindowManager是外界访问Window入口Window具体实现位于WindowManagerService中, WindowManagerWindowManagerService的交互是一个IPC过程

  • Android中所有的视图都是通过Window呈现的, 不管是ActivityDialog还是Toast, 它们的视图实际上都是附加在Window上的, 因此Window实际是View的直接管理者。

View的事件分发机制也可以知道, 单击事件Window传递给DecorView, 然后再由DecorView传递给我们的View, 就连Activity的设置视图的方法setContentView在底层也是通过Window来完成的。