android 华为虚拟按键适配

为了设置状态栏,会设置透明标签,而华为手机的虚拟按键有可能会遮挡底部导航栏。

 requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ad_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

不要设置FLAG_TRANSLUCENT_NAVIGATION。
由于项目中WebView输入数据,软键盘不会顶上布局,遮盖住页面,使用下边此类解决冲突后出现底部导航栏被遮挡的问题。


/**
 * webview-软键盘-冲突
 */

public class KeyBoardListenerManager {

    private Activity activity;

    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

    private static KeyBoardListenerManager keyBoardListener;


    public static KeyBoardListenerManager newInstance(Activity activity) {
        keyBoardListener = new KeyBoardListenerManager(activity);
        return keyBoardListener;
    }


    public KeyBoardListenerManager(Activity activity) {
        super();
       // TODO Auto-generated constructor stub
        this.activity = activity;

    }


    public void init() {

        FrameLayout content = (FrameLayout) activity
                .findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
                    public void onGlobalLayout() {
                        possiblyResizeChildOfContent();
                    }
                });
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent
                .getLayoutParams();


    }


    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView()
                    .getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard / 4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard
                        - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }


    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    }

}

调用方式为:KeyBoardListenerManager.newInstance(this).init();
出现华为虚拟按键冲突问题:
解决方案使用下面此类,此类主要作为封装处理特殊手机的工具类。


/**
 * 手机操作系统检测
 */

public class PhoneSystemManager {

    public static final String SYS_EMUI = "sys_emui";// 华为
    public static final String SYS_MIUI = "sys_miui";// 小米
    public static final String SYS_FLYME = "sys_flyme";// 魅族
    public static final String SYS_NORMAL = "sys_normal";// 一般市面手机


    private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
    private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
    private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";
    private static final String KEY_EMUI_API_LEVEL = "ro.build.hw_emui_api_level";
    private static final String KEY_EMUI_VERSION = "ro.build.version.emui";
    private static final String KEY_EMUI_CONFIG_HW_SYS_VERSION = "ro.confg.hw_systemversion";

    public static String getTelPhoneSystem() {
        String SYS = SYS_NORMAL;
        try {
            Properties prop = new Properties();
            prop.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
            if (prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null
                    || prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null
                    || prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null) {
                SYS = SYS_MIUI;//小米
            } else if (prop.getProperty(KEY_EMUI_API_LEVEL, null) != null
                    || prop.getProperty(KEY_EMUI_VERSION, null) != null
                    || prop.getProperty(KEY_EMUI_CONFIG_HW_SYS_VERSION, null) != null) {
                SYS = SYS_EMUI;//华为
            } else if (getMeizuFlymeOSFlag().toLowerCase().contains("flyme")) {
                SYS = SYS_FLYME;//魅族
            }
        } catch (IOException e) {
            e.printStackTrace();
            return SYS;
        }
        return SYS;
    }

    public static String getMeizuFlymeOSFlag() {
        return getSystemProperty("ro.build.display.id", "");
    }

    private static String getSystemProperty(String key, String defaultValue) {
        try {
            Class clz = Class.forName("android.os.SystemProperties");
            Method get = clz.getMethod("get", String.class, String.class);
            return (String) get.invoke(clz, key, defaultValue);
        } catch (Exception e) {
        }
        return defaultValue;
    }


    /** 设置透明状态栏目
        setMiuiStatusBarDarkMode(this, true);
        setMeizuStatusBarDarkIcon(this, true);
     **/
    public static boolean setMiuiStatusBarDarkMode(Activity activity, boolean darkmode) {
        Class clazz = activity.getWindow().getClass();
        try {
            int darkModeFlag = 0;
            Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
            Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
            darkModeFlag = field.getInt(layoutParams);
            Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
            extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public static boolean setMeizuStatusBarDarkIcon(Activity activity, boolean dark) {
        boolean result = false;
        if (activity != null) {
            try {
                WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class
                        .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class
                        .getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                activity.getWindow().setAttributes(lp);
                result = true;
            } catch (Exception e) {
            }
        }
        return result;
    }

    /**
     * 处理华为手机虚拟按键和底部导航遮挡问题
     * 出现原因-
     * getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
     * getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
     * 加:
     * -android::fitsSystemWindows="true"
     * 去除-FLAG_TRANSLUCENT_NAVIGATION
     * -仍旧不行使用本类-在setContentView(……
     * if (AndroidWorkaround.checkDeviceHasNavigationBar(this))
     * {
     * AndroidWorkaround.assistActivity(findViewById(android.R.id.content));
     * }
     *
     */
    public static class AndroidWorkaround {

        public static void assistActivity(View content) {
            new AndroidWorkaround(content);
        }

        private View mChildOfContent;
        private int usableHeightPrevious;
        private ViewGroup.LayoutParams frameLayoutParams;

        private AndroidWorkaround(View content) {
            mChildOfContent = content;
            mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                public void onGlobalLayout() {
                    possiblyResizeChildOfContent();
                }
            });
            frameLayoutParams = mChildOfContent.getLayoutParams();
        }

        private void possiblyResizeChildOfContent() {
            int usableHeightNow = computeUsableHeight();
            if (usableHeightNow != usableHeightPrevious) {

                frameLayoutParams.height = usableHeightNow;
                mChildOfContent.requestLayout();
                usableHeightPrevious = usableHeightNow;
            }
        }

        private int computeUsableHeight() {
            Rect r = new Rect();
            mChildOfContent.getWindowVisibleDisplayFrame(r);
            return (r.bottom);
        }

        /** 获取虚拟功能键高度 */

        public static int getVirtualBarHeigh(Context context) {

            int vh = 0;

            WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();
            DisplayMetrics dm = new DisplayMetrics();

            try {

                @SuppressWarnings("rawtypes")
                Class c = Class.forName("android.view.Display");

                @SuppressWarnings("unchecked")
                Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);

                method.invoke(display, dm);
                vh = dm.heightPixels - windowManager.getDefaultDisplay().getHeight();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return vh;
        }

        public static boolean checkDeviceHasNavigationBar(Context context) {
            boolean hasNavigationBar = false;
            Resources rs = context.getResources();
            int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
            if (id > 0) {
                hasNavigationBar = rs.getBoolean(id);
            }
            try {
                Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
                Method m = systemPropertiesClass.getMethod("get", String.class);
                String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
                if ("1".equals(navBarOverride)) {
                    hasNavigationBar = false;
                } else if ("0".equals(navBarOverride)) {
                    hasNavigationBar = true;
                }
            } catch (Exception e) {

            }
            return hasNavigationBar;
        }
    }
}

最终得以解决。
请在加载布局文件后使用。
调用方法:

/**
     * 虚拟按键-tangZd
     */
    private void doSpecialiSomethingAsVirtualBar(){

        KeyBoardListenerManager.newInstance(this).init();
        if (PhoneSystemManager.AndroidWorkaround.checkDeviceHasNavigationBar(this)) {
            PhoneSystemManager.AndroidWorkaround.assistActivity(findViewById(android.R.id.content));
            ViewStub stub = (ViewStub) findViewById(R.id.view_stub);
            stub.inflate();
            View enuiStubView = this.findViewById(R.id.enuiNatView);
            LinearLayout.LayoutParams zLayoutParams = (LinearLayout.LayoutParams) enuiStubView.getLayoutParams();
            zLayoutParams.height = PhoneSystemManager.AndroidWorkaround.getVirtualBarHeigh(this);
            enuiStubView.setLayoutParams(zLayoutParams);
        }
    }

需要在对应布局的最底部增加布局:

 <ViewStub
        android:id="@+id/view_stub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/enui_layout"/>

enui_layout布局文件代码:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="@color/black"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <View
        android:id="@+id/enuiNatView"
        android:background="@color/black"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

LinearLayout>

你可能感兴趣的:(android 华为虚拟按键适配)