界面精确布局的探究

来源:互联网 发布:three.js注释库 编辑:程序博客网 时间:2024/05/16 12:02

界面精确布局的探究

在多布局的时候会有这样的困扰,设置dp值使蒙层布局能够纹丝合缝的覆盖掉底层,但是宽屏手机如:魅族、华为荣耀,小屏手机如:oppo。总会出现覆盖的图“走位”。设置dp值只能使多数手机适配,下面的方法会让所有的手机都能适配。

实施步骤

  • 1 找到底层布局的left,top,由于get*()方法在sign控件界面加载出来前为零,咱们略作延迟,Handler post延迟时间为
    SystemClock.uptimeMillis()+delaytime

        new Handler().postDelayed(new Runnable() {        @Override        public void run() {            // TODO Auto-generated method stub            sign.getLocationOnScreen(loaction);            left = sign.getLeft();            top = sign.getTop();            right = sign.getRight();            bottom = sign.getBottom();            statusH = 60;//60为状态栏的高度,为了适配不同的手机,动态获取。demo中是在普通activity中拿的值。            signDialog = new SignGuideDialog(mActivity,R.layout.layout_guide_sign);            signDialog.show();            //GuideControlUtil.getInstance(mActivity).setFinishShowSignGuide();            //signDialog.setDialogViewClick(this);        }    }, 100);

也可以在onWindowFocusChanged(boolean hasfocus)中得到这些值,不需要Handler。另外一种情况就是需要覆盖的View可能位置会被移动,再去执行sign.getLocationOnScreen(loaction);得到的结果与之前没有移动的时候取得的值相同。这里面还包含状态栏的高度。在精确的计算中还得减去这部分。

解决的方法是,为该View添加监听

ViewTreeObserver vto = imageView.getViewTreeObserver();   vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override  public void onGlobalLayout() { imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this); imageView.getHeight();imageView.getWidth();imageView.getTop();}   });

ViewTreeObserver是专门监听绘图回调的,我们在每次监听前remove前一次的监听,避免重复监听。

  • 2 将left,top传给蒙层,设置蒙层的layoutparams。

    public void initLayout(){    ImageView imgRect = (ImageView) findViewById(R.id.guide_sign);    int left = UnLoginSignDialog.left;    int right = UnLoginSignDialog.right;    int top = UnLoginSignDialog.top;    int bottom = UnLoginSignDialog.bottom;    int[] loaction = UnLoginSignDialog.loaction;    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(right-left, bottom-top);    //当然也可以用imgRect.getLayoutParams得到布局文件中的属性,修改部分属性后,imgRect.setLayoutParams    params.leftMargin = loaction[0];    params.topMargin = loaction[1]-UnLoginSignDialog.statusH;    imgRect.setLayoutParams(params);}

延伸扩展

得到状态栏高度

    private int getStatusLayerHeight(){        Rect frame = new Rect();        getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);        int statusBarHeight = frame.top;        return statusBarHeight;    }

得到标题栏高度

private void getTitleLayerHeight(){    int contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();    //statusBarHeight是上面所求的状态栏的高度    int titleBarHeight = contentTop - getStatusLayerHeight();}

得到全屏高度

 private static DisplayMetrics sDisplayMetrics;public static void init(Context context) {    sDisplayMetrics = context.getResources().getDisplayMetrics();    checkScreen();}/** * 获取屏幕宽度 单位:像素 * * @return 屏幕宽度 */public static int getWidthPixels() {    return sDisplayMetrics.widthPixels;}/** * dp 转 px * * @param dp dp值 * @return 转换后的像素值 */public static int dp2px(int dp) {    return (int) (dp * sDisplayMetrics.density + ROUND_DIFFERENCE);}/** * dp 转 px * * @param dp dp值 * @return 转换后的像素值 */public static float dp2px(float dp) {    return dp * sDisplayMetrics.density + ROUND_DIFFERENCE;}/** * px 转 dp * * @param px px值 * @return 转换后的dp值 */public static int px2dp(int px) {    return (int) (px / sDisplayMetrics.density + ROUND_DIFFERENCE);}

许多手机有NavigationBar,有些是在屏幕下方,有些是在实体键盘中,这部分也会算入屏幕大小。这样会造成布局控件在onMeasure()方法操作有误差。故需要判断是否存在,如果存在那么高度几何

是否存在NavigationBar

private 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) {Log.w(TAG, e);}return hasNavigationBar;}

- 获取NavigationBar的高

private static int getNavigationBarHeight(Context context) {    int navigationBarHeight = 0;    Resources rs = context.getResources();    int id = rs.getIdentifier("navigation_bar_height", "dimen", "android");    if (id > 0 && checkDeviceHasNavigationBar(context)) {        navigationBarHeight = rs.getDimensionPixelSize(id);    }    return navigationBarHeight;}

7/2/2015 9:26:41 AM

0 0
原创粉丝点击