Search code examples
androidandroid-resourcesdimensionsandroid-screen-support

Is my method to set up android apps dimensions correct?


I use Android studio as a development environment and My method to set up android apps dimensions is like that:

1- I create a layout for hdpi devices basing on Nexus S offered by Android Studio.

2- I put all dimensions (using dp and sp units) in the values-hdpi folder.

3- I make 9 copies from this folder and rename them as the following:

  1. values-420dpi
  2. values-560dpi
  3. values-ldpi
  4. values-mdpi
  5. values-sw480dp
  6. values-sw600dp
  7. values-sw720dp
  8. values-xhdpi
  9. values-xxhdpi

4- After that, I open the layout file that I want to configure its dimensions and I select the following:

  1. Nexus 5X FOR 420dpi
  2. Nexus 6P FOR 560dpi
  3. 2.7" QVGA FOR ldpi
  4. 3.2" QVGA FOR mdpi
  5. 5.4" FWVGA FOR sw480dp
  6. Nexus 7 FOR sw600dp
  7. Nexus 9 FOR sw720dp
  8. Nexus 4 FOR xhdpi
  9. Nexus 5 FOR xxhdpi

5- I start changing the dimensions in each file until layout fit within the selected device.

This was my method to set up android apps dimensions, and I want to know if it is correct? and if it exists another way to do the same thing but easily?


Solution

  • You should use only one type of selector. For example, in your case:

    1. values-sw420dp
    2. values-sw480dp
    3. values-sw560dp
    4. values-sw600dp
    5. values-sw720dp

    should be enough (but obviously that depends on the requirements of the app and the device you want to fully support). Why are you using also density-based selectors (like values-mdpi)? As you probably know, dp and sp dimensions are density independent.

    It's worth adding that, if you design your layout carefully, you can reduce a lot the number of dimensions you need to explicitly declare. For example, you can use LinearLayouts with weighed children.

    In complex projects, when I want the app to scale with the screen size, I usually use a script to generate all the dimens files starting from a reference one, applying the desired multiplier to every screen class. The actual code depends a lot on your specific needs, but an example in Java could be:

    public class GenerateDimens {
    
        public static void main(String[] args) throws Exception {
            String resFolder = "app/src/main/res/";
            String dimensFileName = "dimens.xml";
            File source = new File(resFolder + "values-sw800dp", dimensFileName);
            File target = new File(resFolder + "values-sw0dp", dimensFileName);
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document document = builder.parse(source);
            NodeList nodeList = document.getElementsByTagName("dimen");
            Pattern pattern = Pattern.compile("(\\d+).*");
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node dimen = nodeList.item(i);
                String textContent = dimen.getTextContent();
                Matcher matcher = pattern.matcher(textContent);
                if (matcher.find()) {
                    String oldValue = matcher.group(1);
                    String newValue = String.valueOf((int) (Integer.parseInt(oldValue) / 1.33));
                    dimen.setTextContent(textContent.replaceFirst(oldValue, newValue));
                }
            }
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");
            document.setXmlStandalone(true);
            transformer.transform(new DOMSource(document), new StreamResult(target));
        }
    
    }