Original address: tangpj.com/2018/09/29/…

Jane address book: www.jianshu.com/p/6824ae172…

Calces automatically implements componentized module building for Android

preface

Screen adaptation has always been a hot topic in mobile development, but the adaptation solution often conflicts with the design draft provided by UI during actual development. This paper is mainly based on the officially recommended configuration qualifier scheme (the optimal scheme for Android screen adaptation at present) to achieve a nearly perfect screen adaptation scheme.

Original statement: this article is an original article, without the consent of the blogger is strictly prohibited to reprint.

The author defines a perfect adaptation scheme as follows:

  1. Can be perfectly adapted to UI draft.
  2. After the adaptation is complete, there will be no blur on the HD device.
  3. Minimize intrusion into the project.

I’ll start with the basics of screen adaptation and show you an optimal screen adaptation solution.

Here is a library of Android build AIDS I’ve written, where the Screen plugin is the key to automatic Screen adaptation. In case you miss this plugin, I recommend it here in advance.

The Screen plug-in provides two main functions:

  1. Configure the design draft density and the value of Smallest Width to fit the screen to automatically generate the corresponding resource file
  2. Provides the highest resolution bitmap required and automatically scales bitmap resources according to the desired density.

Github: If you find this tool helpful, you can click on Star, which is what keeps me going 💪

To learn more about how this plugin automatically helps you with screen adaptation, read on.

Demo address for this article: Demo. ScreenAdaptation in the project is the Demo of this article.

Screen adaptation overview

concept

  • Screen size: Screen size is the physical size of the screen and is measured by measuring the diagonal of the screen.

  • Screen density: The number of pixels in the physical area of the screen, often called DPI (pixels per inch). The higher the density, the better the reality.

  • Resolution: The total number of physical pixels on the screen. When performing screen adaptation, do not directly through resolution adaptation, should be based on screen size and screen density adaptation

  • Dp: Dp is an Android specific virtual pixel unit, independent of physical parameters. 1DP is equal to one physical pixel on a 160 dpi screen, and at run time any scaling of the DP units is handled transparently as needed, depending on the actual density of the screen in use. Converting dp units to screen pixels is simple: px = dp * (dpi / 160). On a 240 dpi screen, 1 dp equals 1.5 physical pixels.

How to support multiple screens

The foundation of Android’s support for multiple screens is its ability to render the layout and bitmap of an application in an appropriate manner for the configuration of the current screen, which is supported at the system level. We can better handle the adaptation of different screen configurations in the following ways:

  1. By default, Android will resize the layout of the app to fit the current device screen, and in most cases the system will provide the support we need. But sometimes different layouts need to be designed for different screen resolutions to achieve better realism.
  2. We can use the configuration qualifier of the density resource to provide images of different pixels to match different screen densities.

For the first point, it is difficult to achieve in practical work. This is because UI usually only provides one set of designs and does not provide adaptations for different screen resolutions. However, we have no way to control what resolution screen our App will eventually run on. In order to achieve display effects on different screens, we can provide bitmap resources of different densities and the Smallest Width scheme to achieve screen adaptation.

What is the Smallest Width adaptation

The Smallest Width is specified by the Smallest size of the available screen area. Specifically, the device’s smallestWidth is the minimum size of the available screen height and width.

For example, if the layout requires that the minimum size of the screen area always be at least 600dp, you can use this qualifier to create the layout resource res/ layout-SW600dp /. The system uses these resources only if the minimum size of the available screen is at least 600DP, regardless of whether 600DP represents an edge that the user considers to be high or wide. SmallestWidth is a fixed screen size feature of the device; The smallestWidth of the device does not change with screen orientation.

So we can provide different resources based on the SW value of the screen that needs to be adapted to achieve screen adaptation.

Some basic concepts of UI design and screen adaptation

I think a lot of screen adaptation tutorials miss an important point: they don’t explain the relationship between screen adaptation and UI design!

During actual development, UI designers usually provide a set of UI sketches and rulers, and engineers develop the UI through this set of rulers. UI If we’re going to do a good job of screen adaptation on Android, it’s important to understand that UI scripts serve as an anchor point in our interface development. To adapt to other screens, you must calculate dimens resources for other screens based on this benchmark.

One example: for example, many UI designers use the size of the iPhone6 as a standard for their designs and rulers, and the iPhone6 screen is 375px wide, so this 375px design is our baseline for screen fit.

If there is a device whose SW is equal to 375DP, then the corresponding relationship between the device and the design is 1dp = 1px, then we do not need to do any adaptation, and directly convert the scale value of the design in px units into dp units in a 1:1 ratio.

Here, we can draw a conclusion is: screen adaptation needs to UI draft as the benchmark to develop the appropriate adaptation scheme!

One problem is that every UI designer’s preferences are different, and the scale of the design provided is not fixed. Also, Android’s screens are very fragmented, and the value of sw we need to fit the screen is very variable. Therefore, if the corresponding Dimens value needs to be calculated manually each time, it will be very time-consuming and tedious. There are tools available online to quickly generate dimens values for sw, but these tools have two disadvantages:

  1. There is no way to convert from a UI design draft, so it may not be 100% accurate

  2. A large number of useless Dimens are generated. In fact, if we carefully observe the design draft, we will find that in fact, each design draft commonly used PX values are fixed about a dozen. For example, using the same 375px design as the baseline, the tool will generate dp values between 1px and 375px, so there will be a lot of useless Dimens. This will only increase the size of the installation package.

These two disadvantages can be solved by using the author’s calces.screen plug-in, which will be described in the following paragraphs.

Fast implementation of Smalles Widths adaptation using Calces. screen

Comparison before and after adaptation

Still take iPhone6 design draft as an example, if there is such a design draft below, if there is no adaptation, the display effect on different devices is compared as follows:

The first phone is the one with sw = 375dp mentioned above. We can see that the display effect is not satisfactory on other phones with SW values. On both sw = 411DP and SW = 900DP devices, there is a lot of white space, and on SW = 360DP devices, there is out of screen range. The goal of our adaptation is to achieve the same display on all devices as the design (sw = 375DP).

Using the Calces.Screen plugin, you can see the following:

One thing to note here is that you can see that the adaptation in the third device is still a bit of a problem, leaving about 1DP of white edge. This is the simulator for Pixel 2 XL. You can see that the measured SW value should be 411dp, but after the author’s actual measurement, it is found that the SW value should be 412dp. You can create a control with a width of 411dp in the layout editor. You can see that the pixel 2 XL device also has a white edge of about 1dp. So this 1dp error should be device-specific. Here is the dimens file with sw = 411dp generated by calces.screen for reference.

<resources>
  <! -- sw411dp -->
  <dimen name='px_48'>53dp</dimen>
  <dimen name='px_75'>83dp</dimen>
  <dimen name='px_100'>110dp</dimen>
  <dimen name='px_125'>137dp</dimen>
  <dimen name='px_150'>165dp</dimen>
  <dimen name='px_200'>220dp</dimen>
  <dimen name='px_250'>274dp</dimen>
  <dimen name='px_300'>329dp</dimen>
  <dimen name='px_375'>411dp</dimen>
  <dimen name='text_px_28'>31sp</dimen>
  <dimen name='text_px_32'>36sp</dimen>
  <dimen name='text_px_40'>44sp</dimen>
</resources>
Copy the code

When sw = 411DP, the actual value of PX_375 is 411dp, so this is in line with our expected transformation results.

How to introduce Calces.Screen

First, we need to introduce the Calces plugin, which is simple:

Add code to your project’s build.gradle:

// If Gradle version is higher than 2.1 (recommended)
plugins {
    id "calces.screen" version "1.2.3"
}

// If the Gradle version is earlier than 2.1 (2.1 + is compatible with this method)
buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.com.tangpj.tools:calces:1.2.3"}}Copy the code

Add code to modules’ build.gradle:

apply plugin: "calces.appconfig"
Copy the code

Use calces.screen to fit the screen

First, we need to create the dimens. XML file in the res/values/ folder, and then write the required dimensions according to the ruler of the design to this file. Such as:

<?xml version="1.0" encoding="utf-8"? >
<resources>
    <! --design 375px-->
    <dimen name="px_48">48dp</dimen>
    <dimen name="px_75">75dp</dimen>
    <dimen name="px_100">100dp</dimen>
    <dimen name="px_125">125dp</dimen>
    <dimen name="px_150">150dp</dimen>
    <dimen name="px_200">200dp</dimen>
    <dimen name="px_250">250dp</dimen>
    <dimen name="px_300">300dp</dimen>
    <dimen name="px_375">375dp</dimen>

    <! --text size-->
    <dimen name="text_px_28">28sp</dimen>
    <dimen name="text_px_32">32sp</dimen>
    <dimen name="text_px_40">40sp</dimen>
</resources>
Copy the code

This is our benchmark Dimens file.

For example, in the example above, we need 320dp, 411dp, 900dp, then we need to add the following code to the build. Gradle file:

screen{

    dimens{
        designPx 375
        smallesWidths 320.375.411.900
        scale BigDecimal.ROUND_UP
        auto true}}Copy the code

The mapping between the preceding configurations is as follows:

  • DesignPx: Sw size of the design (in px)

  • SmallesWidths: Screen SW size to be adapted (unit: DP)

  • Since The Android system can only handle integer dp values, we can use scale to configure the specific positive method. Here we take the Round provided by BigDecimal directly to implement. If not set, a value of type double dp is generated (the decimal place is actually discarded).

  • Auto: indicates whether to automatically generate dimens. If auto is true, the dimens file will be generated again for each build. If auto is not set or set to false, you can manually call the Gradle task to generate. Call the command: /gradlew dimensCovert you can also directly click on the Gradle task and execute it as shown below:

After the configuration is complete, re-build the following project to see the generated resource file, as shown in the figure below:

To ensure that the compilation time is not affected, you are advised to set auto to False and manually start the task to generate the adaptation resource file when necessary.

How do we determine what SW values we need to fit?

In addition to automatically generating SW, we also need to determine which SW values our App needs to support. The easiest way to do this is to decide which devices we want to support. The author’s suggestion here is that there are many devices in the market with the SW value of 360DP, so we must adapt 360DP devices. For other devices, we can make sure that we find a parameter called minimum width in the developer mode, which is the desired SW value. The details are as follows:

For example, the above is the SW value of the Nexus S. If we don’t specifically match the screen with sw = 384dp, then the system will default to look for adaptation resources less than 384dp (so 360dp is a relatively common adaptation value). Using the Calces.Screen adaptor is very simple when we have the test equipment. So what if we don’t know there’s no test equipment? (For example, there is user feedback that there is a big problem with the adaptation of a certain device)

Here’s a site to recommend: Device Metrics

This is Material Design’s device parameter search site, where users can simply find the size of the device (the previous method was overturned and slipped away).

Generally, screens with sw of 360dp and 480dp are common, so we have to generate these two sets of resources. If we need to support Pad, we need to adapt to screens with SW = 600dp or SW = 720dp, and then adapt to other screens with SW values according to the actual situation.

So far, we have completed the Android screen adaptation based on the SW solution, very simple!

But that’s not the end of the article. In addition to providing automatic adaptation of sw-based solutions, the plug-in also provides a killer feature: it automatically generates bitmap resources of the corresponding resolution based on the configuration. When it comes to phones with different screen densities, just provide a set of high definition bitmap resources, freeing both your hands and UI designers.

Calces.screen implements automatic bitmap scaling

Providing different bitmap resources for different densities of screens is Google’s official recommendation for screen adaptation. The benefit of this approach is that the App works best on screens of different densities, without having a senier-like display in HD, and keeps a relatively stable display in different densities. The following is the ratio of bitmap resource density:

Density qualifier Proportional relationship instructions
ldpi 0.75 Resources suitable for low density screens (~120dpi)
mdpi 1 Resources (baseline density) for medium density screens (~160dpi)
hdpi 1.5 Resources suitable for high-density screens (~240dpi)
xhdpi 2 Resources suitable for ultra-high density screens (~320dpi)
xxhdpi 3 Resources suitable for ultra high density screens (~480dpi)
xxxhdpi 4 Resources for super super super high density screens (~ 640Dpi). This qualifier applies only to the initiator icon.

But there’s a problem with this. Usually, bitmap resources are provided to us by the UI designer. I’ve talked to a lot of UI designers, and their solution is to cut a set of images with the highest resolution, scale them as needed, and provide them to the engineers.

In general, there’s nothing wrong with this except that it’s a little tedious. But what if there’s a situation where you need to support a lower density screen? This only allows the UI designer to scale another set of density bitmaps. What if some part of the bitmap is no longer used and needs to be deleted? The engineer needs to find the bitmaps of the other densities and delete them. And when you add new bitmaps to the project, you need to add them manually.

So in general, the UI provides image resources — and the engineers use the image resources by hand. The work is tedious and pointless, and the manual migration process is very error-prone (imagine what would happen if you copied a bitmap resource with a few densities missing?). . So Calces.Screen also provides bitmap management.

Calces.screen manages bitmaps

Before using Screen’s bitmap zoom feature, discuss with the designer/product what Screen density your App needs to support. Then the designer only needs to provide the bitmap of the density in the future. After that, we just need to configure modules in build.gradle, as follows:

screen{
    mipmap{
        designDensity "xxxhdpi" // For testing purposes, currently the mobile screen is only supported up to XXHDPI
        mipmapDensity 'xxhdpi'.'xhdpi'.'hdpi'.'mdpi'
        auto true}}Copy the code

If you don’t want to increase the compile time, you can set auto to false or leave it at all. Mipmap supports incremental compilation. Only bitmaps that do not exist in the folder will be scaled. If existing bitmaps exist, they will be skipped. The method for manually enabling bitmap scaling is the same as the preceding method. The task name is mipmapZoom. Here’s how it works:

Transformation before

After the transformation

Readers can click in to see the size of the converted picture, you can find that the converted picture is in line with the proportion we need. Interested readers can download the demo, delete the bitmap resources of other resolutions, and regenerate them through the mipmapZoom task.

With the mipmapZoom task, UI designers and engineers can greatly reduce their workload by just having to manage a set of bitmap files, which frees us from mechanized tasks.

Note: The current version does not support the function of deleting bitmaps, so when we need to delete some bitmaps, we need to delete all the automatically generated picture files and regenerate them. This function will be added in the later version.

conclusion

Screen adaptation has always been a big problem for mobile developers. Faced with a wide range of screen sizes and screen densities, we have been looking for a better adaptation scheme. Smallest Width is the simplest and most useful adaptation scheme in Android at present. It is supported by the system and won’t cause some strange problems due to the large difference between the screen resolution and the design draft during adaptation (the big screen will become paste, while the small screen will be too dense with pixels). This adaptation scheme is based on Smallest Width and provides multiple sets of bitmaps. Gradle plug-in is used to automatically process SW proportion calculation and file generation as well as automatic bitmap scaling to achieve a relatively better adaptation scheme.

Calces.screen was originally developed to simplify the workload of UI designers and Android engineers, and it has largely achieved that goal.

Ok, so much for the calces.Screen plugin, but again, if you find calces helpful, click star and encourage the author. If you have some better ideas, you can participate in this open source project. I will continue to maintain this project and try to reduce the burden on Android engineers and leave all the repetitive mechanical work to Gradle.

Github: If you find this tool helpful, you can click on Star, which is what keeps me going 💪