SoFunction
Updated on 2025-04-04

Various tips for real-time preview and writing of Android UI

1. Long-winded

Some readers have previously reported that you have done this so-called best practice and each article is given a library at the end, which doesn’t feel very high-end. Actually, I thought about this question when I first wrote this series. My goal is to give the most practical library to help us develop, and to explain as much as possible how this library is written, hoping that start-up programmers can write less code that leaves tricks for future generations (I believe everyone has a deep understanding of this).

The libraries I gave before are very simple and basic, and basically you can understand them at first glance (but they are exquisite enough). If future articles involve complex libraries, I will specifically attach a library explanation article.

If you know the principles of a library, in addition, this library is easy to expand and maintain, and it also uses a lot of best practice experience, why don't you try it? The significance of the program is to record the excellent thinking and rich experience of predecessors, so that users can easily stand on the shoulders of giants. Its meaning is even comparable to the inheritance of the wisdom of our ancestors through DNA, and it is a subversive existence. If I just share a lot of experience I have gained in practice, this is not a program, but education!
Unfortunately, I can only wrap a lot of things that have chapters to follow as libraries, and the messy technique of debugging UI can only be recorded through articles, so this article was produced.

2. Requirements

Many beginners have heard their predecessors say that the layout of Android Studio (hereinafter referred to as as) is powerful in real-time preview, but when we actually use As, we will find that many interfaces are like this when previewing:

Or it's like this

Even this is:

At this time, whoever tells me that as can allow you to write UI in real time will fight with whom I will be. (┬_┬)
In fact, this is not as's fault, but the fault of the developer (including Google's developers). Because many developers do not pay attention to real-time UI display, everything is based on the results of real-time machine operation as the judgment criteria, resulting in many interfaces that cannot be previewed but can run. In many projects, an effect that could have been seen in one second ultimately takes a long process (compile->run->install->display) to be seen by us. I have to say that this is anti-human, which greatly reduces the development efficiency of Android programmers, destroys the development mood (I pay great attention to the development mood), and makes the powerful preview function of as the inaction. So, since the official is ineffective, we can only do it ourselves! Let’s talk about solutions and techniques for how to make your UI debugging in real time.

3. Principles and skills

3.0 Guiding Principles

Put the one-time attributes into the XML and put the attributes that need to be changed according to the program operation into the Java code.

Thanks to the previewability of the layout file (even if a control is not previewable, we should make it support preview, as the solution will be given below), we can boldly write XML layout without worrying about the problem of difficulty in positioning after maintenance. Just putting dynamically changing things into Java code can separate mutable and immutable code, thereby essentially tending to design pattern principles. In the future writing process, you will find that the code automatically generates a lot of optimization space and has also been greatly enhanced in readability.

3.1 Use less merge tags

Many articles say that to avoid deepening the hierarchy, please use the merge tag, but I say that you can use it less. There are two reasons: 1. The merge tag will cause the relationship between each element in the layout to be confused and the ui position cannot be displayed accurately (during preview). 2. The automatic code prompt function of as will be lost in the merge tag, making writing difficult.
These two points are extremely fatal for real-time preview of the UI, so it is recommended to use linearLayout and other viewgroups to make the root layout first, and then use merge to replace it after writing it. I'm not saying that the merge tag is not good, the design idea of ​​the merge tag is great, I just want to point out the problem. Unfortunately, there are no other good solutions to these two problems at present. We can only wait for the official improvement of the IDE and the addition of tools functions.

【Make complaints】

A great merge tag is awkward by these two factors, which is really sad. There is also the namespace of tools that are incompatible with it.

3.2 Multi-use tools properties

xmlns:tools="/tools"It is a very important and very useful namespace. It has all the properties in Android:, but the properties it identifies are only valid in the preview and will not affect the real running results.

For example:

  <TextView
    android:text="Footer"
    android:layout_width="wrap_content"
    android:layout_height="100dp"
    />

This is our previous writing method, which uses android: to identify the text attribute of the textView. What if we want the text of this textview to be controlled in real time in the code, the default is that there is no text? This requires the help of tools.

<TextView
    tools:text="Footer"
    android:layout_width="wrap_content"
    android:layout_height="100dp"
    />

Replace Android on the first line with tools so that you can see the effect in the preview without affecting the actual running result of the code. Because the attributes marked by tools will be ignored during actual operation. You can fully understand that it is a test environment, which is completely independent of the real environment and will not have any impact.

【Make complaints】

The tools tag does not support code prompts, and its own attributes cannot be prompted. They all rely on their own memory, or use Android first instead, and then replace Android with tools. For such a long time, Google seems to have ignored it, which also confirms that Google programmers are not very interested in real-time previewing layouts.

3.3 Use tools to make listview support real-time preview

In the previous code, we always wrote a listview like this and then figured out what the item was put into.

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:andro
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  />

Now we can use tools to preview the item's appearance, like this:

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:andro
  xmlns:tools="/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:listheader="@layout/demo_header"
  tools:listitem="@layout/demo_item"
  />

Is it much better?

Using these two properties of tools allows us to avoid blindly writing the UI, and can also give the design a very intuitive display.

3.4 Use the drawableXXX attribute to make controls with pictures and texts

Both textview and its subclasses have properties such as drawableLeft, drawableRight, etc., and these properties allow us to easily create graphics and text controls. drawablePadding can set the spacing between pictures and texts, but unfortunately there are no attributes such as drawableLeftPadding. For example, we want to make a control with icons on both sides and centered text:


<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:andro
  xmlns:tools="/tools"
  android:layout_width="match_parent"
  android:layout_height="50dp"
  android:textAppearance="?android:attr/textAppearanceListItemSmall"
  android:gravity="center_vertical|center_horizontal"
  android:drawableLeft="@drawable/demo_tab_home_selector"
  android:drawableRight="@drawable/demo_tab_home_selector"
  android:drawablePadding="10dp"
  android:text="ddd"
  android:textSize="20sp"
  />

At this time, if you want to adjust the text position, you only need to modify the value of gravity.

The common controls of our (text + arrow) can be made as follows:

&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;TextView xmlns:andro
  xmlns:tools="/tools"
  android:layout_width="match_parent"
  android:layout_height="60dp"
  android:padding="16dp"
  android:textAppearance="?android:attr/textAppearanceListItemSmall"
  android:gravity="center_vertical"
  android:drawableRight="@drawable/icon_arrow"
  android:drawablePadding="10dp"
  android:text="Settings Menu"
  android:textSize="20sp"
  /&gt;

3.5 Use space and layout_weight to take up the place

Sometimes our needs are very complicated. We hope that multiple controls in a linearLayout are scattered on both sides, because the controls inside linearLayout can only be arranged in order. To complete this effect, space must be used.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:andro
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="horizontal"
  android:gravity="center_vertical"
  android:padding="12dp"
  >
  <TextView
    android:layout_width="wrap_content"
    android:layout_height="100dp"
    android:gravity="center"
    android:text="Header"
    android:textSize="40sp"
    />
  <Space
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    />
  <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/tab_icon_home"
    />
</LinearLayout>

Let me give you another common example:

We want to make a main page with the viewpager above and the tab column at the bottom. This kind of page cannot be done if you just use linearLayout, but it can be easily completed if you use layout_weight.

<LinearLayout xmlns:andro
  xmlns:app="/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  >
  <
    android:
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1.0"
    />
  <
    android:
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />
</LinearLayout>

Key Code:

Copy the codeThe code is as follows:

    android:layout_height="0dp"
    android:layout_weight="1.0"


3.6 Modify native controls to support real-time preview

As mentioned above, many native Android controls are not optimized for real-time previews, let alone third-party ones. In recent projects, I encountered the need to use tabLayout as the main interface tab column. However, the coupling of the tablayout designed by Google is too high. It relies on a viewpager, which relies on adapters, and adapters rely on data. So there is no way to debug a tablayout independently. So I modified its code to support real-time preview of the layout. The main thing is to add the following code:

private void preview(Context context, TypedArray a) {
    final String tabStrArr = (.ExTabLayout_tools_tabStrArray);
    final String[] tabRealStrArr = getTabRealStrArr(tabStrArr);
    ViewPager viewPager = new ViewPager(context);
    (new PagerAdapter() {
      @Override
      public int getCount() {
        return ;
      }
      @Override
      public boolean isViewFromObject(View view, Object object) {
        return view == object;
      }
      @Override
      public CharSequence getPageTitle(int position) {
        return tabRealStrArr[position];
      }
    });
    (0);
    (viewPager);
  }

Don't you want a viewpager? I'll give you a viewpager. Don't you want an adapter, I'll give you an adapter. You also want data, so I will give you data. It is worth noting that if your code is for real-time preview and does not want to have any impact on the real code, then be sure to use isInEditMode() method, for example, the above code is called like this:

  // preview
  if (isInEditMode()) {
    preview(context, a);
  }

Let's take a look at the effect now:

This method of modifying native controls to support preview is not very advanced. You can use similar ideas to transform controls that are difficult to preview.

3.7 Dynamic preview through plug-ins

We all know that as's layout preview only supports static preview, and we cannot interact with the preview interface, so we cannot test the sliding effect and click effect. So I found the plugin jimu mirror to support dynamic previews. After starting mirror, it will install an apk on your phone. This apk displays your current layout page. mirror will listen to changes in the xml file. If the xml file changes, it can refresh the layout immediately. Let's show how I preview the viewpager with its support.

1. First add this code to the viewpager

private void preview(Context context, AttributeSet attrs) {
    TypedArray a = (attrs, );
    List&lt;View&gt; viewList = new ArrayList&lt;&gt;();
    int layoutResId;
    if ((layoutResId = (.ExViewPager_tools_layout0, 0)) != 0) {
      (inflate(context, layoutResId, null));
    }
    if ((layoutResId = (.ExViewPager_tools_layout1, 0)) != 0) {
      (inflate(context, layoutResId, null));
    }
    if ((layoutResId = (.ExViewPager_tools_layout2, 0)) != 0) {
      (inflate(context, layoutResId, null));
    }
    if ((layoutResId = (.ExViewPager_tools_layout3, 0)) != 0) {
      (inflate(context, layoutResId, null));
    }
    if ((layoutResId = (.ExViewPager_tools_layout4, 0)) != 0) {
      (inflate(context, layoutResId, null));
    }
    ();
    setAdapter(new PreviewPagerAdapter(viewList));
  }
  /**
    * @author Jack Tony
    * Here is a list array, and a view can be stripped from each list and displayed.
    * @date :2014-9-24
    */
  public static class PreviewPagerAdapter extends PagerAdapter {
    private List&lt;View&gt; mViewList;
    public PreviewPagerAdapter(List&lt;View&gt; viewList) {
      mViewList = viewList;
    }
    @Override
    public int getCount() {
      return ();
    }
    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
      return arg0 == arg1;
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
      if ((position) != null) {
        ((position));
      }
    }
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
      ((position), 0);
      return (position);
    }
  }

The above work is to support the layout of the page in the viewpager in XML to achieve the preview function.

2. Write an XML layout file

<
    android:
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1.0"
    android:scrollbars="none"

    app:scrollable="true"
    app:tools_layout0="@layout/demo_fragment01"
    app:tools_layout1="@layout/demo_fragment02"
    app:tools_layout2="@layout/demo_fragment01"
    />

Finally, run the plug-in and see the effect:

4. Quick preview plug-in

The above mentioned using jimu mirror to make real-time preview of the UI. For more preview skills, you can browse on their website. Mirror does a real-time replacement of static XML files, allowing developers to see the UI interface in real-time machines. Interested friends can try the experience version of Mirror. After I experienced it, I felt its power and convenience. Because the experience lasted for dozens of days, I had to become a paid user. The most lovely of these is that it supports the properties of the tools tag and supports real-time previewers that are stronger than as.

Similar to jimu mirror, there is also jrebel. This thing is even more powerful. It not only makes the UI interface refresh in real time, but it even allows you to replace the class files in the apk in real time after changing the java code to achieve real-time refresh of the application. I think it uses hot replacement technology. The official website introduction is: Skip build, install and run, so it can save us a lot of time and its effect is also very good.
The focus of jrebel and mirror are different. It focuses on shortening the overall debugging time of the application and still takes the route of real machine results. The purpose of mirror is to allow developers to preview the UI in real time, and it is taking the route of independent UI testing. Overall, these two plug-ins are pretty good, which is simply a slap in the face of the official. But because jrebel is too expensive, I still recommend everyone to use mirror.

5. Summary

This article is indeed quite long and takes a lot of effort. I still feel that the official programmer's thinking is too heavy on designing and optimizing IDEs, and it still brings too little convenience to developers. The tools tag has no code prompts, and the official controls are not previewable and other problems also make it difficult for developers to quickly debug UI. Today, when MVP, MVVM and other modes are popular in Android, independent UI testing has become particularly important. I don’t want everyone to install and run the apk every time they debug the UI, and I don’t want to see the real-time preview function of as become useless.

Anyway, thank you for reading to the end. If you have other UI debugging skills, please point it out. If you find the skills proposed in this article useful, please try it.
I wish you all a happy Double Eleven~