vivo official website APP full model UI adaptation solution

vivo official website APP full model UI adaptation solution

Author: Xu Jie, vivo Internet Client Team

The increasing number of new models brings 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 bother developers. This solution is to introduce the common line solution for different models to dispel the doubts of developers.

1. Challenges Brought by the Increasing Diversity of Aircraft Models

1.1 Background

As technology advances, people's requirements for beauty are gradually increasing, which is why there are all kinds of models on the market.

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

(2) For example, vivo's high-end foldable screen mobile phone provides a better visual experience and is a foldable screen model.

(3) For example, vivo pad has excellent operating feel and high-end texture, and is a tablet model.

1.2 Our Challenge

Before this, we mainly provided services for candy-bar phones. Our development only needed to adapt to this mainstream candy-bar machine. Our UI mainly designed the renderings of this candy-bar phone. Our products and operations mainly selected materials for this type of candy-bar model.

But with the emergence of all kinds of models, the question arises:

  • The adaptation cost for developers is high. Do they need to make a separate application for adaptation for each model?
  • UI designers have to make a lot of renderings. Do they need to design a set of renderings for each model?
  • The materials that products and operations need to choose from are more restricted. Will the material work properly on one machine but not on another?

Why do I say so? Below I will introduce it from the developer's perspective and explain the problems we face.

2. Developer’s Dilemma

2.1 The cost of adapting all models is too high

The increasing number of device models makes us Android developers busy. Although we can adapt according to the requirements, the cost of adapting to large-screen models is still relatively high, because these models are different from the traditional candy-bar phones in aspect ratio (9:16). Therefore, some applications simply leave blank spaces on both sides and display the content area in the center of the screen. Of course, this effect is very poor.

Case 1: A video APP page is not adapted for the pad. The effect after opening is as follows. There is a lot of white space on both sides, which are inoperable areas.

Case 2 : The adaptation effect of a news and information APP 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 Why is the cost of full-model adaptation high?

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

Then there are the problems that need to be solved:

3. Journey to find a solution for all models

3.1 Discussion and determination of the plan

Page stretching and blank space on the left and right are phenomena, which are also the direct experience of users. So this is where we need to improve, so now we have a direction, focusing on "how to display more information in the visible area". This is not a simple rearrangement of the layout, because the solution is definitely not something that can be implemented by the development alone. An apk carries the function to the user and involves the intervention of multiple roles. Product managers need to organize requirements, operators need to configure materials, release apks, testers need to test, etc., so the final solution is not determined by one party, but a result of coordination and unification.

Since we are going to discuss the plan, we must have a basis, so we will omit the process of discussion, review and finalization here.

Let’s first take a look at the external outlines of the straight screen, folding screen, and pad to understand the page shape.

3.2 Schematic diagram of the implementation of the solution

The content to be displayed in each application is different, but the principle is the same. Here we will introduce the principle based on the following styles. The principle is also relatively simple, showing as much content as possible and avoiding 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 the full-screen mode. Therefore, you can choose to only adapt to the full-screen mode, which has a lower adaptation cost. Of course, this also depends on the situation of your own module. For example, WeChat is more suitable for the split-column mode of the left and right screens.

3.2.1 Skeleton diagram of the candy-bar model adaptation solution

The candy-bar model is the current mainstream model, and its aspect ratio is basically 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 foldable screen model adaptation solution

For folding screen models, the screen can be rotated, but the aspect ratio is basically 1:1. The height is basically the same as that of a straight-screen machine, which can reach 2000px. Therefore, in the vertical direction, it can also 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.3 PAD model adaptation solution skeleton diagram

The screen of the pad tablet can be rotated, and the aspect ratio after rotation is quite different. In portrait orientation, the aspect ratio is 5:8, and in landscape orientation, the aspect ratio is 8:5.

When the pad is in portrait orientation, the height pixels are actually enough to display a lot of content, such as the images of module 1, module 2, and module 3 in the following figure;

However, when the pad is in landscape orientation, there is no way to display more content (there is a solution, which I will talk about at the end), and we can only see the pictures of module 1 and module 2 as shown below.

3.3 Solution Implementation Specifications

3.3.1 One set of code 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 display vertically, while a folding screen and pad support horizontal and vertical screen rotation.

The description is as follows:

(1) Demand

  • Candy bar screen: force the screen to be fixed in vertical position;
  • Folding screen: the outer screen is fixed in vertical orientation, and the inner screen (large screen) supports switching between horizontal and vertical orientations;
  • PAD side: support horizontal and vertical screen switching;

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

(2) Switching between horizontal and vertical screens

There are two methods:

Method 1)

By setting in AndroidManifest.xml:

android:screenOrientation attribute

a) android:screenOrientation="portrait"

Force vertical screen;

b) android:screenOrientation="landscape"

Force horizontal screen;

c) android:screenOrientation="unspecified"

The default value is that the screen can be switched between horizontal and vertical orientations;

Method 2)

Set in code:

activity.setRequestedOrientation(****);

a) setRequestedOrientation

(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); Set the screen to vertical orientation;

b)setRequestedOrientation

(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); Set the screen to horizontal orientation;

c)setRequestedOrientation

(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); The screen can be switched between horizontal and vertical orientations;

(3) Different devices support different screen orientations

1) Straight screen:

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

2) Folding screen:

The external screen is consistent with the candy-bar screen, so we won't discuss it for now. However, the internal screen (large screen) must support switching between horizontal and vertical screens. If it is a set of code, it is obviously impossible to implement it through the AndroidManifest file. Here, the system framework has actually helped us implement the logic of horizontal and vertical screens for the corresponding internal screen. In summary, the folding screen can be consistent with the candy-bar 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 switching between horizontal and vertical screens.

3) PAD end:

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

We set setRequestedOrientation in the base class of Activity

(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED), and found that it can indeed make the current page freely switch between horizontal and vertical screens. But there was a problem when starting the activity. When we started an acitivity interface B from the horizontal screen A interface, we found that the B interface was first vertical and then switched to horizontal (as shown in Figure 1). After trying many times, it was still the same. The visible switching process obviously could not meet our needs. This shows that the technical direction of dynamically adjusting the horizontal and vertical screens through Java code is not feasible. In summary, the mutually exclusive needs of the PAD end and the straight screen cannot be met through the same code.

Are there any other ways? Don't forget that our entire Android packaging process is completed through gradle. Can we use aspect programming thinking to create different packages for different devices?

The plan has been finalized and technical verification is being carried out here.

One of the important steps of gradle compilation is to merge the AndroidManifest files in the dependent aar and 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 android:screenOrientation field value in the temporary file after the AndroidManifest file is merged, and save it back after the modification is completed. In this way, a separate apk file can be printed for the pad end.

The core code is as follows:

 //pad supports horizontal and vertical screen
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 apk files

So far, the Java code is exactly the same, there is no difference. The key lies in whether the framework provides the ability to ignore screenOrientation. If it does, we only need to output one apk to adapt to all models.

If we don't have this capability, we need to use gradle to generate an additional apk to meet the rotatable requirements.

3.3.2 One set of materials for all models

1. Enlarge the material proportionally

According to the requirements of the above implementation plan, the display effect of the pictures in module 2 is different, as shown below:

  • On a candy-bar phone, Module 2, Picture 1, is on top, Pictures 2 and 3 are on the lower left and lower right corners
  • On the folding screen or pad, the picture 1 of module 2 is on the left, and the pictures 2 and 3 are on the right.
  • The pictures of the folding screen and the module 2 on the pad have been adjusted in style compared to the candy-bar phone, with the top and bottom styles changed to left and right. The pictures have also been enlarged accordingly to ensure that they can fill the entire width of the screen horizontally.

  • To visually represent the effect after processing, please look at the schematic diagram below.

2. Cutting materials without changing height

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

  • On a candy-bar phone, the height of Image 1 in Module 3 is 300px.
  • On a foldable screen or pad, the height of Image 1 in Module 3 is also 300px, but the content cannot be reduced.
  • The solution is to provide an original large image, if the specification is 2400px*300px, and crop it left and right on a candy-bar phone, as shown in the figure below. It can be directly displayed on the folding screen and pad. The cropping step is done on the server side, because it is time-consuming to do it on the client side.

  • To visually represent the effect after processing, please look at the schematic diagram below.

3.3.4 No-Sensing Refresh

Seamless refresh is mainly reflected in the switching of the inner and outer 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 or rotating?

  • This requires preparing the data source in advance to ensure immediate notification when the page changes.
  • It is best to use recyclerview for our page list because recyclerview supports partial refresh.
  • The data source drives the UI. Never judge the model at the UI level and do dynamic calculations on the UI. Otherwise, the page will flash and the user experience will be bad.

3.4 Practical implementation of the solution

The above introduces the adaptation specifications of different models. Now that there is no doubt about this, let’s take a look at how to implement it through cases.

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

3.4.1 How to design UI

As shown in the figure, one can intuitively feel that from a straight-screen mobile phone to a folding screen inner screen and then to a horizontal screen of a Pad, when the display area of ​​the device increases, the page makes full use of the space to display more product information.

3.4.2 Differentiating between different devices

Through the previous brief introduction, you have some understanding of the overall layout of the purchase page and the UI display on different devices. Now let’s see how to adapt a set of codes to multiple devices.

The first step is to distinguish different devices.

Before distinguishing different devices, let’s first look at what information can be obtained from the device?

  • Resolution
  • model
  • The horizontal and vertical state of the current screen

Let me first state the conclusion:

  • Candy-bar phones: differentiated by resolution
  • Folding screen: distinguished by model and internal and external screen status
  • Pad: Distinguish by the model and the horizontal or vertical state of the current screen

So here we provide a tool based on these characteristics.

How to distinguish different devices.

 /**
* @function Determine the screen type of the current mobile phone: There are currently three screen ranges: <= 528dp, 528 ~ 696dp, > 696dp, corresponding to normal straight-screen mobile phones, folding screen mobile phone inner screen and Pad vertical screen, and Pad horizontal screen
*/
public class ScreenTypeUtil {
public static final int NORMAL_SCREEN_MAX_WIDTH_RESOLUTION = 1584; // Normal candy-bar phone: maximum screen width resolution; Pad resolution (1600*2560), 1584 = 528 * 3, 528dp is the candy-bar phone range marked by the UI on the featured page
public static final int MIDDLE_SCREEN_MAX_WIDTH_RESOLUTION = 2088; // Folding screen phone: maximum screen width resolution (1916*1964, rotation: 1808*2072), 2088 = 696 * 3, 2088dp is the folding screen expansion range marked by the UI on the featured page
public static final int LARGE_SCREEN_MAX_WIDTH_RESOLUTION = 2560; // Large screen device: the screen width is temporarily set to the height of the Pad
public static final int NORMAL_SCREEN = 0; // Normal straight screen
public static final int MIDDLE_SCREEN = 1; // Folding screen phone inner screen unfolded, Pad vertical screen
public static final int LARGE_SCREEN = 2; // Pad horizontal screen
public static int getScreenType() {
Configuration configuration = BaseApplication.getApplication().getResources().getConfiguration();
return getScreenType(configuration);
}
// Note that the newConfig here is passed in from the newConfig obtained in onConfigurationChanged in Activity, Fragment, and View. If you cannot get this value, you can use the getScreenType() method
public static int getScreenType(@NonNull Configuration newConfig) {
// Pad determines the current screen type by the model flag and the current horizontal or vertical screen state
if (SystemInfoUtils.isPadDevice()) {
return newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ? LARGE_SCREEN : MIDDLE_SCREEN;
}
// The Fold screen determines the current screen type based on the model logo and the status of the inner and outer screens.
if (SystemInfoUtils.isFoldableDevice()) {
return SystemInfoUtils.isInnerScreen(newConfig) ? MIDDLE_SCREEN : NORMAL_SCREEN;
}
// Ordinary mobile phones judge by resolution
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 changes

  • For candy-bar phones, the purchase page has only one state, which is to keep the vertical screen display
  • For folding screens, the folding screen can be switched from the inner screen to the outer screen, which involves switching between two different states.
  • For Pad, it supports switching between horizontal and vertical screens, so it also switches between two different states.

When the screen type, horizontal or vertical screen, or internal or external screen is switched, 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 candy-bar phones: because there is only one vertical screen state, only one set of data source is needed; for folding screens: Normal stores the data source of the outer screen of the folding screen, and Width stores the data source of the inner screen of the folding screen; for Pad: Normal stores the data source of the vertical screen state of Pad, and Width stores the data source of the horizontal screen state of Pad.

(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, prepare two sets of data sources first: one is Normal and the other is Width.

After requesting network data and 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: 2 product information are displayed in one row.
  • Folding screen - inner screen - floor 4: 3 product information are displayed in one row.

Note: The numbers 2 and 3 here are determined at the beginning of UI design. Each row of products is a RecyclerView, and GridLayoutManager is used to control its number of columns. Therefore, 2 and 3 are also the column values ​​passed to GridLayoutManager, and they must be kept consistent here.

Data source analysis of sub-floors

 //The normalProductMultiClassifyUiBeanList collection here stores information about two products
for (ProductMultiClassifyUiBean productMultiClassifyUiBean : normalProductMultiClassifyUiBeanList) {
productMultiClassifyUiBean.setFirstFloor(isFirstFloor);
shopListDataWrapper.addNormalBaseUiBeans(productMultiClassifyUiBean);
}
//The normalProductMultiClassifyUiBeanList collection here stores information about three products
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 outer screen of the folding screen switches to the inner screen. At this time, the Fragment will use the onConfigurationChanged method.

Screen type switch - data source switch - update RecyclerView.

 public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//1. First, check if the RecyclerViewAdapter and data source in the content area are empty
if (mRecyclerViewAdapter == null || mPageBeanAll == null) {
return;
}
//2. Determine the current screen type. Note: This is where the method provided by 3 is called: ScreenTypeUtil.getScreenType(newConfig)
// Bar phone, foldable screen external screen
if (ScreenTypeUtil.NORMAL_SCREEN == ScreenTypeUtil.getScreenType(newConfig)) {
mPageBeanAll.setBaseUiBeans(mPageBeanAll.getNormalBaseUiBeans());
} else if (ScreenTypeUtil.MIDDLE_SCREEN == ScreenTypeUtil.getScreenType(newConfig)) {
if (SystemInfoUtils.isPadDevice()) {
//Pad vertical screen
mPageBeanAll.setBaseUiBeans(mPageBeanAll.getNormalBaseUiBeans());
} else {
// Inner screen of folding screen
mPageBeanAll.setBaseUiBeans(mPageBeanAll.getWidthBaseUiBeans());
}
} else {
//Pad's horizontal screen, large resolution screen
mPageBeanAll.setBaseUiBeans(mPageBeanAll.getWidthBaseUiBeans());
}
//Get the latest data source for the current screen type
mRecyclerViewAdapter.setDataSource(mPageBeanAll.getBaseUiBeans());
//Data source drives floor UI changes
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.

4. The Path to Ultimate Simplicity

The simplest way is to follow the standards and principles, and you can think of how to adapt to multiple models without getting bogged down in details.

With this as a guideline, many other adaptations can be done. Here are some examples, but I won’t explain how to implement them.

1. Enlarge the text display area

As shown in the figure below, the length of the title changes as the width of the entire container becomes wider, ensuring that the length of the content can change adaptively.

2. Compatibility of pop-up 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 originally displayed content may be blocked. The solution here is to allow the content area to slide up and down.

3. Camera position processing

As shown in the figure below, after the screen rotates, the camera can appear in the lower right corner. If the page is not set at this time, the content area may not occupy the entire screen area, and the experience is poor. The solution here is to set the page to immersive so that the camera can reasonably cover part of the content.

5. Are we free from trouble?

5.1 Solve the original problem

Through the previous introduction, we know that the team of vivo 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 for developers is high. Do they need to make a separate application for each model?

Answer: According to the design plan of full-screen mode, folding screens and pads are just large-sized machines. Developers can judge the resolution and size of the model and choose a corresponding layout to display it. All it takes is one application.

(2) UI designers have to make a lot of renderings. Do they need to design a set of renderings for each model?

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

(3) The materials that can be selected for products and operations are more restricted. Is it possible that a material works properly on one machine but not on another?

Answer: You can adapt to changes by staying constant. You can use one set of materials to adapt to different models. You don’t have to worry about inconsistent display on different machines.

5.2 What else can we do

5.2.1 Our advantages

Folding screen and pad devices have been on the market for a long time. 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 maintenance costs, and subsequent development will have to be based on multiple installation packages, which is more time-consuming.

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

For example, some apps have adapted for split columns but not for full screen, so the effect is relatively poor. The input-output ratio may also be taken into consideration here.

3. The current adaptation guidance documents are not very instructive for developers.

Various adaptation guidance documents are still more official. For developers, it is still impossible to identify problems in advance. When problems arise, they still have to solve them in practice.

Based on this, our advantages are as follows:

1. We only have one installation package.

We have an installation package that is compatible with all models. Although the APP display style of each model is different, for developers, it is just adding a style, and the thinking is clearer.

2. Full-scenario adaptation.

The vertical and horizontal screen switching of different models is perfectly adapted. One of our features is that one set of materials is suitable for all models.

3. Provide targeted adaptation solutions.

This solution is based on the problems encountered in actual development. It can help developers solve actual problems and has a better reference value.

5.2.2 What else can we improve

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

<<:  Use these UI experience optimization techniques to make your designs more advanced!

>>:  Application of workflow engine in vivo marketing automation

Recommend

More than 1 million degrees! Why is it hotter the farther away from the sun?

The farther away from a heat source, the cooler t...

In-depth analysis of the Douyin algorithm mechanism

There are thousands of ways to play Tik Tok . It ...

Ten rules for open source success

[[151765]] Everyone wants it, and many are trying...

Goodbye WeChat! My WeChat chat history is not worth 180 yuan

Saving and migrating WeChat chat history has alwa...