检测Android导航栏方向

时间:2014-01-11 00:41:49

标签: android

有没有办法知道这个导航栏的横向显示位置:

  • 在Nexus7上它位于底部
  • 在nexus 5上,它在右边。

由于

enter image description here

6 个答案:

答案 0 :(得分:6)

我的解决方案

public static boolean hasNavBar (Resources resources)
{
    int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
    if (id > 0)
        return resources.getBoolean(id);
    else
        return false;
}

public static int getNavigationBarHeight (Resources resources)
{
    if (!Utils.hasNavBar(resources))
        return 0;

    int orientation = resources.getConfiguration().orientation;

    //Only phone between 0-599 has navigationbar can move
    boolean isSmartphone = resources.getConfiguration().smallestScreenWidthDp < 600;
    if (isSmartphone && Configuration.ORIENTATION_LANDSCAPE == orientation)
        return 0;

    int id = resources
        .getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android");
    if (id > 0)
        return resources.getDimensionPixelSize(id);

    return 0;
}

public static int getNavigationBarWidth (Resources resources)
{
    if (!Utils.hasNavBar(resources))
        return 0;

    int orientation = resources.getConfiguration().orientation;

    //Only phone between 0-599 has navigationbar can move
    boolean isSmartphone = resources.getConfiguration().smallestScreenWidthDp < 600;

    if (orientation == Configuration.ORIENTATION_LANDSCAPE && isSmartphone)
    {
        int id = resources.getIdentifier("navigation_bar_width", "dimen", "android");
        if (id > 0)
            return resources.getDimensionPixelSize(id);
    }

    return 0;
}

基于的解决方案 https://android.googlesource.com/platform/frameworks/base/+/9f65c4c34abb07bdda54649ed510af26f16e9c1b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

答案 1 :(得分:6)

部分基于Pauland的答案(反过来基于PhoneWindowManager的实施),以下是我目前正在使用的内容:

  public static boolean isSystemBarOnBottom(Context ctxt) {
    Resources res=ctxt.getResources();
    Configuration cfg=res.getConfiguration();
    DisplayMetrics dm=res.getDisplayMetrics();
    boolean canMove=(dm.widthPixels != dm.heightPixels &&
        cfg.smallestScreenWidthDp < 600);

    return(!canMove || dm.widthPixels < dm.heightPixels);
  }

这适用于Nexus 7 2012和Nexus 4,每个都运行Android 5.1。

在具有永久MENU键的设备上,没有系统栏。根据您的使用情况,您可能需要检查此案例:

ViewConfiguration.get(ctxt).hasPermanentMenuKey()

(其中ctxt是某些Context

就我个人而言,我正在尝试将滑动面板放在与系统条相反的轴上,因为系统条一侧的边框滑动有点难以触发。我不会使用这个或任何其他算法(如依赖于getDecorView()的算法)来做任何关键的事情。

答案 2 :(得分:5)

通过将decor view的属性与当前DisplayMetrics结合使用,您可以找到导航栏位于哪一侧。

// retrieve the position of the DecorView
Rect visibleFrame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame);

DisplayMetrics dm = getResources().getDisplayMetrics();
// check if the DecorView takes the whole screen vertically or horizontally
boolean isRightOfContent = dm.heightPixels == visibleFrame.bottom;
boolean isBelowContent   = dm.widthPixels  == visibleFrame.right;

答案 3 :(得分:3)

我的工作解决方案是:

<div class="lets-talk-out"> </div>
        <div class="slide-popup-box-form-main">
            <div class="slide-popup-box-form">

                <form id="lets-talk-frm" action="contactus.php" method="post" >
                <input type="text"  name="name" id="name" placeholder="Name:" >
                <input type="text"  name="email"  id="email" placeholder="Email:" >
                <input type="text"  name="skype" id="skype" placeholder="Skype" >
                <input type="text"  name="mobile" id="mobile" placeholder="Mobile:" >
                <input type="hidden" name="slider_unlock" value="02" >
                <input type="text"  name="date"   placeholder="Date:" id="ldate" >
                <input type="text"  name="time"  placeholder="Time:" id="ltime" >
                <div class="g-recaptcha" data-sitekey="6Lfc4xETAAAAALO-3I6chqeyOrpfDPRl1u7fW2XD"></div>

                <input type="submit" id="lets-talk" value="submit" name="submit">
                </form>
                </div>

            </div>
<script> 
var k=  jQuery.noConflict();

k(document).ready(function() { 
    var options = { 
        target:        '#lets-talk-out',   // target element(s) to be updated with server response 
    }; 
    k('#ltime').datetimepicker({ 
                        datepicker:false,
                        format:'H:i'
                        });
    k('#ldate').datetimepicker({ 
                        timepicker:false,
                        format: 'Y/m/d',
                         minDate:'-1970/01/01'
                        }); 


    // bind form using 'ajaxForm' 
    k('#lets-talk-frm').ajaxForm({success:function(responseText, statusText, xhr, $form){ 
                                k('.slide-popup-box-form-main').prepend('<h4>'+responseText+'</h4>');
                                k('.slide-popup-box-form').hide();

                                //alert(responseText);
                                //showSlidingDiv();
                                //document.getElementById("lets-talk-out").html(responseText);
                            //  k('#lets-talk-out').html(responseText);
                                },
                                }); 
}); 
     k("#lets-talk-frm").validate({
        rules: {



        name: "required",
        email: {
            required: true,
            email: true
        },

        //skype: "required",
        mobile:{
        required: true,
        digits: true,
         minlength: 7
        },
        date: "required",
        time: "required",



        },
        messages:{
            name: '',
            email: '', skype: '', mobile: '', date: '', time: '', phone: '',
        },




        });






    k( '#slider_full_1' ).sliderCaptcha({
            type: "filled",
            textFeedbackAnimation: 'swipe_overlap',
            hintText: "Swipe to submit",
            width: '300px',
            height: '55px',
            styles: {
                knobColor: "#72ba1c",
                knobColorAfterUnlock: "#000000",
                backgroundColor: "#444",
                textColor: "#fff",
                textColorAfterUnlock: "#fff"
            },
            face: {
                top: 0,
                right: 9,
                icon: 'tisind\images\arrow.png',
                textColor: '#ddd',
                textColorAfterUnlock: '#72ba1c',
                topAfterUnlock: 0,
                rightAfterUnlock: 9,                
                iconAfterUnlock: 'flag'
            },
            events: {
                submitAfterUnlock: 0,
                validateOnServer: 1,
                validateOnServerParamName: "slider_unlock"

            }
        }); 
    var $ = jQuery.noConflict();

</script>

答案 4 :(得分:1)

这适用于我的应用,我使用半透明状态栏和导航栏来设置填充。

boolean navBarOnTheBottom(){
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int viewHeight = displaymetrics.heightPixels;
        if (bkg.getHeight() == viewHeight)
        {
            Log.d(TAG, "nav bar on the side");
            return false;
        }
        else{
            Log.d(TAG, "nav bar on the bottom");
            return true;
        }
    }

bkg它是保存我所有应用视图的主要linearLayout。 确保bkg.getHeight()没有给你0,有些布局确实给了我0

修改 如果上面给出的0

,请获取这样的布局高度
@Override
    public void onWindowFocusChanged (boolean hasFocus) {
        // the height will be set at this point
        bkgHeight = bkg.getHeight();
    }

答案 5 :(得分:0)

请注意,从Android 7.1开始,导航栏也可能位于屏幕的左侧。为确保您始终知道导航栏的位置,请使用DisplayListener来检查Android 7.1及更高版本上的180°屏幕更改,如下所示:How to detect screen rotation through 180 degrees from landscape to landscape orientation?

我已经成功,可靠地使用以下代码来确定导航栏位置的任何更改:

DisplayManager.DisplayListener displayListener;

@Override
protected void onCreate(Bundle savedInstanceState) {

    ...

    displayListener = new DisplayManager.DisplayListener() {
        private int lastRotation =
                ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
                                           .getDefaultDisplay().getRotation();

        @Override
        public void onDisplayAdded(int displayId) {
        }

        @Override
        public void onDisplayChanged(int displayId) {
            int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
                                   .getDefaultDisplay().getRotation();
            if (rotation == Surface.ROTATION_90
                        && lastRotation == Surface.ROTATION_270
                    || rotation == Surface.ROTATION_270
                        && lastRotation == Surface.ROTATION_90) {
                onNavigationBarMoved(true);
            }
            lastRotation = rotation;
        }

        @Override
        public void onDisplayRemoved(int displayId) {
        }
    };
    DisplayManager displayManager =
            (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
    displayManager.registerDisplayListener(displayListener, null);
    onNavigationBarMoved(false);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    onNavigationBarMoved(false);
}

@Override
protected void onDestroy() {
    if (displayListener != null) {
        DisplayManager displayManager =
                (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
        displayManager.unregisterDisplayListener(displayListener);
    }
    super.onDestroy();
}

protected void onNavigationBarMoved(boolean landscapeScreenRotation) {
    boolean leftSideNavigationBar = Build.VERSION.SDK_INT > Build.VERSION_CODES.N
                         && ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
                                .getDefaultDisplay().getRotation() == Surface.ROTATION_270;
    // add whatever else you need here
}

请记住,将已经横向移动的设备旋转180°时将不会重新创建“活动”,因此在onNavigationBarMoved内,landscapeScreenRotation的值会告诉您何时发生这种情况,以便您重新调整您的用户界面相应。