vivo Internet Client Team - Xu Jie

The increasing number of models has brought a lot of adaptation work to developers. Whether the code can be unified, whether the apk can be unified, how to select materials, how to display styles, etc. are all problems that plague developers. This solution is to introduce the collinear solution of different models to dispel developers' doubts.

1. Challenges posed by increasingly diverse models

1.1 Background

Technology is advancing, and people's requirements for beauty are gradually increasing, so there are all kinds of models on the market now.

(1) For example, the vivo X60 mobile phone adopts a thin curved screen design, which is a candy bar model.

图片

(2) For example, vivo high-end mobile phones with folding screens provide a better visual experience and belong to folding screen models.

图片

(3) For example, vivo pad, with excellent operating feel and advanced texture, is a tablet model.

图片

1.2 Our challenges

Before that, we mainly served candy bar phones. Our development only needs to adapt to this mainstream candy bar machine. Our UI mainly designs the renderings of this candy bar phone. Our products and operations are mainly for this kind of candy bar. model to select the material.

图片

But with the emergence of this variety of models, the problem arises :

(1) The adaptation cost of developers is high. Is it necessary to make a separate application for adaptation for each model?

(2) UI designers have to do more renderings. Is it necessary to design a set of renderings for each model?

(3) The materials that need to be selected for products and operations are more restricted. Will this material be normal on a machine? Does it not work on other machines?

Why do I say this? Let's introduce it from the perspective of developers and explain the problems we face.

2. The dilemma of developers

2.1 The cost of adapting all models is too high

The increasingly rich model adaptation makes us android developers exhausted. Although we can adapt as required, the cost of adapting to large-screen models is still relatively high, because these models are different from traditional candy bar phones in terms of width and height ratio. (9:16). Therefore, some applications simply leave blank on both sides, and the content area is displayed in the center of the screen. Of course, this effect is very poor.

Case 1: A certain video APP page has not been adapted on the pad. The effect after opening is as follows, with a lot of blank space on both sides, which is an inoperable area.

图片

Case 2: For a news APP, the adaptation effect on the pad is as follows. Within the visible range, the information flow displays less content, and the pictures are stretched and blurred.

图片

2.2 Where is the high cost of adapting all models

The above case is only one of the superficial problems. As a developer, there are many factors to consider. First of all, you must think about the characteristics of these models:

图片

Then there is the problem that needs to be solved:

图片

3. A journey to find a full-model adaptation solution

3.1 Scheme discussion and determination

Page stretching and left and right blanks are phenomena, which are also the direct experience of users. So that's where we're going to improve, so now there's direction, around "how to show more information in the visible area." This is not a simple rearrangement and combination of layouts, because the solution is definitely not something that can be implemented only if the development decides how to implement it. An apk carries functions to users and involves the involvement of multiple roles. Product managers need to sort out requirements, operators need to configure materials, release apk, tests need to be tested, etc., so the final plan is not determined by one party, but a coordinated and unified result.

Since the plan is to be discussed, there must be a basis, and the process of discussion, review, and finalization is omitted here.

Let's first take a look at the external outlines of the candy bar, folding screen, and pad to know how the page looks.

图片

3.2 Schematic diagram of the implementation of the scheme

The content to be displayed by each application is inconsistent, but the principle is the same. Here, the principle is introduced based on the following styles. The principle is also relatively simple, show as much content as possible, and avoid large blank areas.

The following does not introduce the adaptation of the split-column mode, because the split-column mode may also be turned off by the user and eventually become a full-screen mode. Therefore, you can choose to only adapt to the full-screen mode, which has a lower cost of adaptation. Of course, this should also be determined according to the situation of your own module, such as WeChat, which is more suitable for the column mode of the left and right screens.

3.2.1 Skeleton diagram of the adaptation scheme of the candy bar model

The candy bar model, the current mainstream model, basically has an aspect ratio of 9:16, which can display more content to the maximum extent, such as the pictures of module 1, module 2, and module 3 in the figure below.

图片

3.2.2 Skeleton diagram of folding screen model adaptation scheme

Folding screen models, the screen can be rotated, but the aspect ratio is basically 1:1, and the height is basically the same as that of the candy bar machine, which can reach 2000px pixels, so in the vertical direction, it can also display more content to the maximum extent, such as the following Picture of module 1, module 2, and module 3 in the figure.

图片

3.2.3 Skeleton diagram of PAD model adaptation scheme

Pad tablet, the screen can be rotated, and the aspect ratio after rotation is large, the aspect ratio is 5 : 8 in portrait orientation, and the aspect ratio is 8 : 5 in landscape orientation.

When the pad is vertical, in fact, the height pixels are enough to display a lot of content, such as the pictures of module 1, module 2, and module 3 in the following figure;

However, when the pad is horizontal, there is no way to display more content (there is a solution, I will talk about it at the end), only the pictures of module 1 and module 2 in the figure below.

图片

3.3 Specifications for the implementation of the scheme

3.3.1 One set of codes is suitable for all models

To determine whether an apk can be adapted to all models, the first thing to solve is to meet the characteristics of different models. For example, a candy bar phone can only be displayed vertically, and the folding screen and pad support horizontal and vertical screen rotation.

Described as follows:

(1) Demand

  • Straight screen: Forced to fix vertical screen;
  • Folding screen: the external screen is fixed in vertical screen, and the internal screen (large screen) supports horizontal and vertical screen switching;
  • PAD side: support horizontal and vertical screen switching;

We need to implement the above requirements through a set of codes at the above three ends.

(2) Switch between horizontal and vertical screens

There are the following 2 methods:

  • way 1)

By setting in AndroidManifest.xml: android:screenOrientation property

a) android:screenOrientation="portrait" forced vertical screen;

b) android:screenOrientation="landscape" forced landscape;

c) The default value of android:screenOrientation="unspecified" can switch between horizontal and vertical screens;

way 2)

Set in code: activity.setRequestedOrientation( * *);

a) setRequestedOrientation(ActivityInfo.SCREEN\_ORIENTATION\_PORTRAIT); Set vertical screen;

b)setRequestedOrientation(ActivityInfo.SCREEN\_ORIENTATION\_LANDSCAPE); Set horizontal screen;

c)setRequestedOrientation(ActivityInfo.SCREEN\_ORIENTATION\_UNSPECIFIED); Can switch between horizontal and vertical screens;

(3) Different devices support different horizontal and vertical screen modes

1) Candy bar screen:

Because it is a forced vertical screen, you can set android:screenOrientation="portrait" for the Activity in AndroidManifest.xml.

2) Folding screen:

The external screen and the candy bar screen are consistent and will not be discussed for the time being. However, the internal screen (large screen) must support horizontal and vertical screen switching. If it is a set of code, obviously it cannot be achieved through the AndroidManifest file. In fact, the system framework has already helped us realize the logic of horizontal and vertical screens corresponding to the internal screen. To sum up, the folding screen can be consistent with the straight screen. Set android:screenOrientation="portrait" for the Activity in AndroidManifest.xml. If you switch to the internal screen, the system automatically ignores the screenOrientation attribute value and forcibly supports horizontal and vertical screen switching.

3) PAD side:

Of course, not all systems corresponding to the project will automatically help us ignore the value of the screenOrientation attribute, so we need to implement it ourselves.

By setting setRequestedOrientation(ActivityInfo.SCREEN\_ORIENTATION\_UNSPECIFIED) in the base class of Activity, we found that we can indeed switch the current page horizontally and vertically. But I encountered a problem when starting the activity. When we start an acitivity B interface from the horizontal screen state A interface, we find that the B interface is first in the vertical screen, and then switches to the horizontal screen (as shown in Figure 1). After many attempts, it is still the same, and the visible switching process obviously cannot meet our needs. This shows that the technical direction of dynamically adjusting the horizontal and vertical screens through java code is not feasible. To sum up, the same code cannot meet the mutually exclusive requirements of the PAD side and the candy bar screen.

图片

Is there any other way. Don't forget, the whole process of our Android packaging is done through gradle. Can we create different packages for different devices through the thinking of faceted programming?

The scheme is confirmed, and the technical verification is carried out here.

An important part of gradle compilation is to merge the AndroidManifest files in the dependent aar and the local module, and finally output a temporary complete manifest file, which is stored in the /app/build/intermediates/merged_manifest/ *Release/ path.

Therefore, we can dynamically modify the value information of the android:screenOrientation field in the temporary file after the AndroidManifest file merge is completed, and then save it back after the modification is completed. In this way, an apk file can be typed separately for the pad side.

The core code is as follows:

 //pad支持横竖屏
def processManifestTask = project.tasks.getByName("processDefaultNewSignPadReleaseManifest");
if (processManifestTask != null) {
    processManifestTask.doLast { pmt ->
        def manifestPath = pmt.getMultiApkManifestOutputDirectory().get().toString() + "/AndroidManifest.xml"
        if (new File(manifestPath).exists()) {
            String manifest = file(manifestPath).getText()
            manifest = manifest.replaceAll("android:screenOrientation=\"portrait\"", "android:screenOrientation=\"unspecified\"");
            file(manifestPath).write(manifest)
            println(" =============================================================== manifestPath: " + manifestPath)
        }
    }
}

(4) Number of apks

So far, the java code is completely the same, and there is no distinction. The key is whether the framework provides the ability to ignore screenOrientation. If it is provided, we only need to output an apk to adapt to all models.

Without this ability, we need to use gradle to type an additional apk to meet the requirements of rotation.

3.3.2 One set of materials for all models

1. Equally enlarged material

According to the requirements of the above landing plan, for the pictures of module 2, the display effect is different, as shown in the following figure:

(1) On the candy bar phone, picture 1 of module 2 is on the top, pictures 2 and 3 are distributed in the lower left and lower right corners

(2) On the folding screen or pad, picture 1 of module 2 is on the left, and pictures 2 and 3 are distributed on the right

(3) The picture of module 2 on the folding screen and the pad has been adjusted in style compared to the candy bar phone, and the upper and lower styles have been changed to left and right. The picture is also enlarged accordingly to ensure that the entire width of the screen can be filled in the horizontal direction.

图片

(4) In order to visualize the effect after processing, just look at the following schematic diagram.

图片

图片

2. The height is unchanged, and the material is cut

For the pictures of module 3, you can review the display style in 3.2, the requirements are

(1) On the candy bar phone, the height of picture 1 in module 3 is 300px here.

(2) On the folding screen or pad, the height of picture 1 of module 3 is also 300px, but the content cannot be reduced.

(3) The solution is to provide an original large image, if the size is 2400px*300px, and crop it left and right on the candy bar phone, as shown in the figure below. Display directly on the folding screen and pad. The cutting step is performed on the server side, because it is time-consuming for the client to cut.

图片

(4) In order to visualize the effect after processing, just look at the following schematic diagram.

图片

图片

3.3.4 Sensorless refresh

Non-sensing refresh is mainly reflected in the switching between internal and external screens of the folding screen, and the horizontal and vertical screen rotation of the pad. How to ensure that the page will not flash when switching and rotating?

(1) It is necessary to prepare the data source in advance to ensure that when the page changes, notify immediately.

(2) It is best to use recyclerview for our page list, because recyclerview supports partial refresh.

(3) The data source drives the UI. Never judge the model at the UI level to perform dynamic UI calculations. The page will flicker and the experience will be bad.

图片

3.4 The actual implementation of the plan

The above describes the adaptation specifications of different models. After there is no doubt about this, let’s see how to implement it directly through the case.

图片

As shown in the figure above, the purchase page can be roughly divided into a category navigation bar area and a content area, where the content area is composed of multiple floors.

3.4.1 How the UI is designed

图片

As shown in the figure, it can be intuitively felt that when the display area of the device increases, the page makes full use of the space to display more product information, from the candy bar phone to the inner screen of the folding screen to the horizontal screen of the Pad.

3.4.2 How to distinguish different devices

Through the previous brief introduction, I have an understanding of the overall layout of the purchase page and the UI display on different devices. Let's take a look at how to implement a set of code adaptation on multiple devices.

The first step is how to distinguish different devices.

Before distinguishing between different devices, let's take a look at what information can be obtained from the device?

1) Resolution

2) Model

3) The horizontal and vertical status of the current screen

Conclusion first:

  • Candy bars: differentiated by resolution
  • Folding screen: distinguish by model and internal and external screen status
  • Pad: distinguished by the model and the horizontal and vertical status of the current screen

So here is a tool based on these characteristics.

Differentiate between different devices.
 /**
 * @function 判断当前手机的屏幕是处于哪个屏幕类型:目前三个屏幕范围:分别为 <= 528dp、528 ~ 696dp、> 696dp,对应的分别是正常直板手机、折叠屏手机内屏和Pad竖屏、和Pad横屏
 */
public class ScreenTypeUtil {
 
    public static final int NORMAL_SCREEN_MAX_WIDTH_RESOLUTION = 1584; // 正常直板手机:屏幕最大宽度分辨率;Pad的分辨率(1600*2560), 1584 = 528 * 3, 528dp是UI在精选页标注的直板手机范围
    public static final int MIDDLE_SCREEN_MAX_WIDTH_RESOLUTION = 2088; // 折叠屏手机:屏幕最大宽度分辨率(1916*1964, 旋转:1808*2072),2088 = 696 * 3, 2088dp是UI在精选页标注的折叠屏展开范围
    public static final int LARGE_SCREEN_MAX_WIDTH_RESOLUTION = 2560; // 大屏幕设备:屏幕宽度暂定为 Pad的高度
 
    public static final int NORMAL_SCREEN = 0; // 正常直版手机屏幕
    public static final int MIDDLE_SCREEN = 1; // 折叠屏手机内屏展开、Pad竖屏
    public static final int LARGE_SCREEN = 2;  // Pad横屏
 
    public static int getScreenType() {
        Configuration configuration = BaseApplication.getApplication().getResources().getConfiguration();
        return getScreenType(configuration);
    }
 
    // 注意这里的newConfig 在Activity、Fragment、View 中的onConfigurationChanged中获得的newConfig传入,如果获得不了该值,可以使用getScreenType()方法
    public static int getScreenType(@NonNull Configuration newConfig) {
        // Pad 通过机型标志位及当前处于横竖屏状态 来判断当前屏幕类型
        if (SystemInfoUtils.isPadDevice()) {
            return newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ? LARGE_SCREEN : MIDDLE_SCREEN;
        }
        // Fold折叠屏 通过机型标志及内外屏状态 来判断当前屏幕类型
        if (SystemInfoUtils.isFoldableDevice()) {
            return SystemInfoUtils.isInnerScreen(newConfig) ? MIDDLE_SCREEN : NORMAL_SCREEN;
        }
        // 普通手机 通过分辨率判断
        return AppInfoUtils.getScreenWidth() <= NORMAL_SCREEN_MAX_WIDTH_RESOLUTION ? NORMAL_SCREEN : (AppInfoUtils.getScreenWidth() <= MIDDLE_SCREEN_MAX_WIDTH_RESOLUTION ? MIDDLE_SCREEN : LARGE_SCREEN);
    }
}

3.4.3 Implementation plan

(1) The idea of data source driving UI change

For a candy bar phone, there is only one state of the purchase page, which is displayed in a vertical screen.

For the folding screen, the folding screen can be switched from the inner screen to the outer screen, which involves the switching of two different states.

For Pad, Pad supports horizontal and vertical screen switching, so it is also two different state switching.

When the screen type, horizontal and vertical screen switching, internal and external screen switching, Activity\Fragment\View will call the onConfigurationChanged method, so the data source switching can be placed here for candy bar phones, folding screens and pads.

No matter what kind of device it is, there are at most two different states. Therefore, two sets of data sources can be prepared here: one is Normal and the other is Width. For candybar phones: because there is only one vertical screen state, so Only one set of data sources is needed; for the folding screen: Normal stores the data source of the external screen of the folding screen, and Width stores the data source of the inner screen of the folding screen; for the Pad: Normal stores the vertical screen state of the Pad The data source, Width stores the data source of the Pad landscape state.

(2) Content area

The content area on the right is a Fragment, which contains a RecyclerView.

each sub-floor
 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_classify_horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
 
    <xxx.widget.HeaderAndFooterRecyclerView
        android:id="@+id/shop_product_multi_rv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
 
</LinearLayout>

Each floor is also a separate RecyclerView. Taking floor 4 as an example, each row of products on floor 4 is a RecyclerView, and each RecyclerView uses GridLayoutManager to control the number of columns displayed in the layout.

(3) Data source

Take the folding screen as an example: for the data of each sub-floor, when parsing, first prepare two sets of data sources: one is Normal and the other is Width.

After requesting network data back, after parsing the data, two sets of data sources are stored. These two sets of data sources should be assembled according to the rules of UI design. For example, take floor 4 of the folding screen as an example:

Folding screen - external screen - floor 4: Display 2 product information in one row.

Folding screen-inner screen-floor 4: Display 3 product information in one row.

Note: The numbers 2 and 3 here are set at the beginning of the UI design. Each row of products is a RecyclerView, and the GridLayoutManager is used to control the number of columns. Therefore, the numbers 2 and 3 are also the column values passed into the GridLayoutManager. Here Be consistent.

Data source analysis of sub-floor
 //这里的normalProductMultiClassifyUiBeanList集合中存放了2个商品信息
for (ProductMultiClassifyUiBean productMultiClassifyUiBean : normalProductMultiClassifyUiBeanList) {
    productMultiClassifyUiBean.setFirstFloor(isFirstFloor);
    shopListDataWrapper.addNormalBaseUiBeans(productMultiClassifyUiBean);
}
//这里的normalProductMultiClassifyUiBeanList集合中存放了3个商品信息
for (ProductMultiClassifyUiBean productMultiClassifyUiBean : widthProductMultiClassifyUiBeanList) {
    productMultiClassifyUiBean.setFirstFloor(isFirstFloor);
    shopListDataWrapper.addWidthBaseUiBeans(productMultiClassifyUiBean);
}

Therefore, the required data source part has been obtained here

(4) Screen type switching

Taking the folding screen as an example, the external screen of the folding screen is switched to the internal screen. At this time, the Fragment will go to the onConfigurationChanged method.

Screen Type Switch - Data Source Switch - Update RecyclerView.
 public void onConfigurationChanged(@NonNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //1、 首先进行内容区域中的RecyclerViewAdapter、数据源判空
    if (mRecyclerViewAdapter == null || mPageBeanAll == null) {
        return;
    }
    //2、判断当前的屏幕类型,注意:这个地方是调用3提供的方法:ScreenTypeUtil.getScreenType(newConfig)
    // 直板手机、折叠屏外屏
    if (ScreenTypeUtil.NORMAL_SCREEN == ScreenTypeUtil.getScreenType(newConfig)) {
        mPageBeanAll.setBaseUiBeans(mPageBeanAll.getNormalBaseUiBeans());
    } else if (ScreenTypeUtil.MIDDLE_SCREEN == ScreenTypeUtil.getScreenType(newConfig)) {
        if (SystemInfoUtils.isPadDevice()) {
            // Pad的竖屏
            mPageBeanAll.setBaseUiBeans(mPageBeanAll.getNormalBaseUiBeans());
        } else {
            // 折叠屏的内屏
            mPageBeanAll.setBaseUiBeans(mPageBeanAll.getWidthBaseUiBeans());
        }
    } else {
        // Pad的横屏、大分辨率屏幕
        mPageBeanAll.setBaseUiBeans(mPageBeanAll.getWidthBaseUiBeans());
    }
    //获取当前屏幕类型的最新数据源
    mRecyclerViewAdapter.setDataSource(mPageBeanAll.getBaseUiBeans());
    //数据源驱动楼层UI改变
    mRecyclerViewAdapter.notifyDataSetChanged();
}

Through the onConfigurationChanged method, you can see how the data source is switched according to different screen types. When the data source is switched, the UI will be changed through the notifyDataSetChanged method.

Fourth, the creation of the road to simplicity

The road is simple, follow the norms and principles, you can think of how to adapt to multiple models, don't get caught up in the details.

Using this as a guiding ideology, many other adaptations can be made. The following lists some examples, but do not explain the implementation.

1. Enlarge the text display area

As shown in the figure below, the length of the title changes when the display width of the entire container becomes wider, ensuring that the length of the content can be changed adaptively.

图片

2. Compatibility of bullet frame styles

As shown in the figure below, the blue area is the height of the keyboard. When the screen is rotated, the height of the keyboard also changes. At this time, the original displayed content may be blocked. The processing method here is: let the content area Swipe up and down.

图片

3. Processing of camera position

As shown in the figure below, after the screen is rotated, the camera can appear in the lower right corner. If the page is not set at this time, there may be a problem that the content area cannot occupy the entire screen area, and the experience is relatively poor. The processing method here is: Set the page immersion, the camera can reasonably cover part of the content.

图片

5. Are we out of trouble?

5.1 Solving the original problem

Through the previous introduction, we know that the team of vivo's official website has adopted a full-screen display solution for large screens such as folding screens and pads. At the beginning, the problems we encountered were also solved:

(1) The adaptation cost of developers is high. Is it necessary to make a separate application for adaptation for each model?

Answer: According to the design scheme of full-screen mode, the folding screen and pad are also large-sized machines. The developer judges the resolution and size of the model and selects a corresponding layout for display. Only one application can be used to display it. Get it done.

(2) UI designers have to do more renderings. Is it necessary to design a set of renderings for each model?

Answer: Develop a set of specifications. When the size is larger than a certain size, other styles will be displayed. All information content will follow this specification, and there will be no design confusion.

(3) The materials that need to be selected for products and operations are more restricted. Will this material be normal on a machine? Does it not work on other machines?

Answer: Keeping the same, using a set of materials and adapting to different models can already be implemented, so you don't need to worry about the inconsistency of displaying on different machines.

5.2 What else can we do

5.2.1 Our advantages

The folding screen and pad have been used in the market for a long time, and various manufacturers have adopted different adaptation solutions to improve the interactive experience, but there are often the following problems:

1. Different installation packages are used for different models.

This solution will actually increase the maintenance cost, and the later development will be based on multiple installation packages, which is more time-consuming.

2. Adapted to different models, but the style is not ideal in some scenarios.

For example, some APPs have been adapted to the columns, but they have not been adapted to the full screen, and the effect is relatively poor. The input-output ratio may also be considered here.

3. The current adaptation guidance document is less instructive for developers.

Various adaptation guidance documents are still relatively official. For developers, it is still impossible to identify problems in advance, and problems must be solved actually. https://developer.huawei.com/consumer/cn/doc/ 90101

Based on this, our advantages are as follows:

1. We only have one installation package.

We are an installation package suitable for all models. Although the style of the APP display of each model is different, for developers, it is to add a style, and the thinking is relatively clear.

2. Full scene adaptation.

The vertical, horizontal and vertical screen switching of different models has been perfectly adapted, and one set of materials suitable for all models is also a feature of us.

3. Provide tailored solutions.

This solution is based on the problems encountered in actual development, which can help developers solve problems that may be encountered in practice, and has better reference.

5.2.2 What else can we improve

Looking back on the plan, what we have done here is to use the full-screen mode to adapt to different models, and more suitable for e-commerce apps such as JD.com, Taobao, and malls. In fact, some non-apps now use the form of columns Adaptation is also a way of interacting with users. This solution does not mention columns. After the subsequent columns are implemented, this part will be supplemented.


vivo互联网技术
3.3k 声望10.2k 粉丝