github_DPScreenAdaptation

APKdemo

@[toc]

Xiaobian has tried two screen adaptation methods:

1 PX adaptation

Use PXGenerator code to generate folders and files of various resolutions. Take a certain resolution such as 480×800 as the benchmark,1px= 1px, and generate dimen files of other resolutions in proportion, such as 1px=4px,1px=3px, so as to achieve the purpose of screen adaptation

<dimen name="py11"> 14.7 px < / dimen > < dimen name ="py12"> 16.0 px < / dimen > < dimen name ="py13"> 17.3 px < / dimen > < dimen name ="py14"> 18.7 px < / dimen > < dimen name ="py15"> 20.0 px < / dimen > < dimen name ="py16"> 21.3 px < / dimen > < dimen name ="py17"> 22.7 px < / dimen > < dimen name ="py18"> 24.0 px < / dimen > < dimen name ="py19"> 25.3 px < / dimen > < dimen name ="py20"> 26.7 px < / dimen > < dimen name ="py21"> 28.0 px < / dimen > < dimen name ="py22"> 29.3 px < / dimen > < dimen name ="py23"> 30.7 px < / dimen > < dimen name ="py24"> 32.0 px < / dimen > < dimen name ="py25"> 33.3 px < / dimen > < dimen name ="py26"> 34.7 px < / dimen > < dimen name ="py27"> 36.0 px < / dimen > < dimen name ="py28"> 37.3 px < / dimen > < dimen name ="py29"> 38.7 px < / dimen >Copy the code
public class PXGenerator {
	
	private static final String HEAD="
      \n"; // Header private static final String START_TAG="<resources>\n"; // Start tag private static final String END_TAG="</resources>\n"; Private static Final String ROOT="F:\\AndroidStudioWorkSpace\\ScreenAdaptation\\app\\src\\main\\res\\values-2560x1800\\"; Private static final String FILE_NAME="dimen_py2560.xml"; // File name private static final String path=ROOT+FILE_NAME; // File path private static finalfloatTIMES = 1920 * 1.0 f / 2560; private static final int DIMENSION=1920; Public static void main(String[] args) {generateXMl(); } private static voidgenerateXMl()
	{
		try 
		{
			File diectoryFile = new File(ROOT);
			if(! diectoryFile.exists()){ diectoryFile.mkdirs(); } File file = new File(path);if(file.exists()){
				file.delete();
			}
			FileWriter fileWriter = new FileWriter(file);
			fileWriter.write(HEAD);
			fileWriter.write(START_TAG);
			for(int i=0; i<=DIMENSION; i++){ String output="\t<dimen name=\"py"+i+"\" >"+roundString(i)+"px</dimen>\n";
				fileWriter.write(output);
			}
			fileWriter.write(END_TAG);
			fileWriter.flush();
			fileWriter.close();
			
			System.out.println("Write succeeded");
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("Write failed");
		}
	}
	
	private static String roundString(int data)
	{
		String result="";
		float floatResult=data/TIMES;
		DecimalFormat df = new DecimalFormat("0.00");
		result = df.format(floatResult);
		returnresult; }}Copy the code

Disadvantages: Too many dimen with relevant resolution need to be generated, which increases the size of APK package

2. Origin of DP adaptation

Reference CSDN adu, write a good thief, help a thief, thief thanks

Familiarize yourself with the parameters shown below

 private String getScreenParams() { DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int heightPixels = dm.heightPixels; // High pixels int widthPixels = dm.widthPixels; Int densityDpi = dm.densityDpi; //dpifloatxdpi = dm.xdpi; //xdpifloatydpi = dm.ydpi; //ydpifloatdensity = dm.density; / 160 / / density = dpi, density ratiofloatscaledDensity = dm.scaledDensity; //scaledDensity=dpi/160 font density ratiofloatheightDP = heightPixels / density; // Height dpfloatwidthDP = widthPixels / density; // width dp String STR ="heightPixels: " + heightPixels + "px";
        str += "\nwidthPixels: " + widthPixels + "px";
        str += "\ndensityDpi: " + densityDpi + "dpi";
        str += "\nxdpi: " + xdpi + "dpi";
        str += "\nydpi: " + ydpi + "dpi";
        str += "\ndensity: " + density;
        str += "\nscaledDensity: " + scaledDensity;
        str += "\nheightDP: " + heightDP + "dp";
        str += "\nwidthDP: " + widthDP + "dp";

        return str;
    }
Copy the code

1. P:

Screen resolution: the number of pixels in horizontal and vertical. Unit: px= 1px=1 pixel point. It is usually represented by vertical pixels x horizontal pixels, such as 1920×1080

2.dpi:

Screen pixel density, refers to the number of pixels per inch, short for dot per inch, related to screen size and screen resolution. Take the Nexus5 for example. The official parameter is 1920*1080,dpi=445, 4.95 inch. As can be seen from the above, screen size 4.95 is the diagonal length of the screen, while DPI refers to the number of pixels per inch, so it should be divided by the diagonal pixel value by 4.95, as follows:

3.dp/dip:

Dp is the same as DIP, Density Independent Pixels, based on 160dpi. 1dp=1px on a 160dpi device, 1DP =1.5px on a 240dpi device, and so on

Density: density= Dpi /160, density ratio

5. ScaledDensity: scaledDensity= DPI /160 font zoom density ratio

6. HeightDP: heightDP = heightPixels/density; // Height dp

7. WidthDP: heightDP = widthPixels/density; // Width dp

Refer to the Android official website, the official website tells us how to adapt

Sw < N >dp: smallestWidth

There are several dimensions available officially, sw refers to the minimum width, regardless of portrait or landscape:

Such as 800DPx480DP(minimum width is 480DP, such as some 800×480 mobile phones), 592DPx360DP(minimum width is 360DP, Like some 1920×1080 phones), 604DPx360DP(minimum width is 360DP, like some 1920×1080 phones), 680DPx360DP(minimum width is 360DP). For example, some 2160×1080 mobile phones (long screen mobile phones and bang-screen mobile phones became popular around 2018), 1232DPx900DP(the minimum width is 900DP, such as some 2560×1800 mobile phones (tablets))

It is found here that the minimum width of mobile phones with various resolutions is 360DP, especially 1920×1080, which is the most popular screen resolution around 2018. Therefore, it is considered to make adaptation based on the width of 360DP (this is why DP adaptation is used instead of PX adaptation, because DP adaptation requires much less DIMens files).

Sw < N > DP will be compatible upward:

For example, the valuse-SW481dp directory will search for the value only when the minimum width of the phone dp>=481dp. The minimum width of 800DPx480DP is 480dp. Therefore, the valuse-SW481dp directory cannot search for the value if there is no corresponding value in the values directory. Only one result GG=APP crashes. Be sure to create values in the values directory at all times

As mentioned above, the minimum width of mobile phones with various resolutions is 360DP, especially 1920×1080, which is the most popular screen resolution around 2018. Therefore, it is considered to adapt with the width of 360DP as the base

3.DP adaptation principle and specific operations

Common SWDP are as follows:

// private static final int[] dps = {360, 384, 392, 400, 410, 411, 480, 533, 592, // 600, 640, 662, 720, 768, 800, 811, 820,900, 960, 961, 1024, 1280}; // List of common DPSCopy the code

In order to fit as many phones as possible, the DP should contain as many as possible, and be highly continuous and spaced

Dp adaptation principle: Similar to PX adaptation principle (calculated in proportion), based on SW360DP,

 <dimen name="height_title">48dp</dimen>
    <dimen name="sp18">18sp</dimen>
    <dimen name="padding_icon">12dp</dimen>
    <dimen name="dp360">360dp</dimen>
    <dimen name="sp10">10sp</dimen>
    <dimen name="dp30">30dp</dimen>
    <dimen name="dp10">10dp</dimen>
    <dimen name="sp14">14sp</dimen>
    <dimen name="dp40">40dp</dimen>
    <dimen name="dp70">70dp</dimen>
    <dimen name="dp100">100dp</dimen>
    <dimen name="dp80">80dp</dimen>
    <dimen name="sp12">12sp</dimen>
    <dimen name="dp60">60dp</dimen>
    <dimen name="_dp10">-10dp</dimen>
    <dimen name="dp4_5"Dp > 4.5 < / dimen > < dimen name ="_dp5_5"Dp > 5.5 < / dimen >Copy the code

So sw720dp is as follows: all 2x values

<dimen name="height_title">96dp</dimen>
    <dimen name="sp18">36sp</dimen>
    <dimen name="padding_icon">24dp</dimen>
    <dimen name="dp360">720dp</dimen>
    <dimen name="sp10">20sp</dimen>
    <dimen name="dp30">60dp</dimen>
    <dimen name="dp10">20dp</dimen>
    <dimen name="sp14">28sp</dimen>
    <dimen name="dp40">80dp</dimen>
    <dimen name="dp70">140dp</dimen>
    <dimen name="dp100">200dp</dimen>
    <dimen name="dp80">160dp</dimen>
    <dimen name="sp12">24sp</dimen>
    <dimen name="dp60">120dp</dimen>
    <dimen name="_dp10">-20dp</dimen>
    <dimen name="dp4_5">9dp</dimen>
    <dimen name="_dp5_5">-11dp</dimen>
Copy the code

Specific operation:

1) Based on SW360DP and according to the UI design drawing of 1920×1080, designers can mark DP and SP with software such as “Biao You”, or upload it to Blue Lake, where the marking is more cool. Define the corresponding DImen label of DP value in dimens file under VALUES. For example, a button with a height of 40dp marked on the UI diagram is created in dimens file

<dimen name="height_btn_">40dp</dimen>
Copy the code

Name You can take any name you like

2) Put the following code classes under the app Module of the current Android project. Remember to change the root directory to your android project directory.

public class DPGeneratorLittle {

    private static final String HEAD = "
      \n"; // Header private static final String START_TAG ="<resources>\n"; // Start tag private static final String END_TAG ="</resources>\n"; End tag private static finalfloatDP_BASE = 360; Private static final int DP_MAX = 720; Private static final int SP_MAX = 48; private static final int SP_MAX = 48; Private static final int[] DPS = {360, 384, 392, 400, 410, 411, 480, 533, 592, 600, 640, 662, 720, 768, 800, 811, 820,900, 960, 961, 1024, 1280}; Private static final int[] DPS = {100,481,510,720,900}; private static final int[] DPS = {100,481,510,720,900}; // Common DP list private static final String root="F:\\AndroidStudioWorkSpace\\ScreenAdaptation\\app\\src\\main\\res\\"; Private static ExecutorService fixedThreadPool; Private static int size_thread = 5; // Thread pool size private static DocumentBuilderFactory dbFactory; private static DocumentBuilder db; private static Document document; public static void main(String[] args) { try { dbFactory = DocumentBuilderFactory.newInstance(); db = dbFactory.newDocumentBuilder(); Parse (root+); // Parse the content of the given URI into an XML Document and return the Document object"values\\dimens.xml"); / / return included in the document in document order with a given tag name all the Element of the NodeList NodeList dimenList = document. The getElementsByTagName ("dimen");
            if (dimenList.getLength()==0)return;
            List<Dimen> list = new ArrayList<>();
            for(int i = 0; i < dimenList.getLength(); I ++) {// Get the I book Node Node = dimenlist.item (I); NamedNodeMap = Node.getAttributes (); / / to get known, called the name of the attribute value String atrName = namedNodeMap. The getNamedItem ("name").getTextContent();

                String value = node.getTextContent();

                System.out.println("+++atrName++++++++++++++++++++" + atrName);
                System.out.println("+++++++++++++value++++++++++" + value);


                list.add(new Dimen(atrName, value));


            }


            fixedThreadPool = Executors.newFixedThreadPool(size_thread);

            for(int i = 0; i < dps.length; i++) { XMLThread xmlThread = new XMLThread(i, list); fixedThreadPool.execute(xmlThread); }} catch (SAXException e) {e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } } private static class XMLThread implements Runnable { private int index = 0; private List<Dimen> list; public XMLThread(int index, List<Dimen> list) { this.index = index; this.list = list; } @Override public voidrunGenerateXMl (list, index, root+) {// Remember to change your current project path to generateXMl(list, index, root+)"values-sw" + dps[index] + "dp\\"."dimens.xml");
        }
    }


    private static void generateXMl(List<Dimen> list, int index, String pathDir, String fileName) {
        try {
            File diectoryFile = new File(pathDir);
            if(! diectoryFile.exists()) { diectoryFile.mkdirs(); } File file = new File(pathDir + fileName);if(file.exists()) { file.delete(); } FileWriter fileWriter = new FileWriter(file); fileWriter.write(HEAD); fileWriter.write(START_TAG); / /????????????????????????????????????????????????????????????????????????? int size = list.size(); String atrName; String value;for (int i = 0; i < size; i++) {
                atrName = list.get(i).getAtrName();
                value = list.get(i).getValue();

                String output = "\t<dimen name=\"" + atrName + "\" >" +
                        roundString(Float.valueOf(value.substring(0, value.length() - 2)), index) +
                        value.substring(value.length()-2)+"</dimen>\n";
                fileWriter.write(output);

            }

            fileWriter.write(END_TAG);
            fileWriter.flush();
            fileWriter.close();

            System.out.println("Write succeeded");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Write failed"); }} // Round to 2 decimal places (SW1280dp = 160dp, 1dp=1px); // Round to 1 decimal place (SW1280dp = 4PX); // Round to 2 decimal places (SW1280dp = 160dp, 1dp=1px); Error within 1PX) private static String roundString(float data, int index) {
        String result = "";
        float floatResult = data * dps[index] / DP_BASE;
        DecimalFormat df = new DecimalFormat("0.00");
        result = df.format(floatResult);
        return result;
    }

    private static class Dimen {
        private String atrName;
        private String value;

        public Dimen(String atrName, String value) {
            this.atrName = atrName;
            this.value = value;
        }

        public String getAtrName() {
            return atrName;
        }

        public void setAtrName(String atrName) {
            this.atrName = atrName;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) { this.value = value; }}}Copy the code

Execute the main method of the utility class as shown in the figure to generate various DIMens files

3) Relevant principles and techniques used

1. The utility class parses dimens files in values directory and generates dimens files corresponding to other DP based on all dimen labels, name and values

2.DP_BASE can be modified to your own baseline (you can specify other DP according to actual situation, in general, define 360DP, because most mobile sw is 360DP)

3. Root corresponds to the home directory path of the current Android project. Do not make mistakes

4. Size_thread, the default thread pool size is 5, you can set other values

5. You can also change the style you like according to your own habits and preferences of OBSessive-compulsive disorder. The code is very simple and easy to modify

6. Execute DPGeneratorLittle’s main method to ensure that all dimen files are up to date before each package (if you need to debug a phone other than SW360DP, or launch an APP)

7 negative dp, decimal DP, even decimal SP (generally not this case) can be generated, rest assured bold use

8. If it is found that the adaptation effect of a mobile phone is not very good, then the real machine debugging, get its SWDP, and then generate the corresponding SWDP, DImen file with DPGeneratorLittle

9. If DPGeneratorLittle fails, delete all generated valuse directories, clean the project, and retry

4. Enjoy DP adaptation cases

800 pxx480px mobile phone

As you can see, the fit is good, and there are few unacceptable areas:

<? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/height_title"
        android:background="#1d953f"
        android:gravity="center_vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:layout_toRightOf="@+id/iv_back"
            android:gravity="center_vertical"

            android:text="Screen fit"
            android:textColor="#ffffff"
            android:textSize="@dimen/sp18" />

        <ImageView
            android:id="@+id/iv_back"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"

            android:padding="@dimen/padding_icon"
            android:scaleType="centerInside"
            android:src="@drawable/back" />


    </RelativeLayout>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp360">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="@dimen/dp360"
            android:layout_height="@dimen/dp360"
            android:layout_gravity="center_horizontal"
            android:scaleType="centerCrop"
            android:src="@drawable/rec" />

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:textColor="#fff"
            android:textSize="@dimen/sp18" />
    </FrameLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <View
            android:layout_width="@dimen/dp40"
            android:layout_height="@dimen/dp40"
            android:layout_marginLeft="@dimen/_dp5_5"
            android:background="# 436876" />

        <com.cy.screenadaptation.ViewCanMeasure
            android:id="@+id/view_bottom"
            android:layout_width="@dimen/dp60"
            android:layout_height="@dimen/dp60"
            android:background="#00f"
            android:gravity="center"
            android:textColor="#fff"
            android:textSize="@dimen/sp12" />

        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1" />


        <View
            android:layout_width="@dimen/dp4_5"
            android:layout_height="@dimen/dp40"
            android:layout_marginRight="@dimen/dp10"
            android:background="#00f" />

        <View
            android:layout_width="@dimen/dp40"
            android:layout_height="@dimen/dp40"
            android:layout_marginRight="@dimen/_dp10"
            android:background="#f00" />
    </LinearLayout>

</LinearLayout>

Copy the code
public class MainActivity extends AppCompatActivity {


    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = (TextView) findViewById(R.id.tv);


        tv.setText(getScreenParams());

    }

    private String getScreenParams() { DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int heightPixels = dm.heightPixels; // High pixels int widthPixels = dm.widthPixels; Int densityDpi = dm.densityDpi; //dpifloatxdpi = dm.xdpi; //xdpifloatydpi = dm.ydpi; //ydpifloatdensity = dm.density; / 160 / / density = dpi, density ratiofloatscaledDensity = dm.scaledDensity; //scaledDensity=dpi/160 font density ratiofloatheightDP = heightPixels / density; // Height dpfloatwidthDP = widthPixels / density; // width dp String STR ="heightPixels: " + heightPixels + "px";
        str += "\nwidthPixels: " + widthPixels + "px";
        str += "\ndensityDpi: " + densityDpi + "dpi";
        str += "\nxdpi: " + xdpi + "dpi";
        str += "\nydpi: " + ydpi + "dpi";
        str += "\ndensity: " + density;
        str += "\nscaledDensity: " + scaledDensity;
        str += "\nheightDP: " + heightDP + "dp";
        str += "\nwidthDP: " + widthDP + "dp";

        returnstr; }}Copy the code

** DP adapter advantages: ** Dimens files are few, does not affect the size of apK package, disadvantages: Before each package (if you need to debug a phone other than SW360DP, or launch an APP), you need to execute DPGeneratorLittle’s main method to make sure all the dimen files are up to date, which is a bit annoying

If you don’t want to worry, you can use the DPGenerator class github_DPScreenAdaptation to generate all possible DP and SP files, but this may add hundreds of KB files

Welcome to contact, correct, criticize and quarrel if you have any questions

GitHub

Common open source libraries for Android development

Jane’s book

Wechat official account

QQ group