1

I've tested on several other devices and my UI looks fine.

However on the Samsung Note 3, the UI is getting cut off on the bottom.

I have logged the system specs and done the math. I have the screen height of the device at 1920.

I have a button that is sized at 108 x 108.

I want that button resting on the bottom of the screen (I am not using XML, I am using Java).

    _button.setMinimumHeight(buttonDimension);
    _button.setMaxHeight(buttonDimension);
    _button.setY(1920 - 108);

However this results (on only the Samsung Note 3) in the bottom of the button being cut off. Also if I try to right align there is a slight cut off there too. It looks like its off by about 25 pixels on the bottom.

What is going on here?

It looks like Samsung considers a smaller area below and to the right of the actual rendering window as part of the 'screen height'.

Do you know how I can get the actual display height of the screen in cases where its off from the reported value?

If I use layoutparams and align to bottom, it does work perfectly but I need it to work with the pixel data.

Aggressor
  • 13,323
  • 24
  • 103
  • 182

2 Answers2

1

Why are you hardcoding dimensions in there? Just because the screen height is 1920x1080 doesn't mean you actually have that many pixels available for your application (unless you're using immersive full-screen mode).

What type of layout is your button in? If it's in a FrameLayout, just set the layout_gravity of the button to bottom|center_horizontal. From Java, that would look like:

FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) _button.getLayoutParams();
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
_button.requestLayout();

RelativeLayout? Just use layout_centerHorizontal and layout_alignParentBottom:

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) _button.getLayoutParams();
params.addRule(RelativeLayout.CENTER_HORIZONTAL);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
_button.requestLayout();

EDIT: Looking at your recent edit, you should just use the actual dimensions of the parent to determine the positioning. You can add an OnGlobalLayoutListener to the parent layout to determine its size:

parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        parent.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        int parentHeight = parent.getHeight();
        // do your positioning
    }
}
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • I was using hardcode values to make my question easier to understand. I calculate the dimensions of the phone on the fly per device. I am in Immersive full-screen mode. – Aggressor May 25 '15 at 19:18
  • I also calculate for the fact that some phones have a navigation bar and I subtract that height value. But on the Samsung there is this extra padding and I have no idea what it is? – Aggressor May 25 '15 at 19:19
  • parent.height() now thats an idea. Im going to try that now! – Aggressor May 25 '15 at 19:20
  • See my edit. You should never be relying on the actual screen resolution for layout purposes. Figure out the dimensions that your parent layout actually takes when laid out, and position from there. The extra space could be the status bar or some other random Samsung addition. – Kevin Coppock May 25 '15 at 19:20
  • But dont I have to wait several frames before this can happen? I parse my UI dimensions from a JSON and position them based on % of screen height/width. So I do all the positioning in onCreate(). Does this mean I need to defer creation to onGlobalLayout instead? – Aggressor May 25 '15 at 19:21
  • Yes, if you're positioning relative to parent dimensions, then you'd need to defer all of that to `onGlobalLayout()` (since you don't actually know the available space until after the parent has been measured and laid out). This will occur before any frames are drawn, so you don't have to worry about seeing your UI jump around on you. – Kevin Coppock May 25 '15 at 19:25
  • 1
    Thanks this gives me some good ideas. Im going to create a reference Layout when the app is launched, and query its dimensions instead and use that with my onCreate(). Its a little hacky but your suggestion was bang on! Thank you! – Aggressor May 25 '15 at 19:27
  • Ok the problem seems to be rooted in the buttons creation. The height and width params were what I thought (after waiting for global layout, was still 1920 x 1080 in immersion mode). Its the button that was not respecting its creation. If I set the button to minimum height 108 and maximum height 108 it was still get re-sized! The button height keeps coming out to 136. – Aggressor May 25 '15 at 21:36
  • 1
    Setting adjustsViewBounds(true) was the culprit. But thank you, your suggestion lead to finding the true error – Aggressor May 25 '15 at 21:39
0

My buttons height was not having its view bounds adjusted and as such had the wrong height. Setting setAdjustViewBounds(true) fixed the issue.

The reason it only 'appeared' to happen on some phones and not others is the down and upsampling. If the density of the asset was such that it could fit inside the button, then it would look normal. But on the Samsung 3 (in this specific case) the drawable asset was coming in at a size of 136 x 136 and the button was not able to resize it to be smaller. When I set the adjustsBounds to true, it was allowed to shrink it to the right size.

Aggressor
  • 13,323
  • 24
  • 103
  • 182