Search code examples
javaandroidxmlandroid-layout

Android app chooses dimesion file for wrong display type


I have a simple XML layout file in Android with just one button:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Here is the corresponding Java file of the fragment:

public class FR_Test extends Fragment {


    public FR_Test() {
        // Required empty public constructor
    }



    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


    }
    private FragmentTestBinding binding;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        binding = FragmentTestBinding.inflate(inflater, container, false);


        int desiredHeightDP = getResources().getDimensionPixelSize(R.dimen.height_line_graph);
        Log.e("DR_Stats", "desiredHeightDP: " + desiredHeightDP);
        float density = getResources().getDisplayMetrics().density;
        Log.e("DR_Stats", "density: " + density);
        int desiredHeightPixels = (int) (desiredHeightDP * density);
        Log.e("DR_Stats", "desiredHeightPixels: " + desiredHeightPixels);

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        int screenWidthDp = (int) (displayMetrics.widthPixels / displayMetrics.density);
        int screenHeightDp = (int) (displayMetrics.heightPixels / displayMetrics.density);

        Log.e("DR_Stats", "screenWidthDp: " + screenWidthDp);
        Log.e("DR_Stats", "screenHeightDp: " + screenHeightDp);

        binding.button.setHeight(desiredHeightPixels);



        return binding.getRoot();
    }
}

I want to set the height of the button depending on the used display size. For this purpose, I defined - next to the standard value folder - the value folder "values-sw600dp" with the dimension file

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="height_line_graph">700dp</dimen>

</resources>"

In the default value folder the dimesion (dimens.xml) file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="height_line_graph">10dp</dimen>
</resources>

When using Pixel 3 as an emulator in Android Studio, which has the dp resolution 393 x 786, in landscape mode, I get an output that I don't understand at all:

2023-12-03 11:51:01.102  7448-7448  DR_Stats                com.example.drinkserver              E  desiredHeightDP: 28
2023-12-03 11:51:01.102  7448-7448  DR_Stats                com.example.drinkserver              E  density: 2.75
2023-12-03 11:51:01.102  7448-7448  DR_Stats                com.example.drinkserver              E  desiredHeightPixels: 77
2023-12-03 11:51:01.102  7448-7448  DR_Stats                com.example.drinkserver              E  screenWidthDp: 737
2023-12-03 11:51:01.102  7448-7448  DR_Stats                com.example.drinkserver              E  screenHeightDp: 392 

In particular I have 3 question:

  1. Why is the desiredHeightDP: 28. I just have 2 dimens.xml files. On the one for smaller screns it should be 10dp and in the other one it should be 700dp. Where does the 28 come from.
  2. The Pixcel 3 has a width of 786 dp in landscape mode and heigth 393dp according to the properties in Android Studio Virutal Device manageer. Why is the output of the width slightly different with 737dp and the height with 392 dp?
  3. Even with the sligthly reduced width of 737dp, the app should choose values from the dimens.xml file which is in the "values-sw600dp" folder, as the smallest width is over 600dp. But it does not do that.

Can anyone help me on these 3 questions? The overall goal is to change the size of certain elements in a layout depending on the screen size. I was recommended to use the approach of defining different folders like "values-sw600dp" for different smallest widths


Solution

  • Ignoring question 2 (as I do not use emulators all that much and I so rarely care about screen size versus window size nowadays...).

    Why is the desiredHeightDP: 28. I just have 2 dimens.xml files. On the one for smaller screns it should be 10dp and in the other one it should be 700dp. Where does the 28 come from.

    You are calling getDimensionPixelSize(). That returns a value in pixels, not dp. Your density is 2.75, so 10dp will be about 28 pixels.

    Even with the sligthly reduced width of 737dp, the app should choose values from the dimens.xml file which is in the "values-sw600dp" folder, as the smallest width is over 600dp. But it does not do that.

    The smallest width is the smallest X/Y dimension. For a phone in portrait, smallest width is the current width. For a phone in landscape, the smallest width is the current height. As a result, smallest width is independent of orientation. And, in your case, the smallest width is 393dp.

    In this very app everything will be in Landscape mode. So I am not sure whether I should use values-sw600dp or values-w600dp?

    Off the cuff, I would use values-w600dp, but, again, it depends on the specific designs.